Skip to content

Commit

Permalink
Merge pull request #14 from LilDrunkenSmurf/feat/bitwarden-cli
Browse files Browse the repository at this point in the history
Add new workflows for bitwarden-cli
  • Loading branch information
joryirving authored Jan 10, 2024
2 parents 65a2de0 + 8205ad4 commit 5c45247
Show file tree
Hide file tree
Showing 28 changed files with 1,120 additions and 12 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{bash,sh}]
indent_style = space
indent_size = 4
7 changes: 7 additions & 0 deletions .github/labeler.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
area/ci:
- changed-files:
- any-glob-to-any-file: ".github/**/*"
area/containers:
- changed-files:
- any-glob-to-any-file: "apps/**"
8 changes: 6 additions & 2 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
":enablePreCommit",
":automergeDigest",
":automergeBranch",
":label(renovate/{{depName}})",
"security:openssf-scorecard",
"github>LilDrunkenSmurf/containers//.github/renovate/autoMerge.json5",
"github>LilDrunkenSmurf/containers//.github/renovate/commitMessage.json5",
"github>LilDrunkenSmurf/containers//.github/renovate/labels.json5",
Expand All @@ -18,7 +20,9 @@
"dependencyDashboardTitle": "Renovate Dashboard 🤖",
"suppressNotifications": ["prIgnoreNotification"],
"rebaseWhen": "conflicted",
"schedule": ["every saturday"],
"assignees": [
"LilDrunkenSmurf"
],
"pre-commit": {
"enabled": true
},
Expand All @@ -31,4 +35,4 @@
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}"
}
]
}
}
191 changes: 191 additions & 0 deletions .github/scripts/prepare-matrices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#!/usr/bin/env python3
import importlib.util
import sys
import os

import json
import yaml
import requests

from subprocess import check_output

from os.path import isfile

repo_owner = os.environ.get('REPO_OWNER', os.environ.get('GITHUB_REPOSITORY_OWNER'))

TESTABLE_PLATFORMS = ["linux/amd64"]

def load_metadata_file_yaml(file_path):
with open(file_path, "r") as f:
return yaml.safe_load(f)

def load_metadata_file_json(file_path):
with open(file_path, "r") as f:
return json.load(f)

def get_latest_version_py(latest_py_path, channel_name):
spec = importlib.util.spec_from_file_location("latest", latest_py_path)
latest = importlib.util.module_from_spec(spec)
sys.modules["latest"] = latest
spec.loader.exec_module(latest)
return latest.get_latest(channel_name)

def get_latest_version_sh(latest_sh_path, channel_name):
out = check_output([latest_sh_path, channel_name])
return out.decode("utf-8").strip()

def get_latest_version(subdir, channel_name):
ci_dir = os.path.join(subdir, "ci")
if os.path.isfile(os.path.join(ci_dir, "latest.py")):
return get_latest_version_py(os.path.join(ci_dir, "latest.py"), channel_name)
elif os.path.isfile(os.path.join(ci_dir, "latest.sh")):
return get_latest_version_sh(os.path.join(ci_dir, "latest.sh"), channel_name)
elif os.path.isfile(os.path.join(subdir, channel_name, "latest.py")):
return get_latest_version_py(os.path.join(subdir, channel_name, "latest.py"), channel_name)
elif os.path.isfile(os.path.join(subdir, channel_name, "latest.sh")):
return get_latest_version_sh(os.path.join(subdir, channel_name, "latest.sh"), channel_name)
return None

def get_published_version(image_name):
r = requests.get(
f"https://api.github.com/users/{repo_owner}/packages/container/{image_name}/versions",
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": "token " + os.environ["TOKEN"]
},
)

if r.status_code != 200:
return None

data = json.loads(r.text)
for image in data:
tags = image["metadata"]["container"]["tags"]
if "rolling" in tags:
tags.remove("rolling")
# Assume the longest string is the complete version number
return max(tags, key=len)

def get_image_metadata(subdir, meta, forRelease=False, force=False, channels=None):
imagesToBuild = {
"images": [],
"imagePlatforms": []
}

if channels is None:
channels = meta["channels"]
else:
channels = [channel for channel in meta["channels"] if channel["name"] in channels]


for channel in channels:
version = get_latest_version(subdir, channel["name"])
if version is None:
continue

# Image Name
toBuild = {}
if channel.get("stable", False):
toBuild["name"] = meta["app"]
else:
toBuild["name"] = "-".join([meta["app"], channel["name"]])

# Skip if latest version already published
if not force:
published = get_published_version(toBuild["name"])
if published is not None and published == version:
continue
toBuild["published_version"] = published

toBuild["version"] = version

# Image Tags
toBuild["tags"] = ["rolling", version]
if meta.get("semantic_versioning", False):
parts = version.split(".")[:-1]
while len(parts) > 0:
toBuild["tags"].append(".".join(parts))
parts = parts[:-1]

# Platform Metadata
for platform in channel["platforms"]:

if platform not in TESTABLE_PLATFORMS and not forRelease:
continue

toBuild.setdefault("platforms", []).append(platform)

platformToBuild = {}
platformToBuild["name"] = toBuild["name"]
platformToBuild["platform"] = platform
platformToBuild["version"] = version
platformToBuild["channel"] = channel["name"]

