refactor(ci): extract workflow scripts

This commit is contained in:
Haitao Pan 2026-03-18 16:37:21 +08:00
parent 9569df6a27
commit 3f4f7d9c92
11 changed files with 157 additions and 78 deletions

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
: "${ORG:?ORG is required}"
: "${MANIFEST_DIGEST:?MANIFEST_DIGEST is required}"
: "${TARGET_NS:?TARGET_NS is required}"
: "${GHCR_USERNAME:?GHCR_USERNAME is required}"
: "${GHCR_TOKEN:?GHCR_TOKEN is required}"
: "${DOCKERHUB_USERNAME:?DOCKERHUB_USERNAME is required}"
: "${DOCKERHUB_TOKEN:?DOCKERHUB_TOKEN is required}"
sudo apt-get update -y
sudo apt-get install -y skopeo
src="docker://ghcr.io/${ORG}/dashboard@${MANIFEST_DIGEST}"
dst="docker://docker.io/${TARGET_NS}/dashboard:latest"
skopeo login ghcr.io -u "${GHCR_USERNAME}" -p "${GHCR_TOKEN}"
skopeo login docker.io -u "${DOCKERHUB_USERNAME}" -p "${DOCKERHUB_TOKEN}"
skopeo copy --all "${src}" "${dst}"

View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
: "${REGISTRY:?REGISTRY is required}"
: "${ORG:?ORG is required}"
: "${IMAGE_SHA:?IMAGE_SHA is required}"
: "${AMD_DIGEST:?AMD_DIGEST is required}"
: "${ARM_DIGEST:?ARM_DIGEST is required}"
: "${TAGS_CSV:?TAGS_CSV is required}"
: "${GITHUB_ENV:?GITHUB_ENV is required}"
src_amd="${REGISTRY}/${ORG}/dashboard:build-${IMAGE_SHA}-linux-amd64@${AMD_DIGEST}"
src_arm="${REGISTRY}/${ORG}/dashboard:build-${IMAGE_SHA}-linux-arm64@${ARM_DIGEST}"
first_tag=""
while IFS= read -r tag; do
[ -n "${tag}" ] || continue
if [ -z "${first_tag}" ]; then
first_tag="${tag}"
fi
docker buildx imagetools create -t "${tag}" "${src_amd}" "${src_arm}"
done < <(printf '%s' "${TAGS_CSV}" | tr ',' '\n')
[ -n "${first_tag}" ] || {
echo "No tags were generated." >&2
exit 1
}
manifest_digest="$(docker buildx imagetools inspect "${first_tag}" --format '{{.Digest}}')"
echo "MANIFEST_DIGEST=${manifest_digest}" >> "${GITHUB_ENV}"
echo "FINAL_TAG=${first_tag}" >> "${GITHUB_ENV}"

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
: "${DIGEST_FILE:?DIGEST_FILE is required}"
: "${GITHUB_ENV:?GITHUB_ENV is required}"
echo "IMAGE_DIGEST=$(tr -d '\n' < "${DIGEST_FILE}")" >> "${GITHUB_ENV}"

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
: "${AMD_DIGEST_FILE:?AMD_DIGEST_FILE is required}"
: "${ARM_DIGEST_FILE:?ARM_DIGEST_FILE is required}"
: "${GITHUB_ENV:?GITHUB_ENV is required}"
echo "AMD_DIGEST=$(tr -d '\n' < "${AMD_DIGEST_FILE}")" >> "${GITHUB_ENV}"
echo "ARM_DIGEST=$(tr -d '\n' < "${ARM_DIGEST_FILE}")" >> "${GITHUB_ENV}"

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
: "${IMAGE_DIGEST:?IMAGE_DIGEST is required}"
: "${OUTPUT_FILE:?OUTPUT_FILE is required}"
printf '%s\n' "${IMAGE_DIGEST}" > "${OUTPUT_FILE}"

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
: "${REGISTRY:?REGISTRY is required}"
: "${ORG:?ORG is required}"
: "${SERVICE_NAME:?SERVICE_NAME is required}"
: "${IMAGE_DIGEST:?IMAGE_DIGEST is required}"
: "${IMAGE_SHA:?IMAGE_SHA is required}"
: "${IMAGE_ARTIFACT:?IMAGE_ARTIFACT is required}"
: "${GITHUB_ENV:?GITHUB_ENV is required}"
echo "IMG=${REGISTRY}/${ORG}/${SERVICE_NAME}:build-${IMAGE_SHA}-${IMAGE_ARTIFACT}@${IMAGE_DIGEST}" >> "${GITHUB_ENV}"

