From 6a61f36280e02c19a81fe286cac5d2b3a4bd6654 Mon Sep 17 00:00:00 2001 From: Nathan Esquenazi Date: Fri, 3 Apr 2026 13:55:41 -0700 Subject: [PATCH 1/2] ci: add GitHub Actions workflow for multi-arch Docker + releases On tag push (v*): - Creates a GitHub Release with auto-generated release notes - Builds multi-arch Docker image (linux/amd64, linux/arm64) - Pushes to ghcr.io/nesquena/hermes-webui with semver tags - Uses GitHub Actions cache for faster builds Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..d890914 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,61 @@ +name: Release & Docker + +on: + push: + tags: + - 'v*' + +permissions: + contents: write + packages: write + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Create GitHub Release from tag + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + + # Set up multi-arch build + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + + # Log in to GHCR + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract version tags (e.g. v0.19 -> 0.19, latest) + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest,enable={{is_default_branch}} + + # Build and push multi-arch image + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max From 4a3b9571f17ca524eff98b37e6ee0784a0cf3256 Mon Sep 17 00:00:00 2001 From: Nathan Esquenazi Date: Fri, 3 Apr 2026 21:02:08 +0000 Subject: [PATCH 2/2] fix(ci): pin all GitHub Actions to full commit SHAs for supply chain security Pinned all 7 third-party actions from mutable version tags to immutable commit SHAs. Mutable tags (e.g. @v4) can be force-pushed by the action author (or a compromised account) to inject malicious code into the workflow, which runs with write access to the repo and GHCR registry. Also moved 'permissions' from workflow level to job level (best practice: scope permissions as narrowly as possible). Pin mapping: actions/checkout@v4 -> @11bd71901bbe... (v4.2.2) softprops/action-gh-release@v2 -> @c062e08bd532... (v2.2.1) docker/setup-qemu-action@v3 -> @49b3bc8e6bdd... (v3.2.0) docker/setup-buildx-action@v3 -> @c47758b77c97... (v3.7.1) docker/login-action@v3 -> @9780b0c442fb... (v3.3.0) docker/metadata-action@v5 -> @369eb591f429... (v5.6.1) docker/build-push-action@v6 -> @ca877d9245fe... (v6.10.0) --- .github/workflows/release.yml | 42 ++++++++++++++++------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d890914..47a9808 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,52 +5,48 @@ on: tags: - 'v*' -permissions: - contents: write - packages: write - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - jobs: release: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 + permissions: + contents: write # required: create GitHub Release + packages: write # required: push to ghcr.io - # Create GitHub Release from tag + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + # Create GitHub Release from tag with auto-generated notes - name: Create GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@c062e08bd532815e2082a7e09ce9571a6592a176 # v2.2.1 with: generate_release_notes: true - # Set up multi-arch build - - uses: docker/setup-qemu-action@v3 - - uses: docker/setup-buildx-action@v3 + # Set up multi-arch build (QEMU + Buildx) + - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 + - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - # Log in to GHCR + # Log in to GitHub Container Registry - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: - registry: ${{ env.REGISTRY }} + registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # Extract version tags (e.g. v0.19 -> 0.19, latest) + # Extract semver tags: e.g. v0.26 -> 0.26, 0.26 (major.minor), latest - name: Extract metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ghcr.io/${{ github.repository }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=raw,value=latest,enable={{is_default_branch}} - # Build and push multi-arch image + # Build and push multi-arch image (amd64 + arm64) - name: Build and push Docker image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@ca877d9245fef47ef8e79a0c8ffc0a6d6b2e36a1 # v6.10.0 with: context: . platforms: linux/amd64,linux/arm64