Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 95 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:

permissions: read-all

env:
IMAGE_NAME: phanan/koel

jobs:
test:
name: Run tests
Expand All @@ -16,19 +19,39 @@ jobs:
- name: Run tests
uses: ./.github/actions/test

deploy:
name: Deploy to Docker Hub
runs-on: ubuntu-24.04
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
needs: [test]
strategy:
fail-fast: false
matrix:
include:
# amd64 and arm64 each build on their own architecture. arm/v7 is 32-bit ARM,
# which the 64-bit Arm runners cannot execute, so it stays emulated on x86.
- platform: linux/amd64
runner: ubuntu-24.04
emulated: false
- platform: linux/arm64
runner: ubuntu-24.04-arm
emulated: false
- platform: linux/arm/v7
runner: ubuntu-24.04
emulated: true
steps:
- name: Checkout code
uses: actions/checkout@v6
Comment on lines 42 to 43

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

for action in \
  actions/checkout@v6 \
  docker/setup-qemu-action@v4 \
  docker/build-push-action@v7 \
  actions/upload-artifact@v4 \
  actions/download-artifact@v4 \
  docker/setup-buildx-action@v4 \
  docker/login-action@v4
do
  repo="${action%@*}"
  ref="${action#*@}"
  printf '%s@' "$repo"
  gh api "repos/$repo/commits/$ref" --jq '.sha'
done

Repository: koel/docker

Length of output: 600


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Release workflow action refs:\n'
rg -n 'uses:\s*[^#]+' .github/workflows/release.yml

printf '\nRelevant credential/job context:\n'
sed -n '1,150p' .github/workflows/release.yml

Repository: koel/docker

Length of output: 4696


Pin release workflow actions to full commit SHAs.

The release workflow runs Docker Hub login and publish steps from third-party actions tagged with mutable @vN refs. These action refs appear at .github/workflows/release.yml:18, 43, 52, 57, 60, 73, 88, 101, 108, 111; pin each one to a verified 40-character commit SHA so upstream tags cannot redirect build, registry login, artifact upload, or manifest merge code.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 42-43: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 42 - 43, Update every third-party
action reference in the release workflow, including the checkout action named in
the diff and the actions at the listed workflow steps, from mutable version tags
to verified full 40-character commit SHAs. Preserve each action’s current
version and behavior while ensuring all release, registry, artifact, and
manifest steps use immutable pinned references.


- name: Name this platform
env:
PLATFORM: ${{ matrix.platform }}
run: echo "PLATFORM_SLUG=${PLATFORM//\//-}" >> "$GITHUB_ENV"

- name: Set up QEMU
if: matrix.emulated
uses: docker/setup-qemu-action@v4
id: qemu
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
platforms: ${{ matrix.platform }}

- name: Set up Docker Build
uses: docker/setup-buildx-action@v4
Expand All @@ -41,16 +64,76 @@ jobs:

- name: Resolve version
id: version
run: |
REF="$GITHUB_REF_NAME"
echo "VERSION=${REF#v}" >> "$GITHUB_OUTPUT"
echo "TAG=${REF}" >> "$GITHUB_OUTPUT"
run: echo "TAG=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT"

# Each platform is pushed as an untagged image, identified only by its digest.
# The merge job below collects the digests into one tagged multi-arch manifest.
- name: Build and push the production image
id: build
uses: docker/build-push-action@v7
with:
push: true
tags: phanan/koel:latest,phanan/koel:${{ steps.version.outputs.VERSION }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
platforms: ${{ matrix.platform }}
build-args: |
KOEL_VERSION_REF=${{ steps.version.outputs.TAG }}
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true

- name: Record the digest
env:
DIGEST: ${{ steps.build.outputs.digest }}
run: |
mkdir -p /tmp/digests
touch "/tmp/digests/${DIGEST#sha256:}"

- name: Upload the digest
uses: actions/upload-artifact@v4
with:
name: digest-${{ env.PLATFORM_SLUG }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

merge:
name: Push the multi-arch manifest
runs-on: ubuntu-24.04
needs: [build]
steps:
- name: Download the digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digest-*
merge-multiple: true

- name: Set up Docker Build
uses: docker/setup-buildx-action@v4

- name: Login to DockerHub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}

- name: Resolve version
id: version
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

- name: Create the manifest
working-directory: /tmp/digests
env:
VERSION: ${{ steps.version.outputs.VERSION }}
run: |
sources=()

for digest in *; do
sources+=("$IMAGE_NAME@sha256:$digest")
done

docker buildx imagetools create \
--tag "$IMAGE_NAME:latest" \
--tag "$IMAGE_NAME:$VERSION" \
"${sources[@]}"

- name: Verify the manifest
env:
VERSION: ${{ steps.version.outputs.VERSION }}
run: docker buildx imagetools inspect "$IMAGE_NAME:$VERSION"
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ This repo builds the official Docker image for [koel](https://github.com/koel/ko
5. Tags `vX.Y.Z` (lightweight) and force-moves the `latest` tag.
6. Pushes `master`, the new tag, and the force-updated `latest` tag.
- The tag push triggers `.github/workflows/release.yml`: it runs goss tests, then (on success) builds a multi-arch image (`linux/amd64`, `linux/arm64`, `linux/arm/v7`) and pushes to Docker Hub as `phanan/koel:latest` and `phanan/koel:X.Y.Z` (note: `v` prefix stripped — see "Image tags" below).
- Each platform builds on its own runner and is pushed untagged, identified only by its digest; a final `merge` job stitches the digests into one tagged manifest with `docker buildx imagetools create`. So a partial failure leaves orphan digests on Docker Hub but never a half-built tag.
- `linux/amd64` builds on `ubuntu-24.04` and `linux/arm64` on `ubuntu-24.04-arm`, both native. `linux/arm/v7` is 32-bit ARM, which neither 64-bit runner can execute, so it alone still runs under QEMU and dominates the wall clock. Dropping it would make the whole release fast, at the cost of older Raspberry Pi support.
- There is **no draft step** for Docker images. If the workflow succeeds, the image is live on Docker Hub immediately. If goss tests fail, the git tag is already public but no image is pushed — you'll need to investigate and re-tag.
- Wait for the workflow with `gh run watch <id>` (workflow name: `Release Docker image`). Verify after with `docker pull phanan/koel:X.Y.Z`.
- The Docker release for a given version should follow the koel app release for that same version. Run the app release first (`php artisan koel:release` in the koel repo), wait for it to publish on GitHub, then run `./release vX.Y.Z` here.
Expand Down
Loading