From e359f96842e3d92eb38b932ded28345356bd5c23 Mon Sep 17 00:00:00 2001 From: Jory Irving Date: Wed, 10 Jan 2024 12:34:07 -0700 Subject: [PATCH 1/4] feat: add new pipelines --- .editorconfig | 14 + .github/labeler.yaml | 7 + .github/renovate.json5 | 8 +- .github/scripts/prepare-matrices.py | 191 ++++++++++++ .github/scripts/render-readme.py | 81 +++++ .github/scripts/requirements.txt | 4 + .github/workflows/build-images.yaml | 349 ++++++++++++++++++++++ .github/workflows/get-changed-images.yaml | 46 +++ .github/workflows/meta-labeler.yaml | 40 +++ .github/workflows/pr-validate.yaml | 28 ++ .github/workflows/publish.yaml | 6 +- .github/workflows/release-on-merge.yaml | 41 +++ .github/workflows/release-schedule.yaml | 47 +++ .github/workflows/render-readme.yaml | 54 ++++ .github/workflows/simple-checks.yaml | 37 +++ .gitignore | 3 + .vscode/settings.json | 5 + LICENSE | 2 +- Taskfile.yml | 55 ++++ apps/bitwarden-cli/Dockerfile | 15 + apps/bitwarden-cli/README.md | 15 + apps/bitwarden-cli/ci/latest.sh | 5 + apps/bitwarden-cli/ci/metadata.yaml | 14 + apps/bitwarden-cli/entrypoint.sh | 12 + apps/tf-runner-bitwarden/Dockerfile | 17 +- apps/tf-runner-bitwarden/ci/latest.sh | 4 + apps/tf-runner-bitwarden/ci/metadata.yaml | 12 + metadata.rules.cue | 20 ++ 28 files changed, 1120 insertions(+), 12 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/labeler.yaml create mode 100644 .github/scripts/prepare-matrices.py create mode 100644 .github/scripts/render-readme.py create mode 100644 .github/scripts/requirements.txt create mode 100644 .github/workflows/build-images.yaml create mode 100644 .github/workflows/get-changed-images.yaml create mode 100644 .github/workflows/meta-labeler.yaml create mode 100644 .github/workflows/pr-validate.yaml create mode 100644 .github/workflows/release-on-merge.yaml create mode 100644 .github/workflows/release-schedule.yaml create mode 100644 .github/workflows/render-readme.yaml create mode 100644 .github/workflows/simple-checks.yaml create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Taskfile.yml create mode 100644 apps/bitwarden-cli/Dockerfile create mode 100644 apps/bitwarden-cli/README.md create mode 100644 apps/bitwarden-cli/ci/latest.sh create mode 100644 apps/bitwarden-cli/ci/metadata.yaml create mode 100644 apps/bitwarden-cli/entrypoint.sh create mode 100644 apps/tf-runner-bitwarden/ci/latest.sh create mode 100644 apps/tf-runner-bitwarden/ci/metadata.yaml create mode 100644 metadata.rules.cue diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d9216d --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/.github/labeler.yaml b/.github/labeler.yaml new file mode 100644 index 0000000..740a499 --- /dev/null +++ b/.github/labeler.yaml @@ -0,0 +1,7 @@ +--- +area/ci: + - changed-files: + - any-glob-to-any-file: ".github/**/*" +area/containers: + - changed-files: + - any-glob-to-any-file: "apps/**" diff --git a/.github/renovate.json5 b/.github/renovate.json5 index ea03567..643cacc 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -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", @@ -18,7 +20,9 @@ "dependencyDashboardTitle": "Renovate Dashboard 🤖", "suppressNotifications": ["prIgnoreNotification"], "rebaseWhen": "conflicted", - "schedule": ["every saturday"], + "assignees": [ + "LilDrunkenSmurf" + ], "pre-commit": { "enabled": true }, @@ -31,4 +35,4 @@ "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}" } ] -} \ No newline at end of file +} diff --git a/.github/scripts/prepare-matrices.py b/.github/scripts/prepare-matrices.py new file mode 100644 index 0000000..5b56938 --- /dev/null +++ b/.github/scripts/prepare-matrices.py @@ -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)) diff --git a/.github/scripts/render-readme.py b/.github/scripts/render-readme.py new file mode 100644 index 0000000..7cf222a --- /dev/null +++ b/.github/scripts/render-readme.py @@ -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)) diff --git a/.github/scripts/requirements.txt b/.github/scripts/requirements.txt new file mode 100644 index 0000000..80bad66 --- /dev/null +++ b/.github/scripts/requirements.txt @@ -0,0 +1,4 @@ +requests +pyyaml +packaging +jinja2 diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml new file mode 100644 index 0000000..956f458 --- /dev/null +++ b/.github/workflows/build-images.yaml @@ -0,0 +1,349 @@ +--- + name: "Image Build" + + on: + workflow_call: + inputs: + appsToBuild: + required: false + type: string + default: '' + channelsToBuild: + required: false + type: string + default: '' + pushImages: + required: false + default: false + type: boolean + sendNotifications: + required: false + default: false + type: boolean + force: + required: false + default: true + type: boolean + description: Force rebuild + secrets: + BOT_APP_ID: + description: The App ID of the GitHub App + required: true + BOT_APP_PRIVATE_KEY: + description: The private key of the GitHub App + required: true + + jobs: + prepare: + name: Prepare to Build + runs-on: ubuntu-latest + outputs: + matrices: ${{ steps.prepare-matrices.outputs.matrices }} + steps: + - name: Lowercase repository owner + shell: bash + run: echo "LOWERCASE_REPO_OWNER=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV + + - name: Generate Token + uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: "${{ secrets.BOT_APP_ID }}" + private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" + + - name: Checkout + uses: actions/checkout@v4 + with: + token: "${{ steps.app-token.outputs.token }}" + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + cache: pip + + - name: Install Python Requirements + shell: bash + run: pip install -r ./.github/scripts/requirements.txt && pip freeze + + - name: Prepare Matrices + id: prepare-matrices + env: + TOKEN: ${{ steps.app-token.outputs.token }} + shell: bash + run: | + if [[ -z "${{ inputs.appsToBuild }}" ]]; then + matrices=$(python ./.github/scripts/prepare-matrices.py "all" "${{ inputs.pushImages }}" "${{ inputs.force }}") + else + if [[ -z "${{ inputs.channelsToBuild }}" ]]; then + matrices=$(python ./.github/scripts/prepare-matrices.py "${{ inputs.appsToBuild }}" "${{ inputs.pushImages }}" "${{ inputs.force }}") + else + matrices=$(python ./.github/scripts/prepare-matrices.py "${{ inputs.appsToBuild }}" "${{ inputs.pushImages }}" "${{ inputs.force }}" "${{ inputs.channelsToBuild }}") + fi + fi + echo "matrices=${matrices}" >> $GITHUB_OUTPUT + echo "${matrices}" + + build-platform-images: + name: Build/Test ${{ matrix.image.name }} (${{ matrix.image.platform }}) + needs: prepare + runs-on: ubuntu-latest + if: ${{ toJSON(fromJSON(needs.prepare.outputs.matrices).imagePlatforms) != '[]' && toJSON(fromJSON(needs.prepare.outputs.matrices).imagePlatforms) != '' }} + strategy: + fail-fast: false + matrix: + image: ["${{ fromJSON(needs.prepare.outputs.matrices).imagePlatforms }}"] + permissions: + contents: read + packages: write + steps: + - name: Lowercase repository owner + shell: bash + run: echo "LOWERCASE_REPO_OWNER=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV + + - name: Log Matrix Input + shell: bash + run: | + cat << EOF + ${{ toJSON(matrix.image)}} + EOF + + - name: Validate Matrix Input + shell: bash + run: | + if [[ -z "${{ matrix.image.name }}" ]]; then + echo "image.name is empty" + exit 1 + fi + if [[ -z "${{ matrix.image.version }}" ]]; then + echo "image.version is empty" + exit 1 + fi + if [[ -z "${{ matrix.image.context }}" ]]; then + echo "image.context is empty" + exit 1 + fi + if [[ -z "${{ matrix.image.dockerfile }}" ]]; then + echo "image.dockerfile is empty" + exit 1 + fi + if [[ -z "${{ matrix.image.platform }}" ]]; then + echo "image.platform is empty" + exit 1 + fi + if [[ -z "${{ matrix.image.tests_enabled }}" ]]; then + echo "image.tests_enabled is empty" + exit 1 + fi + echo "${{ matrix.image.name }}" | grep -E "[a-zA-Z0-9_\.\-]+" || "Image Name is invalid" + echo "${{ matrix.image.version }}" | grep -E "[a-zA-Z0-9_\.\-]+" || "Image Version is invalid" + + - name: Generate Token + uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: "${{ secrets.BOT_APP_ID }}" + private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" + + - name: Checkout + uses: actions/checkout@v4 + with: + token: "${{ steps.app-token.outputs.token }}" + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: "${{ github.actor }}" + password: "${{ secrets.GITHUB_TOKEN }}" + + - name: Setup Goss + if: ${{ matrix.image.tests_enabled }} + uses: e1himself/goss-installation-action@v1 + with: + version: latest + + - name: Prepare Build Outputs + id: prepare-build-outputs + shell: bash + run: | + if [[ "${{ inputs.pushImages }}" == "true" ]]; then + image_name="ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/${{ matrix.image.name }}" + outputs="type=image,name=${image_name},push-by-digest=true,name-canonical=true,push=true" + else + image_name="ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/${{ matrix.image.name }}:zztesting" + outputs="type=docker,name=${image_name},push=false" + fi + echo "image_name=${image_name}" >> $GITHUB_OUTPUT + echo "outputs=${outputs}" >> $GITHUB_OUTPUT + + - name: Build Image + uses: docker/build-push-action@v5 + id: build + with: + build-args: |- + VERSION=${{ matrix.image.version }} + REVISION=${{ github.sha }} + CHANNEL=${{ matrix.image.channel }} + # TODO: Use ${{ matrix.image.context }}, requires updates to all dockerfiles :-( + context: . + platforms: ${{ matrix.image.platform }} + file: ${{ matrix.image.dockerfile }} + outputs: ${{ steps.prepare-build-outputs.outputs.outputs }} + cache-from: type=gha + cache-to: type=gha,mode=max + labels: |- + org.opencontainers.image.title=${{ matrix.image.name }} + org.opencontainers.image.url=https://ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/${{ matrix.image.name }} + org.opencontainers.image.source=https://github.com/${{ env.LOWERCASE_REPO_OWNER }}/containers + org.opencontainers.image.version=${{ matrix.image.version }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.vendor=${{ env.LOWERCASE_REPO_OWNER }} + + - name: Run Goss Tests + id: dgoss + if: ${{ matrix.image.tests_enabled }} + env: + CONTAINER_RUNTIME: docker + GOSS_FILE: ${{ matrix.image.goss_config }} + GOSS_OPTS: --retry-timeout 60s --sleep 2s --color --format documentation + GOSS_SLEEP: 2 + GOSS_FILES_STRATEGY: cp + CONTAINER_LOG_OUTPUT: goss_container_log_output + shell: bash + run: | + if [[ '${{ inputs.pushImages }}' == 'true' ]]; then + image_name="${{ steps.prepare-build-outputs.outputs.image_name }}@${{ steps.build.outputs.digest }}" + else + image_name="${{ steps.prepare-build-outputs.outputs.image_name }}" + fi + dgoss run ${image_name} ${{ matrix.image.goss_args }} + + - name: Export Digest + id: export-digest + if: ${{ inputs.pushImages }} + shell: bash + run: | + mkdir -p /tmp/${{ matrix.image.name }}/digests + digest="${{ steps.build.outputs.digest }}" + echo "${{ matrix.image.name }}" > "/tmp/${{ matrix.image.name }}/digests/${digest#sha256:}" + + - name: Upload Digest + if: ${{ inputs.pushImages}} + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.image.name }} + path: /tmp/${{ matrix.image.name }}/* + if-no-files-found: error + retention-days: 1 + + merge: + name: Merge ${{ matrix.image.name }} + runs-on: ubuntu-latest + needs: ["prepare", "build-platform-images"] + # Always run merge, as the prior matrix is all or nothing. We test for prior step failure + # in the "Test Failed Bit" step. This ensures if one app fails, others can still complete. + if: ${{ always() && inputs.pushImages && toJSON(fromJSON(needs.prepare.outputs.matrices).images) != '[]' && toJSON(fromJSON(needs.prepare.outputs.matrices).images) != '' }} + strategy: + matrix: + image: ["${{ fromJSON(needs.prepare.outputs.matrices).images }}"] + fail-fast: false + steps: + - name: Lowercase repository owner + shell: bash + run: echo "LOWERCASE_REPO_OWNER=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV + + - name: Download Digests + uses: actions/download-artifact@v3 + with: + name: ${{ matrix.image.name }} + path: /tmp/${{ matrix.image.name }} + + - name: Ensure all platforms were built + id: ensure-platforms + shell: bash + run: | + EXPECTED_COUNT=$(cat << EOF | jq ". | length" + ${{ toJSON(matrix.image.platforms) }} + EOF + ) + ACTUAL_COUNT=$(ls -1 /tmp/${{ matrix.image.name }}/digests | wc -l) + if [[ $EXPECTED_COUNT != $ACTUAL_COUNT ]]; then + echo "Expected $EXPECTED_COUNT platforms, but only found $ACTUAL_COUNT" + echo "Expected: ${{ toJSON(matrix.image.platforms) }}" + echo "Actual: $(cat /tmp/${{ matrix.image.name }}/digests/*)" + exit 1 + fi + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: "${{ github.actor }}" + password: "${{ secrets.GITHUB_TOKEN }}" + + - name: Log Files + working-directory: /tmp/${{ matrix.image.name }}/digests + shell: bash + run: | + ls -la + cat * + + - name: Merge Manifests + id: merge + working-directory: /tmp/${{ matrix.image.name }}/digests + env: + TAGS: ${{ toJSON(matrix.image.tags) }} + shell: bash + run: | + docker buildx imagetools create $(jq -cr '. | map("-t ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/${{matrix.image.name}}:" + .) | join(" ")' <<< "$TAGS") \ + $(printf 'ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/${{ matrix.image.name }}@sha256:%s ' *) + + - name: Inspect image + id: inspect + shell: bash + run: | + docker buildx imagetools inspect ghcr.io/${{ env.LOWERCASE_REPO_OWNER }}/${{ matrix.image.name }}:${{ matrix.image.tags[0] }} + + - name: Build successful + id: build-success + if: ${{ always() && steps.merge.outcome == 'success' && steps.inspect.outcome == 'success' }} + shell: bash + run: | + echo "message=🎉 ${{ matrix.image.name }} (${{ matrix.image.tags[0] }})" >> $GITHUB_OUTPUT + echo "color=0x00FF00" >> $GITHUB_OUTPUT + + - name: Build failed + id: build-failed + if: ${{ always() && (steps.merge.outcome == 'failure' || steps.inspect.outcome == 'failure') }} + shell: bash + run: | + echo "message=💥 ${{ matrix.image.name }} (${{ matrix.image.tags[0] }})" >> $GITHUB_OUTPUT + echo "color=0xFF0000" >> $GITHUB_OUTPUT + + - name: Send Discord Webhook + uses: sarisia/actions-status-discord@v1 + if: ${{ always() && inputs.sendNotifications == 'true' }} + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + title: ${{ steps.build-failed.outputs.message || steps.build-success.outputs.message }} + color: ${{ steps.build-failed.outputs.color || steps.build-success.outputs.color }} + username: GitHub Actions + + # Summarize matrix https://github.community/t/status-check-for-a-matrix-jobs/127354/7 + build_success: + name: Build matrix success + runs-on: ubuntu-latest + needs: ["prepare", "merge"] + if: ${{ always() }} + steps: + - name: Check build matrix status + if: ${{ (inputs.appsToBuild != '' && inputs.appsToBuild != '[]') && (needs.merge.result != 'success' && needs.merge.result != 'skipped' && needs.prepare.result != 'success') }} + shell: bash + run: exit 1 diff --git a/.github/workflows/get-changed-images.yaml b/.github/workflows/get-changed-images.yaml new file mode 100644 index 0000000..ccf5aa2 --- /dev/null +++ b/.github/workflows/get-changed-images.yaml @@ -0,0 +1,46 @@ +--- + name: "Get Changed Images" + + on: + workflow_call: + outputs: + addedOrModified: + description: "Whether any files were added or modified" + value: ${{ jobs.get-changed-images.outputs.addedOrModified }} + addedOrModifiedImages: + description: "The images that were added or modified" + value: ${{ jobs.get-changed-images.outputs.addedOrModifiedImages }} + + jobs: + get-changed-images: + name: Get Changed Images + runs-on: ubuntu-latest + outputs: + addedOrModified: "${{ steps.changed-files.outputs.all_changed_and_modified_files_count > 0 }}" + addedOrModifiedImages: "${{ steps.changed-containers.outputs.addedOrModifiedImages }}" + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get Changed Files + id: changed-files + uses: tj-actions/changed-files@v41 + with: + files: apps/** + dir_names: true + dir_names_max_depth: 2 + json: true + escape_json: false + + - if: ${{ steps.changed-files.outputs.all_changed_and_modified_files_count > 0 }} + name: Determine changed images + id: changed-containers + shell: bash + run: | + IMAGES=$( \ + echo '${{ steps.changed-files.outputs.all_changed_and_modified_files }}' \ + | jq --raw-output 'map(sub("^apps/"; "")) | join(",")' \ + ) + echo "addedOrModifiedImages=${IMAGES}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/meta-labeler.yaml b/.github/workflows/meta-labeler.yaml new file mode 100644 index 0000000..c9768f9 --- /dev/null +++ b/.github/workflows/meta-labeler.yaml @@ -0,0 +1,40 @@ +--- + name: Labeler + + on: + pull_request: + branches: + - main + + jobs: + labeler: + name: Labeler + runs-on: "ubuntu-latest" + steps: + - name: Generate Token + id: generate-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.RIVERBOT_APP_ID }} + private-key: ${{ secrets.RIVERBOT_APP_PRIVATE_KEY }} + + - name: Labeler + uses: actions/labeler@v5 + with: + repo-token: "${{ steps.generate-token.outputs.token }}" + configuration-path: .github/labeler.yaml + + - name: Label Size + uses: pascalgn/size-label-action@v0.5.0 + env: + GITHUB_TOKEN: "${{ steps.generate-token.outputs.token }}" + with: + sizes: > + { + "0": "XS", + "20": "S", + "50": "M", + "200": "L", + "800": "XL", + "2000": "XXL" + } diff --git a/.github/workflows/pr-validate.yaml b/.github/workflows/pr-validate.yaml new file mode 100644 index 0000000..29cf4c5 --- /dev/null +++ b/.github/workflows/pr-validate.yaml @@ -0,0 +1,28 @@ +--- + name: "Pull Request: Validate" + + on: + pull_request: + branches: ["main"] + types: ["opened", "synchronize", "reopened"] + + concurrency: + group: ${{ github.head_ref }}-pr-validate + cancel-in-progress: true + + jobs: + simple-checks: + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/simple-checks.yaml@main + + get-changed-images: + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/get-changed-images.yaml@main + + build-images: + needs: ["simple-checks", "get-changed-images"] + if: ${{ needs.get-changed-images.outputs.addedOrModified == 'true' }} + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/build-images.yaml@main + secrets: inherit + with: + appsToBuild: "${{ needs.get-changed-images.outputs.addedOrModifiedImages }}" + pushImages: false + sendNotifications: false diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index dfa26c8..54fade8 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -3,9 +3,9 @@ name: Build & publish container images on: workflow_dispatch: {} - push: - branches: - - main + # push: + # branches: + # - main jobs: find-changed-images: diff --git a/.github/workflows/release-on-merge.yaml b/.github/workflows/release-on-merge.yaml new file mode 100644 index 0000000..beddfb0 --- /dev/null +++ b/.github/workflows/release-on-merge.yaml @@ -0,0 +1,41 @@ +--- + name: Release on Merge + + concurrency: + group: container-release + cancel-in-progress: false + + on: + push: + branches: ["main"] + paths: + - "apps/**" + - ".github/scripts/templates/**" + - "!apps/**/metadata.json" + - "!apps/**/metadata.yaml" + - "!apps/**/README.md" + + jobs: + simple-checks: + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/simple-checks.yaml@main + + get-changed-images: + needs: ["simple-checks"] + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/get-changed-images.yaml@main + + build-images: + needs: ["simple-checks", "get-changed-images"] + if: ${{ needs.get-changed-images.outputs.addedOrModified == 'true' }} + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/build-images.yaml@main + secrets: inherit + with: + appsToBuild: "${{ needs.get-changed-images.outputs.addedOrModifiedImages }}" + pushImages: true + sendNotifications: true + + render-readme: + name: Render Readme + needs: build-images + if: ${{ always() && needs.build-images.result != 'failure' }} + uses: ./.github/workflows/render-readme.yaml + secrets: inherit diff --git a/.github/workflows/release-schedule.yaml b/.github/workflows/release-schedule.yaml new file mode 100644 index 0000000..33e756a --- /dev/null +++ b/.github/workflows/release-schedule.yaml @@ -0,0 +1,47 @@ +--- + name: Scheduled Release + + concurrency: + group: container-release + cancel-in-progress: false + + on: + workflow_dispatch: + inputs: + appsToBuild: + description: App(s) to build + required: false + type: string + default: all + force: + description: Force rebuild + type: boolean + default: false + required: true + schedule: + - cron: "0 * * * *" + + jobs: + simple-checks: + name: Simple Checks + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/simple-checks.yaml@main + + build-images: + name: Build Images + needs: simple-checks + uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/build-images.yaml@main + secrets: inherit + permissions: + contents: read + packages: write + with: + appsToBuild: ${{ inputs.appsToBuild }} + force: ${{ inputs.force == true }} + pushImages: true + sendNotifications: true + + render-readme: + name: Render Readme + needs: build-images + uses: ./.github/workflows/render-readme.yaml + secrets: inherit diff --git a/.github/workflows/render-readme.yaml b/.github/workflows/render-readme.yaml new file mode 100644 index 0000000..bfedc8b --- /dev/null +++ b/.github/workflows/render-readme.yaml @@ -0,0 +1,54 @@ +--- + name: "Render Readme" + + on: + workflow_call: + secrets: + BOT_APP_ID: + description: The App ID of the GitHub App + required: true + BOT_APP_PRIVATE_KEY: + description: The private key of the GitHub App + required: true + + jobs: + render-readme: + name: Render README + runs-on: ubuntu-latest + steps: + - name: Generate Token + uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: "${{ secrets.BOT_APP_ID }}" + private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" + + - name: Checkout + uses: actions/checkout@v4 + with: + token: "${{ steps.app-token.outputs.token }}" + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + cache: pip + + - name: Install Python Requirements + shell: bash + run: pip install -r ./.github/scripts/requirements.txt && pip freeze + + - name: Render README + env: + GITHUB_TOKEN: "${{ steps.app-token.outputs.token }}" + shell: bash + run: python ./.github/scripts/render-readme.py + + - name: Commit Changes + shell: bash + run: | + git config --global user.name "${{ secrets.BOT_USERNAME }}" + git config --global user.email "${{ secrets.BOT_USER_ID }}+${{ secrets.BOT_USERNAME }}[bot]@users.noreply.github.com" + git add ./README.md + git commit -m "chore: render README.md" || echo "No changes to commit" + git push origin || echo "No changes to push" diff --git a/.github/workflows/simple-checks.yaml b/.github/workflows/simple-checks.yaml new file mode 100644 index 0000000..21bdbe9 --- /dev/null +++ b/.github/workflows/simple-checks.yaml @@ -0,0 +1,37 @@ +--- + name: "Simple Checks" + + on: + workflow_call: + + jobs: + metadata-validation: + name: Validate Image Metadata + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get Changed Files + id: changed-files + uses: tj-actions/changed-files@v41 + with: + files_yaml: | + cue: + - metadata.rules.cue + - apps/**/metadata.json + - apps/**/metadata.yaml + + - name: Setup CUE + if: ${{ steps.changed-files.outputs.cue_any_changed == 'true' }} + uses: cue-lang/setup-cue@v1.0.0 + + # Run against all files to ensure they are tested if the cue schema is changed. + - name: Validate image metadata + if: ${{ steps.changed-files.outputs.cue_any_changed == 'true' }} + shell: bash + run: | + find ./apps/ -name metadata.json | xargs -I {} cue vet --schema '#Spec' {} ./metadata.rules.cue + find ./apps/ -name metadata.yaml | xargs -I {} cue vet --schema '#Spec' {} ./metadata.rules.cue diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39aa0b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.goss +.private +**/*.pyc diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..75e4e8b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.json5": "jsonc" + } + } diff --git a/LICENSE b/LICENSE index dfc120b..67e4078 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 arthurgeek +Copyright (c) 2023 LilDrunkenSmurf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..2fefdd3 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,55 @@ +--- +version: "3" + +vars: + CHANNEL: '{{ default "stable" .CHANNEL }}' + +tasks: + default: + silent: true + cmds: + - task -l + + test: + desc: |- + task APP= CHANNEL= BASE= test + cmds: + - task: download-goss + - >- + cue vet --schema '#Spec' ./apps/{{.APP}}/metadata.json metadata.rules.cue + - >- + docker buildx build --progress=plain --load + -t {{.APP}}:{{.CHANNEL}} + --build-arg CHANNEL={{.CHANNEL}} + --build-arg VERSION=$(bash ./.github/scripts/upstream.sh "{{.APP}}" "{{.CHANNEL}}") + {{if eq .MULTIPLATFORM "true"}} + --platform $(jq -r '.channels[] | select(.name=="{{.CHANNEL}}").platforms | join(",")' ./apps/{{.APP}}/metadata.json) + {{else}} + --platform "linux/$(uname -m | sed 's/x86_64/amd64/')" + {{end}} + -f ./apps/{{.APP}}/Dockerfile . + - >- + ./.goss/dgoss run {{.APP}}:{{.CHANNEL}} {{if eq .BASE "true"}}tail -f /dev/null{{end}} + env: + CONTAINER_RUNTIME: docker + GOSS_PATH: ./.goss/goss + GOSS_OPTS: --sleep 5s --retry-timeout 60s --color --format documentation + GOSS_SLEEP: 2 + GOSS_FILE: ./apps/{{.APP}}/ci/goss.yaml + GOSS_FILES_STRATEGY: cp + vars: + MULTIPLATFORM: '{{ default "false" .MULTIPLATFORM }}' + + download-goss: + silent: true + vars: + GOSS_VERSION: v0.3.21 + cmds: + - mkdir -p ./.goss + - curl -fsSL -o ./.goss/goss https://github.com/aelsabbahy/goss/releases/download/{{.GOSS_VERSION}}/goss-linux-amd64 + - chmod +x ./.goss/goss + - curl -fsSL -o ./.goss/dgoss https://raw.githubusercontent.com/aelsabbahy/goss/{{.GOSS_VERSION}}/extras/dgoss/dgoss + - chmod +x ./.goss/dgoss + status: + - test -f ./.goss/goss + - test -f ./.goss/dgoss diff --git a/apps/bitwarden-cli/Dockerfile b/apps/bitwarden-cli/Dockerfile new file mode 100644 index 0000000..93df732 --- /dev/null +++ b/apps/bitwarden-cli/Dockerfile @@ -0,0 +1,15 @@ +FROM debian:sid + +ARG TARGETPLATFORM +ARG VERSION + +WORKDIR /usr/local/bin +RUN apt update && apt install -y curl unzip libsecret-1-0 jq +RUN curl -LO "https://github.com/bitwarden/clients/releases/download/cli-v{$VERSION}/bw-linux-{$VERSION}.zip" \ +&& unzip *.zip && chmod +x ./bw + +RUN rm *.zip + +COPY entrypoint.sh / + +CMD ["/entrypoint.sh"] diff --git a/apps/bitwarden-cli/README.md b/apps/bitwarden-cli/README.md new file mode 100644 index 0000000..00071d9 --- /dev/null +++ b/apps/bitwarden-cli/README.md @@ -0,0 +1,15 @@ +# bitwarden-cli + +Environment Variables + +## Required Environment Variables + +1. BW_CLIENTID +2. BW_CLIENTSECRET +3. BW_PASSWORD + + +```bash +bw login --apikey +bw unlock --passwordenv BW_PASSWORD +``` diff --git a/apps/bitwarden-cli/ci/latest.sh b/apps/bitwarden-cli/ci/latest.sh new file mode 100644 index 0000000..ed7cc9b --- /dev/null +++ b/apps/bitwarden-cli/ci/latest.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +version=$(curl -H "Accept: application/vnd.github+json" https://api.github.com/repos/bitwarden/clients/releases | jq -r 'sort_by(.published_at) | reverse | .[].name | select( index("CLI") )' | sed 's:.*CLI v::' | head -n 1) +version="${version#*v}" +version="${version#*cli-}" +printf "%s" "${version}" diff --git a/apps/bitwarden-cli/ci/metadata.yaml b/apps/bitwarden-cli/ci/metadata.yaml new file mode 100644 index 0000000..d381a49 --- /dev/null +++ b/apps/bitwarden-cli/ci/metadata.yaml @@ -0,0 +1,14 @@ +--- +app: bitwarden-cli +# not in use yet +url: https://api.github.com/repos/bitwarden/clients/releases +rules: + - cli + # - sort published_at + # - 'sort_by(.published_at) | reverse | .[].name | select( index("CLI") )' | sed 's:.*CLI v::' | head -n 1) +version_regex: + - v* +channels: + - name: stable + platforms: ["linux/amd64"] + stable: true diff --git a/apps/bitwarden-cli/entrypoint.sh b/apps/bitwarden-cli/entrypoint.sh new file mode 100644 index 0000000..efb189a --- /dev/null +++ b/apps/bitwarden-cli/entrypoint.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +bw config server ${BW_HOST} + +bw login --apikey --raw +export BW_SESSION=$(bw unlock --passwordenv BW_PASSWORD --raw) +bw unlock --check + +echo 'Running `bw server` on port 8087' +bw serve --hostname 0.0.0.0 #--disable-origin-protection diff --git a/apps/tf-runner-bitwarden/Dockerfile b/apps/tf-runner-bitwarden/Dockerfile index beab69d..1b54bbd 100644 --- a/apps/tf-runner-bitwarden/Dockerfile +++ b/apps/tf-runner-bitwarden/Dockerfile @@ -1,13 +1,18 @@ -FROM hashicorp/terraform:1.6.6 as tf -FROM ghcr.io/weaveworks/tf-runner:v0.15.1 +ARG VERSION=v0.15.1 +ARG TARGETPLATFORM -# renovate: datasource=npm depName=@bitwarden/cli versioning=npm -ARG BW_CLI_VERSION=2023.12.1 +# renovate: datasource=github-releases depName=hashicorp/terraform versioning=docker +FROM hashicorp/terraform:1.6.6 as terraform +# renovate: datasource=github-releases depName=weaveworks/tf-runner versioning=docker +FROM ghcr.io/weaveworks/tf-runner:v${VERSION} as runner USER root -RUN apk add --no-cache npm && npm i -g @bitwarden/cli@${BW_CLI_VERSION} +# renovate: datasource=npm depName=@bitwarden/cli versioning=npm +ARG BW_VERSION=2024.1.0 + +RUN apk add --no-cache npm && npm i -g @bitwarden/cli@${BW_VERSION} -COPY --from=tf /bin/terraform /usr/local/bin/terraform +COPY --from=terraform --chown=65532:65532 /bin/terraform /usr/local/bin/terraform USER 65532:65532 \ No newline at end of file diff --git a/apps/tf-runner-bitwarden/ci/latest.sh b/apps/tf-runner-bitwarden/ci/latest.sh new file mode 100644 index 0000000..053817d --- /dev/null +++ b/apps/tf-runner-bitwarden/ci/latest.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +version="$(curl -sX GET "https://api.github.com/repos/weaveworks/tf-controller/tags" | jq --raw-output '.[0].name' 2>/dev/null)" +version="${version#*v}" +printf "%s" "${version}" diff --git a/apps/tf-runner-bitwarden/ci/metadata.yaml b/apps/tf-runner-bitwarden/ci/metadata.yaml new file mode 100644 index 0000000..5780d69 --- /dev/null +++ b/apps/tf-runner-bitwarden/ci/metadata.yaml @@ -0,0 +1,12 @@ +--- +app: tf-runner-bw +# not in use yet +url: "https://api.github.com/repos/weaveworks/tf-controller/tags" +rules: + - "[0].name" +version_regex: + - v* +channels: + - name: stable + platforms: ["linux/amd64"] + stable: true diff --git a/metadata.rules.cue b/metadata.rules.cue new file mode 100644 index 0000000..d29dc9e --- /dev/null +++ b/metadata.rules.cue @@ -0,0 +1,20 @@ +#Spec: { + app: #AcceptableAppName + base: bool + semantic_versioning?: bool + channels: [...#Channels] +} + +#Channels: { + name: #AcceptableChannelName + platforms: [...#AcceptedPlatforms] + stable: bool + tests: { + enabled: bool + type?: =~"^(cli|web)$" + } +} + +#AcceptableAppName: string & !="" & =~"^[a-zA-Z0-9_-]+$" +#AcceptableChannelName: string & !="" & =~"^[a-zA-Z0-9._-]+$" +#AcceptedPlatforms: "linux/amd64" | "linux/arm64" From 61b1070ead5e3aab013a0db509d49abce4fa70c3 Mon Sep 17 00:00:00 2001 From: Jory Irving Date: Wed, 10 Jan 2024 12:35:18 -0700 Subject: [PATCH 2/4] fix: rename token --- .github/workflows/meta-labeler.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/meta-labeler.yaml b/.github/workflows/meta-labeler.yaml index c9768f9..b958da9 100644 --- a/.github/workflows/meta-labeler.yaml +++ b/.github/workflows/meta-labeler.yaml @@ -1,11 +1,11 @@ --- name: Labeler - + on: pull_request: branches: - main - + jobs: labeler: name: Labeler @@ -15,15 +15,15 @@ id: generate-token uses: actions/create-github-app-token@v1 with: - app-id: ${{ secrets.RIVERBOT_APP_ID }} - private-key: ${{ secrets.RIVERBOT_APP_PRIVATE_KEY }} - + app-id: ${{ secrets.BOT_APP_ID }} + private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }} + - name: Labeler uses: actions/labeler@v5 with: repo-token: "${{ steps.generate-token.outputs.token }}" configuration-path: .github/labeler.yaml - + - name: Label Size uses: pascalgn/size-label-action@v0.5.0 env: From aa613c7dbc4307a081c3144ad3778c3ce968af3f Mon Sep 17 00:00:00 2001 From: Jory Irving Date: Wed, 10 Jan 2024 12:38:52 -0700 Subject: [PATCH 3/4] fix: add owner name --- .github/workflows/pr-validate.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr-validate.yaml b/.github/workflows/pr-validate.yaml index 29cf4c5..12e0686 100644 --- a/.github/workflows/pr-validate.yaml +++ b/.github/workflows/pr-validate.yaml @@ -1,26 +1,26 @@ --- name: "Pull Request: Validate" - + on: pull_request: branches: ["main"] types: ["opened", "synchronize", "reopened"] - + concurrency: group: ${{ github.head_ref }}-pr-validate cancel-in-progress: true - + jobs: simple-checks: - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/simple-checks.yaml@main - + uses: LilDrunkenSmurf/containers/.github/workflows/simple-checks.yaml@main + get-changed-images: - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/get-changed-images.yaml@main - + uses: LilDrunkenSmurf/containers/.github/workflows/get-changed-images.yaml@main + build-images: needs: ["simple-checks", "get-changed-images"] if: ${{ needs.get-changed-images.outputs.addedOrModified == 'true' }} - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/build-images.yaml@main + uses: LilDrunkenSmurf/containers/.github/workflows/build-images.yaml@main secrets: inherit with: appsToBuild: "${{ needs.get-changed-images.outputs.addedOrModifiedImages }}" From 8205ad448fb7f05609d6f76c048342ac4469460e Mon Sep 17 00:00:00 2001 From: Jory Irving Date: Wed, 10 Jan 2024 12:39:35 -0700 Subject: [PATCH 4/4] fix: add owner name --- .github/workflows/release-on-merge.yaml | 18 +++++++++--------- .github/workflows/release-schedule.yaml | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release-on-merge.yaml b/.github/workflows/release-on-merge.yaml index beddfb0..f6dfb9a 100644 --- a/.github/workflows/release-on-merge.yaml +++ b/.github/workflows/release-on-merge.yaml @@ -1,10 +1,10 @@ --- name: Release on Merge - + concurrency: group: container-release cancel-in-progress: false - + on: push: branches: ["main"] @@ -14,25 +14,25 @@ - "!apps/**/metadata.json" - "!apps/**/metadata.yaml" - "!apps/**/README.md" - + jobs: simple-checks: - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/simple-checks.yaml@main - + uses: LilDrunkenSmurf/containers/.github/workflows/simple-checks.yaml@main + get-changed-images: needs: ["simple-checks"] - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/get-changed-images.yaml@main - + uses: LilDrunkenSmurf/containers/.github/workflows/get-changed-images.yaml@main + build-images: needs: ["simple-checks", "get-changed-images"] if: ${{ needs.get-changed-images.outputs.addedOrModified == 'true' }} - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/build-images.yaml@main + uses: LilDrunkenSmurf/containers/.github/workflows/build-images.yaml@main secrets: inherit with: appsToBuild: "${{ needs.get-changed-images.outputs.addedOrModifiedImages }}" pushImages: true sendNotifications: true - + render-readme: name: Render Readme needs: build-images diff --git a/.github/workflows/release-schedule.yaml b/.github/workflows/release-schedule.yaml index 33e756a..8ac9f36 100644 --- a/.github/workflows/release-schedule.yaml +++ b/.github/workflows/release-schedule.yaml @@ -1,10 +1,10 @@ --- name: Scheduled Release - + concurrency: group: container-release cancel-in-progress: false - + on: workflow_dispatch: inputs: @@ -20,16 +20,16 @@ required: true schedule: - cron: "0 * * * *" - + jobs: simple-checks: name: Simple Checks - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/simple-checks.yaml@main - + uses: LilDrunkenSmurf/containers/.github/workflows/simple-checks.yaml@main + build-images: name: Build Images needs: simple-checks - uses: ${GITHUB_REPOSITORY_OWNER}/containers/.github/workflows/build-images.yaml@main + uses: LilDrunkenSmurf/containers/.github/workflows/build-images.yaml@main secrets: inherit permissions: contents: read @@ -39,7 +39,7 @@ force: ${{ inputs.force == true }} pushImages: true sendNotifications: true - + render-readme: name: Render Readme needs: build-images