View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
: "${IMAGE:?IMAGE is required}"
: "${KNOWLEDGE_CONTENT_DIR:?KNOWLEDGE_CONTENT_DIR is required}"
docker pull "${IMAGE}"
docker run --rm \
-v "${KNOWLEDGE_CONTENT_DIR}:/app/dashboard/src/content/blog:ro" \
"${IMAGE}" \
sh -c 'test -d /app/dashboard/src/content/blog'

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
: "${TAG:?TAG is required}"
: "${IMAGE_LIST_FILE:?IMAGE_LIST_FILE is required}"
while IFS= read -r image; do
[ -n "${image}" ] || continue
echo "Checking ${image}:${TAG}"
docker manifest inspect "${image}:${TAG}" > /dev/null
docker pull "${image}:${TAG}" > /dev/null
done < "${IMAGE_LIST_FILE}"

12
.github/scripts/check-image/images.txt vendored Normal file
View File

@ -0,0 +1,12 @@
ghcr.io/cloud-neutral-toolkit/openresty-geoip
ghcr.io/cloud-neutral-toolkit/postgres-runtime
ghcr.io/cloud-neutral-toolkit/account
ghcr.io/cloud-neutral-toolkit/dashboard
ghcr.io/cloud-neutral-toolkit/rag-server
ghcr.io/cloud-neutral-toolkit/xcontrol-init
docker.io/cloudneutral/openresty-geoip
docker.io/cloudneutral/postgres-runtime
docker.io/cloudneutral/account
docker.io/cloudneutral/dashboard
docker.io/cloudneutral/rag-server
docker.io/cloudneutral/xcontrol-init

View File

