mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-02 06:58:52 +08:00
feat: ship verified platform upgrades with channel bundle releases
Package production dependencies per architecture for online and offline upgrades. Validate dependencies and isolated backend startup before readiness, repair once when permitted, and preserve service/data through failed preparation or rollback. Publish release bundles with master images and expose an opt-in develop build sharing the development index across Alpine and Debian images.
This commit is contained in:
@@ -8,6 +8,9 @@ on:
|
||||
# CLI is verified separately; its shared Bash upgrade engine ships in images.
|
||||
- "!cli/**"
|
||||
- "cli/src/internal/maintenance/upgradeArtifacts.cjs"
|
||||
- "cli/src/internal/maintenance/platformBundle.cjs"
|
||||
- "cli/src/internal/maintenance/upgradePrestart.cjs"
|
||||
- "cli/src/internal/maintenance/panelUpgrade.cjs"
|
||||
- "!.github/workflows/cli-package.yml"
|
||||
branches:
|
||||
- "master"
|
||||
@@ -16,6 +19,10 @@ on:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_development_bundles:
|
||||
description: Develop only - build and publish shared develop/debian-dev upgrade packages
|
||||
type: boolean
|
||||
default: false
|
||||
static_sync_only:
|
||||
description: Synchronize an existing static snapshot to GitLab and verify Gitee
|
||||
type: boolean
|
||||
@@ -33,6 +40,14 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Keep master image tags and their bundle indexes in one serialized release.
|
||||
# A rerun may intentionally replace a version, including from the same commit.
|
||||
# Manual development bundle releases are serialized independently of master.
|
||||
# Ordinary develop pushes and Git-tag builds remain independent.
|
||||
concurrency:
|
||||
group: version-images-${{ github.ref == 'refs/heads/master' && 'master' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/develop' && inputs.build_development_bundles && 'develop-bundles') || format('{0}-{1}', github.run_id, github.run_attempt) }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
if: ${{ !inputs.static_sync_only }}
|
||||
@@ -203,6 +218,8 @@ jobs:
|
||||
build-alpine:
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
needs: build-static
|
||||
outputs:
|
||||
image-digest: ${{ steps.image.outputs.digest }}
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
packages: write
|
||||
@@ -268,6 +285,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Build and push (Alpine)
|
||||
id: image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
build-args: |
|
||||
@@ -289,6 +307,8 @@ jobs:
|
||||
build-debian:
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
needs: build-static
|
||||
outputs:
|
||||
image-digest: ${{ steps.image.outputs.digest }}
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
packages: write
|
||||
@@ -353,6 +373,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Build and push (Debian)
|
||||
id: image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
build-args: |
|
||||
@@ -563,3 +584,97 @@ jobs:
|
||||
echo '::error::Could not check the published npm version; refusing to publish.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build-upgrade-bundles:
|
||||
# Development packages are opt-in; both channels use this run's image digests.
|
||||
if: ${{ !inputs.static_sync_only && (github.ref == 'refs/heads/master' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/develop' && inputs.build_development_bundles)) }}
|
||||
needs: [build-alpine, build-debian]
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 90
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { platform: linux/amd64, libc: musl, name: x64-musl }
|
||||
- { platform: linux/arm/v6, libc: musl, name: armv6-musl }
|
||||
- { platform: linux/arm/v7, libc: musl, name: armv7-musl }
|
||||
- { platform: linux/arm64, libc: musl, name: arm64-musl }
|
||||
- { platform: linux/ppc64le, libc: musl, name: ppc64-musl }
|
||||
- { platform: linux/s390x, libc: musl, name: s390x-musl }
|
||||
- { platform: linux/386, libc: musl, name: ia32-musl }
|
||||
- { platform: linux/amd64, libc: glibc, name: x64-glibc }
|
||||
- { platform: linux/arm/v6, libc: glibc, name: armv6-glibc }
|
||||
- { platform: linux/arm/v7, libc: glibc, name: armv7-glibc }
|
||||
- { platform: linux/arm64, libc: glibc, name: arm64-glibc }
|
||||
- { platform: linux/ppc64le, libc: glibc, name: ppc64-glibc }
|
||||
- { platform: linux/s390x, libc: glibc, name: s390x-glibc }
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: docker/setup-qemu-action@v4
|
||||
with:
|
||||
cache-image: false
|
||||
- uses: docker/setup-buildx-action@v4
|
||||
- name: Build and probe the immutable platform package
|
||||
env:
|
||||
ALPINE_DIGEST: ${{ needs.build-alpine.outputs.image-digest }}
|
||||
DEBIAN_DIGEST: ${{ needs.build-debian.outputs.image-digest }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
BUNDLE_LIBC: ${{ matrix.libc }}
|
||||
BUNDLE_PLATFORM: ${{ matrix.platform }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
digest="$ALPINE_DIGEST"
|
||||
if [ "$BUNDLE_LIBC" = glibc ]; then digest="$DEBIAN_DIGEST"; fi
|
||||
test -n "$digest"
|
||||
image="ghcr.io/${GITHUB_REPOSITORY}@${digest}"
|
||||
if [ "$BUNDLE_PLATFORM/$BUNDLE_LIBC" = linux/arm/v6/glibc ]; then
|
||||
# This amd64 helper executes a genuine Raspbian ARMv6 userspace under
|
||||
# ARM1176 QEMU. It is a CI validator, not a user runtime or bundle.
|
||||
echo "$GH_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin
|
||||
validator="ghcr.io/${GITHUB_REPOSITORY}:upgrade-armv6-glibc-validator-${GITHUB_SHA}"
|
||||
mkdir -p output/validator
|
||||
docker buildx build --platform linux/amd64 --build-arg "SOURCE_IMAGE=$image" --file docker/Dockerfile.armv6-glibc --target runtime --tag "$validator" --push --metadata-file output/validator/image.json .
|
||||
validator_digest="$(jq -er '."containerimage.digest"' output/validator/image.json)"
|
||||
docker buildx build --platform linux/amd64 --build-arg "BASE_IMAGE=${validator%:*}@${validator_digest}" --file docker/Dockerfile.upgrade-bundle-armv6-glibc --output type=local,dest=output/upgrade .
|
||||
else
|
||||
docker buildx build --platform "$BUNDLE_PLATFORM" --build-arg "BASE_IMAGE=$image" --file docker/Dockerfile.upgrade-bundle --output type=local,dest=output/upgrade .
|
||||
fi
|
||||
- uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: upgrade-${{ matrix.name }}-${{ github.sha }}
|
||||
path: output/upgrade/*
|
||||
if-no-files-found: error
|
||||
|
||||
publish-upgrade-bundles:
|
||||
if: ${{ !inputs.static_sync_only && (github.ref == 'refs/heads/master' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/develop' && inputs.build_development_bundles)) }}
|
||||
needs: build-upgrade-bundles
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
concurrency:
|
||||
group: upgrade-channel-${{ github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '20'
|
||||
- uses: pnpm/action-setup@v6
|
||||
with:
|
||||
version: '8.3.1'
|
||||
- run: pnpm install --prod --frozen-lockfile
|
||||
- run: npm --prefix cli ci
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: upgrade-*-${{ github.sha }}
|
||||
path: output/upgrade
|
||||
merge-multiple: true
|
||||
- run: node scripts/build-bundle-installer.cjs output/upgrade/install-bundle.cjs
|
||||
- name: Publish complete packages before advancing the channel
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
QL_BUILD_DEVELOPMENT_BUNDLES: ${{ inputs.build_development_bundles }}
|
||||
run: node scripts/publish-upgrade-bundles.cjs output/upgrade "$GITHUB_SHA" "$GITHUB_REPOSITORY" "$GITHUB_REF_NAME"
|
||||
|
||||
Reference in New Issue
Block a user