mirror of
https://github.com/hectorqin/reader.git
synced 2026-11-11 21:41:02 +08:00
- main is the long-lived development branch: release.yml no longer runs on a push to it, only on v* tags and workflow_dispatch. ci.yml now runs on every branch push, main included. - android-actions/setup-android's default package list includes `tools`, which current command-line tools no longer carry, so sdkmanager failed; install exactly platform-tools, android-35 and build-tools 35.0.1. - reader-chrome.test.ts left its React roots mounted; a scheduled commit could land after jsdom teardown and fail the run with an unhandled "Right-hand side of 'instanceof' is not an object" (all tests passing). Unmount in afterEach. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
125 lines
4.1 KiB
YAML
125 lines
4.1 KiB
YAML
# Release the single-container image (server + web) to Docker Hub for amd64 and arm64.
|
|
#
|
|
# tag v1.2.3 -> hectorqin/reader-pro:1.2.3, :1.2, :latest, :sha-<short>
|
|
# manual run -> the chosen branch's name (e.g. :main) and :sha-<short>
|
|
#
|
|
# Never on a plain push: main is the long-lived development branch, and a release
|
|
# is a decision (a tag, or "Run workflow" in the Actions tab), not a side effect.
|
|
#
|
|
# CI (ci.yml) runs first; nothing is published from a red build. Each architecture
|
|
# is built on its own native runner — the arm64 image under QEMU would run npm ci
|
|
# and the Vite build emulated, which is many times slower — and pushed by digest,
|
|
# then one job stitches the digests into the multi-arch tags.
|
|
#
|
|
# Needs repository secrets DOCKER_USERNAME and DOCKER_PASSWORD (a Docker Hub
|
|
# password or access token with read/write on hectorqin/reader-pro).
|
|
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags: ['v*']
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: release-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
IMAGE: hectorqin/reader-pro
|
|
|
|
jobs:
|
|
ci:
|
|
uses: ./.github/workflows/ci.yml
|
|
|
|
build:
|
|
name: Image · ${{ matrix.platform }}
|
|
needs: ci
|
|
strategy:
|
|
fail-fast: true
|
|
matrix:
|
|
include:
|
|
- platform: linux/amd64
|
|
runner: ubuntu-24.04
|
|
- platform: linux/arm64
|
|
runner: ubuntu-24.04-arm
|
|
runs-on: ${{ matrix.runner }}
|
|
steps:
|
|
- name: Platform slug
|
|
run: echo "PLATFORM_PAIR=${PLATFORM//\//-}" >> "$GITHUB_ENV"
|
|
env:
|
|
PLATFORM: ${{ matrix.platform }}
|
|
- uses: actions/checkout@v5
|
|
- id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.IMAGE }}
|
|
- uses: docker/login-action@v3
|
|
with:
|
|
username: ${{ secrets.DOCKER_USERNAME }}
|
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
- uses: docker/setup-buildx-action@v3
|
|
- id: build
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: server/Dockerfile
|
|
platforms: ${{ matrix.platform }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
|
cache-from: type=gha,scope=${{ env.PLATFORM_PAIR }}
|
|
cache-to: type=gha,mode=max,scope=${{ env.PLATFORM_PAIR }}
|
|
- name: Record digest
|
|
run: |
|
|
mkdir -p "$RUNNER_TEMP/digests"
|
|
touch "$RUNNER_TEMP/digests/${DIGEST#sha256:}"
|
|
env:
|
|
DIGEST: ${{ steps.build.outputs.digest }}
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: digests-${{ env.PLATFORM_PAIR }}
|
|
path: ${{ runner.temp }}/digests/*
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
publish:
|
|
name: Image · multi-arch tags
|
|
needs: build
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
path: ${{ runner.temp }}/digests
|
|
pattern: digests-*
|
|
merge-multiple: true
|
|
- id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.IMAGE }}
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
type=sha
|
|
flavor: |
|
|
latest=${{ startsWith(github.ref, 'refs/tags/v') }}
|
|
- uses: docker/login-action@v3
|
|
with:
|
|
username: ${{ secrets.DOCKER_USERNAME }}
|
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
- uses: docker/setup-buildx-action@v3
|
|
- name: Create manifest list and push
|
|
working-directory: ${{ runner.temp }}/digests
|
|
run: |
|
|
tags=()
|
|
while read -r tag; do tags+=(-t "$tag"); done < <(jq -r '.tags[]' <<< "$DOCKER_METADATA_OUTPUT_JSON")
|
|
refs=()
|
|
for digest in *; do refs+=("$IMAGE@sha256:$digest"); done
|
|
docker buildx imagetools create "${tags[@]}" "${refs[@]}"
|
|
- name: Inspect
|
|
run: docker buildx imagetools inspect "$IMAGE:$VERSION"
|
|
env:
|
|
VERSION: ${{ steps.meta.outputs.version }}
|