ci: publish amd64 image to GHCR
Docker image / Test (push) Canceled after 0s
Docker image / Build and publish (push) Canceled after 0s

This commit is contained in:
“Rogee”
2026-08-21 13:55:26 +08:00
parent 4f8640acf2
commit 13f77933a2
5 changed files with 133 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
name: Docker image
on:
push:
branches:
- main
tags:
- "v*"
pull_request:
branches:
- main
workflow_dispatch:
permissions:
contents: read
concurrency:
group: docker-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false
- name: Run tests
run: ./scripts/test.sh
build:
name: Build and publish
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate image metadata
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
- name: Build and push image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: mode=max
sbom: true
+1
View File
@@ -22,3 +22,4 @@
- Do not commit SSClash or Mihomo binaries to this repository.
- The Dockerfile may link to official release URLs and users build the image for their own deployment.
- Do not publish a prebuilt image containing SSClash without permission from its copyright holder.
- GitHub Actions may push the amd64 image to private GHCR for this deployment; do not make the package public without that permission.
+13
View File
@@ -47,6 +47,19 @@ Versions are pinned in the Dockerfile:
SSClash is verified against the checksum file from its official release. Mihomo amd64 and arm64 archives are verified against pinned SHA-256 values. To update either component, update the version and checksums together, then run the complete test suite.
## GitHub Container Registry
The GitHub Actions workflow builds `linux/amd64` only. SSClash-Go and Mihomo are downloaded and checksum-verified during the Docker build, so the resulting container never downloads executable files at startup.
The workflow runs tests before building, publishes to `ghcr.io/<github-owner>/mohomo-docker`, attaches SBOM and provenance, and creates these tags:
- `latest` and `main` from the default branch;
- the Git tag and major/minor tags from releases such as `v1.2.3`;
- an immutable `sha-<commit>` tag;
- pull-request tags for build validation only, without pushing.
Keep the GHCR package visibility **private**. The workflow deliberately does not attempt to change package visibility. Making an image containing SSClash-Go available to third parties conflicts with the upstream binary license unless the copyright holder grants permission.
## Tests
```sh
+2
View File
@@ -4,6 +4,8 @@ set -eu
project_root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
cd "$project_root"
./tests/workflow-contract.sh
unformatted=$(gofmt -l cmd internal)
if [ -n "$unformatted" ]; then
echo "Go files require formatting:" >&2
+30
View File
@@ -0,0 +1,30 @@
#!/bin/sh
set -eu
workflow=.github/workflows/docker.yml
test -f "$workflow" || {
echo "missing GHCR workflow: $workflow" >&2
exit 1
}
grep -F 'packages: write' "$workflow" >/dev/null
# Match the GitHub expression literally.
# shellcheck disable=SC2016
grep -F 'ghcr.io/${{ github.repository }}' "$workflow" >/dev/null
grep -F 'platforms: linux/amd64' "$workflow" >/dev/null
grep -F 'needs: test' "$workflow" >/dev/null
# Match the GitHub expression literally.
# shellcheck disable=SC2016
grep -F 'push: ${{ github.event_name != '\''pull_request'\'' }}' "$workflow" >/dev/null
if grep -Ei 'arm64|setup-qemu' "$workflow" >/dev/null; then
echo "workflow must build linux/amd64 only and must not configure QEMU" >&2
exit 1
fi
uses_count=$(grep -Ec '^[[:space:]]+uses:' "$workflow")
pinned_count=$(grep -Ec '^[[:space:]]+uses: [^ ]+@[0-9a-f]{40}([[:space:]]|$)' "$workflow")
if [ "$uses_count" -eq 0 ] || [ "$uses_count" -ne "$pinned_count" ]; then
echo "every GitHub Action must be pinned to a full commit SHA" >&2
exit 1
fi