@ -122,9 +122,10 @@ jobs:
CONTENTLAYER_BUILD=true
- name: Record digest
run: |
set -euo pipefail
echo "${{ steps.build.outputs.digest }}" > digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt
env:
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
OUTPUT_FILE: digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt
run: bash .github/scripts/build-images/record-digest.sh
- uses: actions/upload-artifact@v4
with:
@ -152,14 +153,16 @@ jobs:
name: digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}
- name: Load image digest
run: |
set -euo pipefail
echo "IMAGE_DIGEST=$(cat digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt)" >> "$GITHUB_ENV"
env:
DIGEST_FILE: digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt
run: bash .github/scripts/build-images/load-image-digest.sh
- name: Set image ref
run: |
set -euo pipefail
echo "IMG=${{ env.REGISTRY }}/${{ env.ORG }}/${{ matrix.service.name }}:build-${{ github.sha }}-${{ matrix.arch.artifact }}@${{ env.IMAGE_DIGEST }}" >> "$GITHUB_ENV"
env:
SERVICE_NAME: ${{ matrix.service.name }}
IMAGE_SHA: ${{ github.sha }}
IMAGE_ARTIFACT: ${{ matrix.arch.artifact }}
run: bash .github/scripts/build-images/set-image-ref.sh
- uses: anchore/sbom-action@v0
with:
@ -216,10 +219,10 @@ jobs:
name: digest-dashboard-linux-arm64
- name: Load digests
run: |
set -euo pipefail
echo "AMD_DIGEST=$(cat digest-dashboard-linux-amd64.txt)" >> "$GITHUB_ENV"
echo "ARM_DIGEST=$(cat digest-dashboard-linux-arm64.txt)" >> "$GITHUB_ENV"
env:
AMD_DIGEST_FILE: digest-dashboard-linux-amd64.txt
ARM_DIGEST_FILE: digest-dashboard-linux-arm64.txt
run: bash .github/scripts/build-images/load-manifest-digests.sh
- name: Generate Auto Tags
id: meta
@ -236,23 +239,10 @@ jobs:
- name: Create & Push Multi-Arch Manifests (GHCR)
if: matrix.registry == 'ghcr.io'
run: |
set -euo pipefail
SRC_AMD="${{ env.REGISTRY }}/${{ env.ORG }}/dashboard:build-${{ github.sha }}-linux-amd64@${{ env.AMD_DIGEST }}"
SRC_ARM="${{ env.REGISTRY }}/${{ env.ORG }}/dashboard:build-${{ github.sha }}-linux-arm64@${{ env.ARM_DIGEST }}"
FIRST_TAG=""
echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | while read -r TAG; do
[ -z "$TAG" ] && continue
if [ -z "$FIRST_TAG" ]; then FIRST_TAG="$TAG"; fi
docker buildx imagetools create -t "$TAG" "$SRC_AMD" "$SRC_ARM"
done
TAG1="$(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | head -n 1)"
DIGEST="$(docker buildx imagetools inspect "$TAG1" --format '{{.Digest}}')"
echo "MANIFEST_DIGEST=$DIGEST" >> "$GITHUB_ENV"
echo "FINAL_TAG=$TAG1" >> "$GITHUB_ENV"
env:
IMAGE_SHA: ${{ github.sha }}
TAGS_CSV: ${{ steps.meta.outputs.tags }}
run: bash .github/scripts/build-images/create-ghcr-manifest.sh
- name: Clone knowledge content
if: matrix.registry == 'ghcr.io'
@ -260,14 +250,10 @@ jobs:
- name: Validate blog content mount
if: matrix.registry == 'ghcr.io'
run: |
set -euo pipefail
IMAGE="${{ env.REGISTRY }}/${{ env.ORG }}/dashboard@${{ env.MANIFEST_DIGEST }}"
docker pull "$IMAGE"
docker run --rm \
-v "${{ github.workspace }}/knowledge/content:/app/dashboard/src/content/blog:ro" \
"$IMAGE" \
sh -c 'test -d /app/dashboard/src/content/blog'
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.ORG }}/dashboard@${{ env.MANIFEST_DIGEST }}
KNOWLEDGE_CONTENT_DIR: ${{ github.workspace }}/knowledge/content
run: bash .github/scripts/build-images/validate-blog-content-mount.sh
- name: Login to Docker Hub
if: matrix.registry == 'docker.io'
@ -281,16 +267,8 @@ jobs:
if: matrix.registry == 'docker.io'
env:
TARGET_NS: ${{ inputs.dockerhub_namespace || github.event.inputs.dockerhub_namespace || 'cloudneutral' }}
run: |
set -euo pipefail
sudo apt-get update -y
sudo apt-get install -y skopeo
SRC="docker://ghcr.io/${{ env.ORG }}/dashboard@${{ env.MANIFEST_DIGEST }}"
DST="docker://docker.io/${TARGET_NS}/dashboard:latest"
skopeo login ghcr.io -u "${{ github.actor }}" -p "${{ secrets.GITHUB_TOKEN }}"
skopeo login docker.io -u "${{ secrets.DOCKERHUB_USERNAME }}" -p "${{ secrets.DOCKERHUB_TOKEN }}"
skopeo copy --all "$SRC" "$DST"
GHCR_USERNAME: ${{ github.actor }}
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
run: bash .github/scripts/build-images/copy-image-to-dockerhub.sh

View File

@ -16,34 +16,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Authenticate to GHCR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "$GITHUB_TOKEN" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Check images exist and are pullable
env:
TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
IMAGES=(
"ghcr.io/cloud-neutral-toolkit/openresty-geoip"
"ghcr.io/cloud-neutral-toolkit/postgres-runtime"
"ghcr.io/cloud-neutral-toolkit/account"
"ghcr.io/cloud-neutral-toolkit/dashboard"
"ghcr.io/cloud-neutral-toolkit/rag-server"
"ghcr.io/cloud-neutral-toolkit/xcontrol-init"
"docker.io/cloudneutral/openresty-geoip"
"docker.io/cloudneutral/postgres-runtime"
"docker.io/cloudneutral/account"
"docker.io/cloudneutral/dashboard"
"docker.io/cloudneutral/rag-server"
"docker.io/cloudneutral/xcontrol-init"
)
for IMAGE in "${IMAGES[@]}"; do
echo "Checking ${IMAGE}:${TAG}"
docker manifest inspect "${IMAGE}:${TAG}" > /dev/null
docker pull "${IMAGE}:${TAG}" > /dev/null
done
IMAGE_LIST_FILE: .github/scripts/check-image/images.txt
run: bash .github/scripts/check-image/check-images.sh