if meta.get("base", False):
platformToBuild["label_type"] ="org.opencontainers.image.base"
else:
platformToBuild["label_type"]="org.opencontainers.image"

if isfile(os.path.join(subdir, channel["name"], "Dockerfile")):
platformToBuild["dockerfile"] = os.path.join(subdir, channel["name"], "Dockerfile")
platformToBuild["context"] = os.path.join(subdir, channel["name"])
platformToBuild["goss_config"] = os.path.join(subdir, channel["name"], "goss.yaml")
else:
platformToBuild["dockerfile"] = os.path.join(subdir, "Dockerfile")
platformToBuild["context"] = subdir
platformToBuild["goss_config"] = os.path.join(subdir, "ci", "goss.yaml")

platformToBuild["goss_args"] = "tail -f /dev/null" if channel["tests"].get("type", "web") == "cli" else ""

platformToBuild["tests_enabled"] = channel["tests"]["enabled"] and platform in TESTABLE_PLATFORMS

imagesToBuild["imagePlatforms"].append(platformToBuild)
imagesToBuild["images"].append(toBuild)
return imagesToBuild

if __name__ == "__main__":
apps = sys.argv[1]
forRelease = sys.argv[2] == "true"
force = sys.argv[3] == "true"
imagesToBuild = {
"images": [],
"imagePlatforms": []
}

if apps != "all":
channels=None
apps = apps.split(",")
if len(sys.argv) == 5:
channels = sys.argv[4].split(",")

for app in apps:
if not os.path.exists(os.path.join("./apps", app)):
print(f"App \"{app}\" not found")
exit(1)

meta = None
if os.path.isfile(os.path.join("./apps", app, "metadata.yaml")):
meta = load_metadata_file_yaml(os.path.join("./apps", app, "metadata.yaml"))
elif os.path.isfile(os.path.join("./apps", app, "metadata.json")):
meta = load_metadata_file_json(os.path.join("./apps", app, "metadata.json"))

imageToBuild = get_image_metadata(os.path.join("./apps", app), meta, forRelease, force=force, channels=channels)
if imageToBuild is not None:
imagesToBuild["images"].extend(imageToBuild["images"])
imagesToBuild["imagePlatforms"].extend(imageToBuild["imagePlatforms"])
else:
for subdir, dirs, files in os.walk("./apps"):
for file in files:
meta = None
if file == "metadata.yaml":
meta = load_metadata_file_yaml(os.path.join(subdir, file))
elif file == "metadata.json":
meta = load_metadata_file_json(os.path.join(subdir, file))
else:
continue
if meta is not None:
imageToBuild = get_image_metadata(subdir, meta, forRelease, force=force)
if imageToBuild is not None:
imagesToBuild["images"].extend(imageToBuild["images"])
imagesToBuild["imagePlatforms"].extend(imageToBuild["imagePlatforms"])
print(json.dumps(imagesToBuild))
81 changes: 81 additions & 0 deletions .github/scripts/render-readme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import os
import json
import requests
import yaml

from jinja2 import Environment, PackageLoader, select_autoescape

repo_owner = os.environ.get('REPO_OWNER', os.environ.get('GITHUB_REPOSITORY_OWNER'))
repo_name = os.environ.get('REPO_NAME', os.environ.get('GITHUB_REPOSITORY'))

env = Environment(
loader=PackageLoader("render-readme"),
autoescape=select_autoescape()
)

def load_metadata_file_yaml(file_path):
with open(file_path, "r") as f:
return yaml.safe_load(f)

def load_metadata_file_json(file_path):
with open(file_path, "r") as f:
return json.load(f)

def load_metadata_file(file_path):
if file_path.endswith(".json"):
return load_metadata_file_json(file_path)
elif file_path.endswith(".yaml"):
return load_metadata_file_yaml(file_path)
return None

def get_latest_image(name):
r = requests.get(
f"https://api.github.com/users/{repo_owner}/packages/container/{name}/versions",
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": "token " + os.environ["GITHUB_TOKEN"]
},
)
if r.status_code != 200:
print(f"Failed to get versions for {name}: {r.status_code}: {r.text}")
return None
data = r.json()
for image in data:
tags = image["metadata"]["container"]["tags"]
if "rolling" in tags:
return image
print(f"Couldn't find latest tag for {name}")
return None

if __name__ == "__main__":
base_images = []
app_images = []
for subdir, dirs, files in os.walk("./apps"):
for file in files:
if file != "metadata.yaml" and file != "metadata.json":
continue
meta = load_metadata_file(os.path.join(subdir, file))
for channel in meta["channels"]:
name = ""
if channel.get("stable", False):
name = meta["app"]
else:
name = "-".join([meta["app"], channel["name"]])
image = {
"name": name,
"channel": channel["name"],
"html_url": "",
"owner": repo_owner
}
gh_data = get_latest_image(name)
if gh_data is not None:
image["html_url"] = f"https://github.com/{repo_name}/pkgs/container/{name}"
image["tags"] = sorted(gh_data["metadata"]["container"]["tags"])
if meta["base"]:
base_images.append(image)
else:
app_images.append(image)

template = env.get_template("README.md.j2")
with open("./README.md", "w") as f:
f.write(template.render(base_images=base_images, app_images=app_images))
4 changes: 4 additions & 0 deletions .github/scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
requests
pyyaml
packaging
jinja2
Loading

0 comments on commit 5c45247

Please sign in to comment.