Files
waveform-analysis/.gitea/workflows/package.yml
李启源 a27a541074
Some checks failed
Package component / package (push) Failing after 2m40s
feat(ci): publish tagged releases to npmjs
2026-07-21 13:27:12 +08:00

217 lines
8.4 KiB
YAML

name: Package component
on:
push:
tags:
- 'v*'
jobs:
package:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check out repository
shell: bash
run: |
set -euo pipefail
server_url="${{ gitea.server_url }}"
repository_url="${server_url%/}/${{ gitea.repository }}.git"
tag_name="${{ gitea.ref_name }}"
git init .
git remote add origin "$repository_url"
git fetch --depth 1 origin "refs/tags/$tag_name:refs/tags/$tag_name"
git checkout --detach "$tag_name^{commit}"
- name: Set up pnpm
run: |
corepack enable
corepack prepare pnpm@10.32.1 --activate
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Validate release version
shell: bash
run: |
set -euo pipefail
tag_name="${{ gitea.ref_name }}"
tag_pattern='^v([0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?)$'
if [[ ! "$tag_name" =~ $tag_pattern ]]; then
echo "Release tags must use vX.Y.Z or vX.Y.Z-prerelease format: $tag_name" >&2
exit 1
fi
package_version="${BASH_REMATCH[1]}"
source_version="$(node -p "require('./package.json').version")"
if [[ "$source_version" != "$package_version" ]]; then
echo "package.json version $source_version does not match tag $tag_name" >&2
exit 1
fi
if [[ "$package_version" == *-* ]]; then
npm_dist_tag='next'
is_prerelease='true'
else
npm_dist_tag='latest'
is_prerelease='false'
fi
cat > release.env <<EOF
TAG_NAME=$tag_name
PACKAGE_VERSION=$package_version
NPM_DIST_TAG=$npm_dist_tag
IS_PRERELEASE=$is_prerelease
EOF
printf 'Packaging waveform-analysis@%s from %s\n' "$package_version" "$tag_name"
- name: Verify release is new
shell: bash
run: |
set -euo pipefail
source release.env
server_url="${{ gitea.server_url }}"
registry_url="${server_url%/}/api/packages/admin/npm/"
package_name="$(node -p "require('./package.json').name")"
release_status="$(curl --silent --output /dev/null --write-out '%{http_code}' \
"$server_url/api/v1/repos/${{ gitea.repository }}/releases/tags/$TAG_NAME")"
if [[ "$release_status" != '404' ]]; then
echo "Release tag $TAG_NAME already exists or could not be checked (HTTP $release_status)" >&2
exit 1
fi
package_metadata="$(curl --fail --show-error --silent "$registry_url$package_name")"
if node -e 'const chunks = []; process.stdin.on("data", chunk => chunks.push(chunk)); process.stdin.on("end", () => { const metadata = JSON.parse(Buffer.concat(chunks).toString()); process.exit(metadata.versions?.[process.argv[1]] ? 0 : 1) })' "$PACKAGE_VERSION" <<<"$package_metadata"; then
echo "npm package $package_name@$PACKAGE_VERSION already exists" >&2
exit 1
fi
if npm view "$package_name@$PACKAGE_VERSION" version --registry='https://registry.npmjs.org/' > /dev/null 2>&1; then
echo "npmjs package $package_name@$PACKAGE_VERSION already exists" >&2
exit 1
fi
- name: Validate publish credentials
shell: bash
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
NPMJS_PUBLISH_TOKEN: ${{ secrets.NPMJS_PUBLISH_TOKEN }}
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
set -euo pipefail
: "${NODE_AUTH_TOKEN:?NPM_PUBLISH_TOKEN is required}"
: "${NPMJS_PUBLISH_TOKEN:?NPMJS_PUBLISH_TOKEN is required}"
: "${RELEASE_TOKEN:?RELEASE_TOKEN is required}"
- name: Type check
run: pnpm typecheck
- name: Lint
run: pnpm lint
- name: Test with coverage
run: pnpm test:coverage
- name: Build component
run: pnpm build
- name: Pack component
shell: bash
run: |
set -euo pipefail
source release.env
pnpm pack --pack-destination artifacts
package_file="$(find artifacts -maxdepth 1 -type f -name '*.tgz' -print -quit)"
test -n "$package_file"
mkdir -p release-assets
published_name="waveform-analysis-${PACKAGE_VERSION}.tgz"
install -m 644 "$package_file" "release-assets/$published_name"
sha256sum "release-assets/$published_name" > "release-assets/$published_name.sha256"
- name: Verify component package
shell: bash
run: |
set -euo pipefail
source release.env
package_file="release-assets/waveform-analysis-${PACKAGE_VERSION}.tgz"
test -f "$package_file"
package_contents="$(tar -tzf "$package_file")"
for required_file in \
package/dist/index.js \
package/dist/index.cjs \
package/dist/types/index.d.ts \
package/dist/style.css \
package/src/index.ts \
package/src/components/WaveformChart.vue \
package/package.json \
package/README.md; do
grep -Fxq "$required_file" <<< "$package_contents"
done
- name: Publish to Gitea npm registry
shell: bash
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
run: |
set -euo pipefail
source release.env
: "${NODE_AUTH_TOKEN:?NPM_PUBLISH_TOKEN is required}"
registry_url='https://lqycustomsite.online/api/packages/admin/npm/'
package_file="release-assets/waveform-analysis-${PACKAGE_VERSION}.tgz"
npm config set -- '//lqycustomsite.online/api/packages/admin/npm/:_authToken' "$NODE_AUTH_TOKEN"
npm publish "./$package_file" --registry="$registry_url" --tag "$NPM_DIST_TAG"
- name: Publish to npmjs.org
shell: bash
env:
NODE_AUTH_TOKEN: ${{ secrets.NPMJS_PUBLISH_TOKEN }}
run: |
set -euo pipefail
source release.env
: "${NODE_AUTH_TOKEN:?NPMJS_PUBLISH_TOKEN is required}"
package_file="release-assets/waveform-analysis-${PACKAGE_VERSION}.tgz"
npm config set -- '//registry.npmjs.org/:_authToken' "$NODE_AUTH_TOKEN"
npm publish "./$package_file" --registry='https://registry.npmjs.org/' --tag "$NPM_DIST_TAG" --access public
- name: Create Gitea release
shell: bash
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
set -euo pipefail
source release.env
: "${RELEASE_TOKEN:?RELEASE_TOKEN is required}"
server_url="${{ gitea.server_url }}"
api_url="$server_url/api/v1/repos/${{ gitea.repository }}/releases"
target_commitish="$(git rev-parse HEAD)"
node - "$TAG_NAME" "$PACKAGE_VERSION" "$target_commitish" "$IS_PRERELEASE" > release.json <<'NODE'
const [tagName, packageVersion, targetCommitish, prerelease] = process.argv.slice(2)
process.stdout.write(JSON.stringify({
tag_name: tagName,
target_commitish: targetCommitish,
name: `waveform-analysis ${tagName}`,
body: `Release ${tagName}\n\n- npm: waveform-analysis@${packageVersion}`,
draft: false,
prerelease: prerelease === 'true',
}))
NODE
release_response="$(curl --fail --show-error --silent \
--request POST \
--header "Authorization: token $RELEASE_TOKEN" \
--header 'Content-Type: application/json' \
--data @release.json \
"$api_url")"
release_id="$(node -e 'const chunks = []; process.stdin.on("data", chunk => chunks.push(chunk)); process.stdin.on("end", () => { const release = JSON.parse(Buffer.concat(chunks).toString()); if (!release.id) process.exit(1); process.stdout.write(String(release.id)) })' <<<"$release_response")"
for asset in release-assets/*; do
asset_name="$(basename "$asset")"
curl --fail --show-error --silent \
--request POST \
--header "Authorization: token $RELEASE_TOKEN" \
--header 'Content-Type: application/octet-stream' \
--data-binary "@$asset" \
"$api_url/$release_id/assets?name=$asset_name" > /dev/null
done