feat(release): add Alibaba Cloud OSS distribution (#166)

This commit is contained in:
Laodouuu
2026-08-03 21:04:24 +08:00
committed by GitHub
parent 24cea8c511
commit 2e8389f438
13 changed files with 1199 additions and 57 deletions
+60
View File
@@ -0,0 +1,60 @@
name: Test Alibaba Cloud OSS publishing
on:
workflow_dispatch:
jobs:
staging:
name: Verify GitHub OIDC staging access
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
environment:
name: oss-staging
steps:
- uses: actions/checkout@v5
- name: Validate OSS environment configuration
env:
ALIYUN_OIDC_PROVIDER_ARN: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
ALIYUN_ROLE_ARN: ${{ vars.ALIYUN_ROLE_ARN }}
OSS_BUCKET: ${{ vars.OSS_BUCKET }}
OSS_REGION: ${{ vars.OSS_REGION }}
OSS_ENDPOINT: ${{ vars.OSS_ENDPOINT }}
OSS_PUBLIC_BASE_URL: ${{ vars.OSS_PUBLIC_BASE_URL }}
run: |
set -eu
for name in ALIYUN_OIDC_PROVIDER_ARN ALIYUN_ROLE_ARN OSS_BUCKET OSS_REGION OSS_ENDPOINT OSS_PUBLIC_BASE_URL; do
eval "value=\${$name:-}"
if [ -z "$value" ]; then
echo "error: $name is not configured in the oss-staging environment" >&2
exit 1
fi
done
- name: Download and verify ossutil
run: |
sh scripts/install-ossutil.sh "$RUNNER_TEMP/ossutil-bin"
echo "$RUNNER_TEMP/ossutil-bin" >> "$GITHUB_PATH"
- name: Exchange GitHub OIDC token for Alibaba Cloud credentials
id: aliyun
uses: aliyun/configure-aliyun-credentials-action@1e5248c8d5d93a8781ac344a68e19a43341e79e6
with:
oidc-provider-arn: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
role-to-assume: ${{ vars.ALIYUN_ROLE_ARN }}
role-session-name: penguin-oss-staging-${{ github.run_id }}
role-session-expiration: 1800
audience: github-actions
- name: Verify staging access boundaries
env:
OSS_ACCESS_KEY_ID: ${{ steps.aliyun.outputs['aliyun-access-key-id'] }}
OSS_ACCESS_KEY_SECRET: ${{ steps.aliyun.outputs['aliyun-access-key-secret'] }}
OSS_SESSION_TOKEN: ${{ steps.aliyun.outputs['aliyun-security-token'] }}
OSS_BUCKET: ${{ vars.OSS_BUCKET }}
OSS_REGION: ${{ vars.OSS_REGION }}
OSS_ENDPOINT: ${{ vars.OSS_ENDPOINT }}
OSS_PUBLIC_BASE_URL: ${{ vars.OSS_PUBLIC_BASE_URL }}
run: sh scripts/test-oss-staging.sh
+100 -4
View File
@@ -1,8 +1,8 @@
# Release: tag v* -> build the one-line install artifacts and publish a GitHub Release.
# Releases are immutable: once published, assets can never be replaced. A tiny check-release
# job therefore gates the release job on the tag's Release not existing yet — dispatching an
# already-released tag skips the build/upload entirely and only re-runs npm publishing.
# Two parallel jobs (the release job is gated on the existence check):
# already-released tag skips the GitHub build/upload while still retrying the OSS mirror and npm publishing.
# Release jobs (the release job is gated on the existence check):
# - release: build the monorepo -> pnpm deploy a production CLI dir -> assemble penguin/ (bin + lib + web)
# -> one program payload per target (four platform payloads bundling the official Node runtime,
# a win-x64 payload with runtime + MinGit, and a runtime-less universal payload) -> wrap each
@@ -31,6 +31,10 @@
# that failed mid-chain can be re-run as-is after fixing the config.
# npm publishing lives here rather than a separate `on: release: published` workflow: the Release is created
# by this workflow's GITHUB_TOKEN, and GitHub won't trigger other workflows' release events from that.
# - mirror-oss: download the exact GitHub Release assets, verify their checksums, then mirror the same bytes
# to immutable releases/<tag>/ keys in Alibaba Cloud OSS through GitHub OIDC. The GitHub Environment
# `oss-production` supplies the provider/role ARNs and OSS settings. latest.json is uploaded last and only
# when the tag is still GitHub's current latest Release. Manual retries also work after a Release exists.
name: Release
on:
@@ -54,7 +58,7 @@ env:
jobs:
# Skip the build/upload when the tag's Release already exists (immutable releases forbid
# replacing assets, so re-uploading can only fail; npm publishing is idempotent on its own).
# replacing assets, so re-uploading can only fail; OSS mirroring and npm publishing are idempotent).
check-release:
runs-on: ubuntu-latest
permissions:
@@ -278,7 +282,7 @@ jobs:
- name: Generate SHA256SUMS
run: |
cd dist-artifacts
sha256sum *.tar.gz *.zip > SHA256SUMS
sha256sum -- *.tar.gz *.zip > SHA256SUMS
# Release notes come from changelog/<version>/RELEASE.md, written during release preparation and
# committed BEFORE the tag (the release job runs on the tag's checkout, so a file added afterwards
@@ -319,6 +323,98 @@ jobs:
install.sh
install.ps1
mirror-oss:
name: Mirror GitHub Release to Alibaba Cloud OSS
needs: [check-release, release]
if: >-
${{ always() && needs.check-release.result == 'success' &&
(needs.release.result == 'success' || needs.release.result == 'skipped') }}
runs-on: ubuntu-latest
concurrency:
group: penguin-oss-production
cancel-in-progress: false
permissions:
contents: read
id-token: write
environment:
name: oss-production
url: ${{ vars.OSS_PUBLIC_BASE_URL }}
steps:
# On workflow_dispatch, use the selected branch's current mirror scripts while downloading
# the requested tag's immutable Release assets. A tag push naturally checks out that tag.
- uses: actions/checkout@v5
- name: Validate OSS environment configuration
env:
ALIYUN_OIDC_PROVIDER_ARN: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
ALIYUN_ROLE_ARN: ${{ vars.ALIYUN_ROLE_ARN }}
OSS_BUCKET: ${{ vars.OSS_BUCKET }}
OSS_REGION: ${{ vars.OSS_REGION }}
OSS_ENDPOINT: ${{ vars.OSS_ENDPOINT }}
OSS_PUBLIC_BASE_URL: ${{ vars.OSS_PUBLIC_BASE_URL }}
run: |
set -eu
for name in ALIYUN_OIDC_PROVIDER_ARN ALIYUN_ROLE_ARN OSS_BUCKET OSS_REGION OSS_ENDPOINT OSS_PUBLIC_BASE_URL; do
eval "value=\${$name:-}"
if [ -z "$value" ]; then
echo "error: $name is not configured in the oss-production environment" >&2
exit 1
fi
done
- name: Download and verify ossutil
run: |
sh scripts/install-ossutil.sh "$RUNNER_TEMP/ossutil-bin"
echo "$RUNNER_TEMP/ossutil-bin" >> "$GITHUB_PATH"
# Pinned v1 commit. audience must match the client ID configured on the Alibaba Cloud
# OIDC provider; this project deliberately uses `github-actions`.
- name: Exchange GitHub OIDC token for Alibaba Cloud credentials
id: aliyun
uses: aliyun/configure-aliyun-credentials-action@1e5248c8d5d93a8781ac344a68e19a43341e79e6
with:
oidc-provider-arn: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
role-to-assume: ${{ vars.ALIYUN_ROLE_ARN }}
role-session-name: penguin-oss-${{ github.run_id }}
role-session-expiration: 1800
audience: github-actions
- name: Download exact GitHub Release assets
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
run: |
mkdir -p release-assets
gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" --dir release-assets
- name: Determine whether the tag is the latest Release
id: latest
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
run: |
LATEST_TAG="$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq .tagName)"
if [ "$TAG" = "$LATEST_TAG" ]; then
echo "update=true" >> "$GITHUB_OUTPUT"
else
echo "update=false" >> "$GITHUB_OUTPUT"
echo "$TAG will be mirrored without replacing latest.json (current latest: $LATEST_TAG)."
fi
- name: Mirror and verify OSS objects
env:
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
GH_TOKEN: ${{ github.token }}
OSS_ACCESS_KEY_ID: ${{ steps.aliyun.outputs['aliyun-access-key-id'] }}
OSS_ACCESS_KEY_SECRET: ${{ steps.aliyun.outputs['aliyun-access-key-secret'] }}
OSS_SESSION_TOKEN: ${{ steps.aliyun.outputs['aliyun-security-token'] }}
OSS_BUCKET: ${{ vars.OSS_BUCKET }}
OSS_REGION: ${{ vars.OSS_REGION }}
OSS_ENDPOINT: ${{ vars.OSS_ENDPOINT }}
OSS_PUBLIC_BASE_URL: ${{ vars.OSS_PUBLIC_BASE_URL }}
run: sh scripts/publish-release-to-oss.sh release-assets "$TAG" "${{ steps.latest.outputs.update }}"
publish-npm:
name: Publish npm packages
runs-on: ubuntu-latest