feat: publish v1.0.0-rc.36-custom.1

This commit is contained in:
Codex committed 2026-09-11 05:07:48 +08:00
commit 3a7e8f3b54
2381 files changed
+551494

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
name: CI
on:
pull_request:
types: [opened, synchronize, closed]
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
backend:
name: Backend vet, build, and test
if: github.event.action != 'closed' || github.event.pull_request.merged == true
runs-on: ubuntu-latest
timeout-minutes: 15
env:
GOWORK: 'off'
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: ${{ github.event.pull_request.base.repo.full_name }}
ref: ${{ github.event.action == 'closed' && github.event.pull_request.base.ref || github.ref }}
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version-file: go.mod
cache-dependency-path: |
go.sum
relaykit/go.sum
- name: Create frontend embed placeholder
run: |
mkdir -p web/dist
touch web/dist/index.html
- name: Vet root module
run: go vet ./...
- name: Vet relaykit independently
working-directory: relaykit
run: go vet ./...
- name: Build root module
run: go build ./...
- name: Build relaykit independently
working-directory: relaykit
run: go build ./...
- name: Test root and relaykit modules
run: make test
frontend:
name: Frontend typecheck and test
if: github.event.action != 'closed' || github.event.pull_request.merged == true
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: web
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: ${{ github.event.pull_request.base.repo.full_name }}
ref: ${{ github.event.action == 'closed' && github.event.pull_request.base.ref || github.ref }}
- name: Set up Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.4.0'
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Typecheck
run: bun run typecheck
- name: Test
run: bun run test
+152
View File
@@ -0,0 +1,152 @@
name: Publish Docker image (Multi-arch)
on:
push:
tags:
- '*'
- '!nightly*'
workflow_dispatch:
inputs:
tag:
description: 'Tag name to build (e.g., v0.10.8-alpha.3)'
required: true
type: string
jobs:
build_single_arch:
name: Build & push (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-latest
- arch: arm64
platform: linux/arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
outputs:
tag: ${{ steps.version.outputs.tag }}
permissions:
packages: write
contents: read
id-token: write
steps:
- name: Check out
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: ${{ github.event_name == 'workflow_dispatch' && 0 || 1 }}
ref: ${{ github.event.inputs.tag || github.ref }}
- name: Resolve tag & write VERSION
id: version
run: |
if [ -n "${{ github.event.inputs.tag }}" ]; then
TAG="${{ github.event.inputs.tag }}"
if ! git rev-parse "refs/tags/$TAG" >/dev/null 2>&1; then
echo "::error::Tag '$TAG' does not exist"
exit 1
fi
else
TAG=${GITHUB_REF#refs/tags/}
fi
echo "TAG=${TAG}" >> $GITHUB_ENV
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "${TAG}" > VERSION
echo "Building tag: ${TAG} for ${{ matrix.arch }}"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Log in to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (labels)
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: calciumion/new-api
- name: Build & push
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
platforms: ${{ matrix.platform }}
push: true
tags: |
calciumion/new-api:${{ env.TAG }}-${{ matrix.arch }}
calciumion/new-api:latest-${{ matrix.arch }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: mode=max
sbom: true
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Sign image with cosign
run: cosign sign --yes calciumion/new-api@${{ steps.build.outputs.digest }}
- name: Image summary
run: |
echo "### Docker Image Digest (${{ matrix.arch }})" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "calciumion/new-api:${TAG}-${{ matrix.arch }}" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.build.outputs.digest }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
create_manifests:
name: Create multi-arch manifests
needs: [build_single_arch]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
permissions:
id-token: write
steps:
- name: Set version
run: echo "TAG=${{ needs.build_single_arch.outputs.tag }}" >> $GITHUB_ENV
- name: Log in to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & push manifest (version)
run: |
docker buildx imagetools create \
-t calciumion/new-api:${TAG} \
calciumion/new-api:${TAG}-amd64 \
calciumion/new-api:${TAG}-arm64
- name: Create & push manifest (latest)
run: |
docker buildx imagetools create \
-t calciumion/new-api:latest \
calciumion/new-api:latest-amd64 \
calciumion/new-api:latest-arm64
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Sign manifests with cosign
run: |
cosign sign --yes calciumion/new-api:${TAG}
cosign sign --yes calciumion/new-api:latest
- name: Manifest summary
run: |
echo "### Multi-arch Manifest" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
docker buildx imagetools inspect calciumion/new-api:${TAG} >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
+170
View File
@@ -0,0 +1,170 @@
name: Publish Docker image (manual branch)
on:
workflow_dispatch:
inputs:
branch:
description: "Branch name to build (e.g. alpha, nightly)"
required: true
type: string
jobs:
prepare:
name: Prepare Docker tags
runs-on: ubuntu-latest
outputs:
branch: ${{ steps.version.outputs.branch }}
sha: ${{ steps.version.outputs.sha }}
tag_prefix: ${{ steps.version.outputs.tag_prefix }}
version: ${{ steps.version.outputs.version }}
permissions:
contents: read
steps:
- name: Check out branch
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
ref: ${{ inputs.branch }}
- name: Resolve Docker tags
id: version
env:
BRANCH_NAME: ${{ inputs.branch }}
run: |
TAG_PREFIX=$(printf '%s' "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9_.-]+/-/g; s/^[.-]+//; s/[.-]+$//')
TAG_PREFIX=${TAG_PREFIX:0:105}
TAG_PREFIX=$(printf '%s' "$TAG_PREFIX" | sed -E 's/[.-]+$//')
if [ -z "$TAG_PREFIX" ]; then
echo "::error::Branch '$BRANCH_NAME' cannot be converted to a valid Docker tag prefix"
exit 1
fi
SHA=$(git rev-parse HEAD)
SHORT_SHA=$(git rev-parse --short HEAD)
VERSION="${TAG_PREFIX}-$(date +'%Y%m%d')-${SHORT_SHA}"
echo "branch=$BRANCH_NAME" >> "$GITHUB_OUTPUT"
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
echo "tag_prefix=$TAG_PREFIX" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Prepared Docker tags for $BRANCH_NAME at $SHORT_SHA"
build_single_arch:
name: Build & push (${{ matrix.arch }}) [native]
needs: [prepare]
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-latest
- arch: arm64
platform: linux/arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
permissions:
contents: read
id-token: write
steps:
- name: Check out branch
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
ref: ${{ needs.prepare.outputs.sha }}
- name: Write VERSION
run: |
echo "${{ needs.prepare.outputs.version }}" > VERSION
echo "Publishing version: ${{ needs.prepare.outputs.version }} for ${{ matrix.arch }}"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Log in to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (labels)
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: |
calciumion/new-api
- name: Build & push single-arch
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
platforms: ${{ matrix.platform }}
push: true
tags: |
calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }}-${{ matrix.arch }}
calciumion/new-api:${{ needs.prepare.outputs.version }}-${{ matrix.arch }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: mode=max
sbom: true
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Sign image with cosign
run: cosign sign --yes calciumion/new-api@${{ steps.build.outputs.digest }}
- name: Output digest
run: |
echo "### Docker Image Digest (${{ matrix.arch }})" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }}-${{ matrix.arch }}" >> $GITHUB_STEP_SUMMARY
echo "calciumion/new-api:${{ needs.prepare.outputs.version }}-${{ matrix.arch }}" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.build.outputs.digest }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
create_manifests:
name: Create multi-arch manifests (Docker Hub)
needs: [prepare, build_single_arch]
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Log in to Docker Hub
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & push manifest (Docker Hub - branch)
run: |
docker buildx imagetools create \
-t calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }} \
calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }}-amd64 \
calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }}-arm64
- name: Create & push manifest (Docker Hub - versioned)
run: |
docker buildx imagetools create \
-t calciumion/new-api:${{ needs.prepare.outputs.version }} \
calciumion/new-api:${{ needs.prepare.outputs.version }}-amd64 \
calciumion/new-api:${{ needs.prepare.outputs.version }}-arm64
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Sign manifests with cosign
run: |
cosign sign --yes calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }}
cosign sign --yes calciumion/new-api:${{ needs.prepare.outputs.version }}
- name: Output manifest digest
run: |
echo "### Multi-arch Manifest Digests" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
docker buildx imagetools inspect calciumion/new-api:${{ needs.prepare.outputs.tag_prefix }} >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
docker buildx imagetools inspect calciumion/new-api:${{ needs.prepare.outputs.version }} >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
+141
View File
@@ -0,0 +1,141 @@
name: Build Electron App
on:
push:
tags:
- '*' # Triggers on version tags like v1.0.0
- '!*-*' # Ignore pre-release tags like v1.0.0-beta
- '!*-alpha*' # Ignore alpha tags like v1.0.0-alpha
workflow_dispatch: # Allows manual triggering
jobs:
build:
strategy:
matrix:
# os: [macos-latest, windows-latest]
os: [windows-latest]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.4.0'
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
- name: Setup Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version: '>=1.25.1'
- name: Build frontend
env:
CI: ""
NODE_OPTIONS: "--max-old-space-size=4096"
run: |
cd web
bun install --frozen-lockfile
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(git describe --tags) bun run build
cd ..
# - name: Build Go binary (macos/Linux)
# if: runner.os != 'Windows'
# run: |
# go mod download
# go build -ldflags "-s -w -X 'new-api/common.Version=$(git describe --tags)' -extldflags '-static'" -o new-api
- name: Build Go binary (Windows)
if: runner.os == 'Windows'
run: |
go mod download
go build -ldflags "-s -w -X 'new-api/common.Version=$(git describe --tags)'" -o new-api.exe
- name: Update Electron version
run: |
cd electron
VERSION=$(git describe --tags)
VERSION=${VERSION#v} # Remove 'v' prefix if present
# Convert to valid semver: take first 3 components and convert rest to prerelease format
# e.g., 0.9.3-patch.1 -> 0.9.3-patch.1
if [[ $VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(.*)$ ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
REST=${BASH_REMATCH[4]}
VERSION="$MAJOR.$MINOR.$PATCH"
# If there's extra content, append it without adding -dev
if [[ -n "$REST" ]]; then
VERSION="$VERSION$REST"
fi
fi
npm version $VERSION --no-git-tag-version --allow-same-version
- name: Install Electron dependencies
run: |
cd electron
npm install
# - name: Build Electron app (macOS)
# if: runner.os == 'macOS'
# run: |
# cd electron
# npm run build:mac
# env:
# CSC_IDENTITY_AUTO_DISCOVERY: false # Skip code signing
- name: Build Electron app (Windows)
if: runner.os == 'Windows'
run: |
cd electron
npm run build:win
# - name: Upload artifacts (macOS)
# if: runner.os == 'macOS'
# uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# with:
# name: macos-build
# path: |
# electron/dist/*.dmg
# electron/dist/*.zip
- name: Upload artifacts (Windows)
if: runner.os == 'Windows'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: windows-build
path: |
electron/dist/*.exe
release:
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- name: Upload to Release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
files: |
windows-build/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+168
View File
@@ -0,0 +1,168 @@
name: Release (Linux, macOS, Windows)
permissions:
contents: write
on:
workflow_dispatch:
inputs:
name:
description: 'reason'
required: false
push:
tags:
- '*'
- '!*-alpha*'
jobs:
linux:
name: Linux Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Determine Version
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
else
VERSION=$(git describe --tags --match 'v[0-9]*')
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.4.0'
- name: Build Frontend
env:
CI: ""
run: |
cd web
bun install --frozen-lockfile
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$VERSION bun run build
cd ..
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version: '>=1.25.1'
- name: Build Backend (amd64)
run: |
go mod download
go build -ldflags "-s -w -X 'new-api/common.Version=$VERSION' -extldflags '-static'" -o new-api-$VERSION
- name: Build Backend (arm64)
run: |
sudo apt-get update
DEBIAN_FRONTEND=noninteractive sudo apt-get install -y gcc-aarch64-linux-gnu
CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X 'new-api/common.Version=$VERSION' -extldflags '-static'" -o new-api-arm64-$VERSION
- name: Generate checksums
run: sha256sum new-api-* > checksums-linux.txt
- name: Release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
new-api-*
checksums-linux.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
macos:
name: macOS Release
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Determine Version
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
else
VERSION=$(git describe --tags --match 'v[0-9]*')
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.4.0'
- name: Build Frontend
env:
CI: ""
NODE_OPTIONS: "--max-old-space-size=4096"
run: |
cd web
bun install --frozen-lockfile
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$VERSION bun run build
cd ..
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version: '>=1.25.1'
- name: Build Backend
run: |
go mod download
go build -ldflags "-X 'new-api/common.Version=$VERSION'" -o new-api-macos-$VERSION
- name: Generate checksums
run: shasum -a 256 new-api-macos-* > checksums-macos.txt
- name: Release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
new-api-macos-*
checksums-macos.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
windows:
name: Windows Release
runs-on: windows-latest
defaults:
run:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Determine Version
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
else
VERSION=$(git describe --tags --match 'v[0-9]*')
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.4.0'
- name: Build Frontend
env:
CI: ""
run: |
cd web
bun install --frozen-lockfile
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$VERSION bun run build
cd ..
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version: '>=1.25.1'
- name: Build Backend
run: |
go mod download
go build -ldflags "-s -w -X 'new-api/common.Version=$VERSION'" -o new-api-$VERSION.exe
- name: Generate checksums
run: sha256sum new-api-*.exe > checksums-windows.txt
- name: Release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
new-api-*.exe
checksums-windows.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,250 @@
name: Sync Release to GitCode
permissions:
actions: read
contents: read
on:
workflow_dispatch:
inputs:
tag_name:
description: GitHub release tag to sync
required: true
type: string
sync_files:
description: Sync GitHub release files to GitCode
required: false
default: false
type: boolean
concurrency:
group: gitcode-release-${{ inputs.tag_name }}
cancel-in-progress: false
jobs:
prepare-release:
name: Create or update GitCode release
if: ${{ vars.GITCODE_REPOSITORY != '' }}
runs-on: ubuntu-latest
timeout-minutes: 90
outputs:
release_tag: ${{ steps.release.outputs.tag }}
release_body: ${{ steps.release.outputs.body }}
release_prerelease: ${{ steps.release.outputs.prerelease }}
release_asset_matrix: ${{ steps.assets.outputs.matrix }}
has_release_assets: ${{ steps.assets.outputs.has_assets }}
steps:
- name: Create or update GitCode release
id: release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITCODE_REPOSITORY: ${{ vars.GITCODE_REPOSITORY }}
GITCODE_TOKEN: ${{ secrets.GITCODE_TOKEN }}
RELEASE_TAG: ${{ inputs.tag_name }}
run: |
set -euo pipefail
release_json="$(
gh release view "$RELEASE_TAG" \
--repo "$GITHUB_REPOSITORY" \
--json body,isPrerelease
)"
release_body="$(jq -r '.body // ""' <<< "$release_json" | sed "s/'/’/g")"
release_prerelease="$(jq -r '.isPrerelease' <<< "$release_json")"
if [[ "$release_prerelease" == "true" ]]; then
release_status=pre
else
release_status=latest
fi
gitcode_release_json="$(mktemp)"
gitcode_release_status="$(
curl -L -sS -o "$gitcode_release_json" -w "%{http_code}" \
-H "PRIVATE-TOKEN: $GITCODE_TOKEN" \
-H "Accept: application/json" \
"https://api.gitcode.com/api/v5/repos/$GITCODE_REPOSITORY/releases/tags/$RELEASE_TAG"
)"
request_json="$(mktemp)"
case "$gitcode_release_status" in
200)
request_method=PATCH
request_url="https://api.gitcode.com/api/v5/repos/$GITCODE_REPOSITORY/releases/$RELEASE_TAG"
request_action=update
success_action=updated
jq -n \
--arg tag_name "$RELEASE_TAG" \
--arg name "$RELEASE_TAG" \
--arg body "$release_body" \
--arg release_status "$release_status" \
'{
tag_name: $tag_name,
name: $name,
body: $body,
release_status: $release_status
}' > "$request_json"
;;
404)
if ! git ls-remote --exit-code --tags \
"https://gitcode.com/$GITCODE_REPOSITORY.git" \
"refs/tags/$RELEASE_TAG" > /dev/null; then
echo "::error::Tag $RELEASE_TAG has not been mirrored to GitCode yet. Retry this workflow after the tag appears on GitCode."
exit 1
fi
request_method=POST
request_url="https://api.gitcode.com/api/v5/repos/$GITCODE_REPOSITORY/releases"
request_action=create
success_action=created
jq -n \
--arg tag_name "$RELEASE_TAG" \
--arg name "$RELEASE_TAG" \
--arg body "$release_body" \
--arg release_status "$release_status" \
'{
tag_name: $tag_name,
name: $name,
body: $body,
release_status: $release_status
}' > "$request_json"
;;
*)
echo "::error::Failed to inspect GitCode release. Response code: $gitcode_release_status"
cat "$gitcode_release_json"
exit 1
;;
esac
gitcode_response_json="$(mktemp)"
request_status="$(
curl -L -sS -o "$gitcode_response_json" -w "%{http_code}" \
-X "$request_method" \
-H "PRIVATE-TOKEN: $GITCODE_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-binary "@$request_json" \
"$request_url"
)"
if [[ "$request_status" != "200" ]]; then
echo "::error::Failed to $request_action GitCode release. Response code: $request_status"
cat "$gitcode_response_json"
exit 1
fi
echo "GitCode release $success_action successfully"
delimiter="release-body-$(openssl rand -hex 16)"
{
echo "tag=$RELEASE_TAG"
echo "body<<$delimiter"
echo "$release_body"
echo "$delimiter"
echo "prerelease=$release_prerelease"
} >> "$GITHUB_OUTPUT"
- name: Download GitHub release assets
if: ${{ inputs.sync_files }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ inputs.tag_name }}
run: |
set -euo pipefail
mkdir release-assets
gh release download "$RELEASE_TAG" \
--repo "$GITHUB_REPOSITORY" \
--dir release-assets
if ! find release-assets -maxdepth 1 -type f -print -quit | grep -q .; then
echo "::error::GitHub release has no downloadable assets"
exit 1
fi
while IFS= read -r -d '' file; do
directory="$(dirname "$file")"
filename="$(basename "$file")"
safe_filename="$(sed 's/[^A-Za-z0-9._+-]/-/g' <<< "$filename")"
if [[ "$filename" != "$safe_filename" ]]; then
if [[ -e "$directory/$safe_filename" ]]; then
echo "::error::Asset filename collision after normalization: $safe_filename"
exit 1
fi
mv -- "$file" "$directory/$safe_filename"
fi
done < <(find release-assets -maxdepth 1 -type f -print0)
find release-assets -maxdepth 1 -type f -print | sort
- name: Prepare GitCode release assets
id: assets
if: ${{ inputs.sync_files }}
env:
GITCODE_REPOSITORY: ${{ vars.GITCODE_REPOSITORY }}
GITCODE_TOKEN: ${{ secrets.GITCODE_TOKEN }}
RELEASE_TAG: ${{ inputs.tag_name }}
run: |
set -euo pipefail
local_assets="$(
find release-assets -maxdepth 1 -type f -printf '%s\t%f\n' \
| sort -n -k1,1 \
| cut -f2- \
| jq -Rsc 'split("\n") | map(select(length > 0))'
)"
gitcode_release_json="$(mktemp)"
gitcode_release_status="$(
curl -L -sS -o "$gitcode_release_json" -w "%{http_code}" \
-H "PRIVATE-TOKEN: $GITCODE_TOKEN" \
-H "Accept: application/json" \
"https://api.gitcode.com/api/v5/repos/$GITCODE_REPOSITORY/releases/tags/$RELEASE_TAG"
)"
if [[ "$gitcode_release_status" != "200" ]]; then
echo "::error::Failed to inspect GitCode release assets. Response code: $gitcode_release_status"
cat "$gitcode_release_json"
exit 1
fi
existing_assets="$(jq -c '[.assets[]?.name]' "$gitcode_release_json")"
missing_assets="$(
jq -cn \
--argjson local_assets "$local_assets" \
--argjson existing_assets "$existing_assets" \
'$local_assets - $existing_assets'
)"
jq -rn \
--argjson local_assets "$local_assets" \
--argjson missing_assets "$missing_assets" \
'$local_assets - $missing_assets | .[] | "Skipping existing GitCode asset: \(.)"'
echo "matrix=$missing_assets" >> "$GITHUB_OUTPUT"
echo "has_assets=$(jq -r 'length > 0' <<< "$missing_assets")" >> "$GITHUB_OUTPUT"
- name: Upload release assets for GitCode
if: ${{ inputs.sync_files && steps.assets.outputs.has_assets == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: gitcode-release-assets
path: release-assets/*
if-no-files-found: error
retention-days: 1
gitcode-release-assets:
name: Publish GitCode asset (${{ matrix.file_name }})
needs: prepare-release
if: ${{ inputs.sync_files && needs.prepare-release.result == 'success' && needs.prepare-release.outputs.has_release_assets == 'true' }}
strategy:
fail-fast: false
max-parallel: 4
matrix:
file_name: ${{ fromJSON(needs.prepare-release.outputs.release_asset_matrix) }}
uses: nvdacn/sync_to_gitcode/.github/workflows/CreateReleaseOnGitCode.yaml@18b70112d0e62260bc54085028e5510bbc6323b2
with:
artifact_name: gitcode-release-assets
gitcode_repository: ${{ vars.GITCODE_REPOSITORY }}
default_branch: main
tag_name: ${{ needs.prepare-release.outputs.release_tag }}
body: ${{ needs.prepare-release.outputs.release_body }}
prerelease: ${{ needs.prepare-release.outputs.release_prerelease == 'true' }}
file_name: ${{ matrix.file_name }}
secrets:
GITCODE_TOKEN: ${{ secrets.GITCODE_TOKEN }}