-
Notifications
You must be signed in to change notification settings - Fork 0
163 lines (151 loc) · 6.07 KB
/
Copy pathrelease.yml
File metadata and controls
163 lines (151 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Auto-release to npm from version tags or release-branch merges on main.
#
# The workflow publishes in three ways:
# 1. A merged PR from a `release/vX.Y.Z` branch into `main` (the normal
# path — branch name and `package.json` are both validated against
# each other). `gh release create` pushes the tag as a side effect;
# the subsequent tag-push run is short-circuited by the "already on
# npm" check, so there is no infinite loop.
# 2. A `vX.Y.Z` tag push to `main` (escape hatch / re-publish path —
# tag must match `package.json`).
# 3. A manual `workflow_dispatch` (re-publish / same-version dry test).
#
# PR pushes to a `release/v*` branch, force-pushes, and merges of any
# other branch do NOT publish.
#
# Required repo secret: NPM_TOKEN (npm "Automation" access token with publish
# rights for the `orbcode` package).
name: Release
# Per-run title:
# - tag push → "Release v0.3.1"
# - PR merge → "Release release/v0.3.1"
# - dispatch → "Release v0.3.1" if `version` input set, else "Release manual"
# `run-name` only sees github.* and inputs.* — package.json can't be read here.
run-name: >-
Release ${{
github.event_name == 'push' && github.ref_name ||
github.event_name == 'pull_request' && github.event.pull_request.head.ref ||
(inputs.version && format('v{0}', inputs.version)) || 'manual'
}}
on:
push:
tags:
- "v*"
pull_request:
types:
- closed
branches:
- main
workflow_dispatch:
inputs:
version:
description: "Version to publish (must match package.json). Leave empty to read from package.json."
required: false
type: string
permissions:
contents: write # create the GitHub Release
id-token: write # npm --provenance (requires a public GitHub repo)
concurrency:
group: release
cancel-in-progress: false
jobs:
release:
runs-on: ubuntu-latest
if: |
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
(github.event_name == 'pull_request'
&& github.event.pull_request.merged == true
&& github.event.pull_request.base.ref == 'main'
&& startsWith(github.event.pull_request.head.ref, 'release/v')) ||
(github.event_name == 'workflow_dispatch')
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
cache: npm
- name: Install
run: npm ci
- name: Resolve and verify version
id: version
run: |
set -euo pipefail
PKG_VERSION=$(node -p "require('./package.json').version")
NAME=$(node -p "require('./package.json').name")
EVENT="${{ github.event_name }}"
if [ "$EVENT" = "push" ]; then
# Tag push: REF is refs/tags/vX.Y.Z
TAG_VERSION=${GITHUB_REF#refs/tags/v}
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Tag v$TAG_VERSION does not match package.json version $PKG_VERSION."
echo "::error::Update package.json (and this tag) to publish a coherent release."
exit 1
fi
VERSION="$TAG_VERSION"
elif [ "$EVENT" = "pull_request" ]; then
# Merged release branch: derive version from head_ref (release/vX.Y.Z)
# and require it to match the bumped package.json.
HEAD_REF="${{ github.event.pull_request.head.ref }}"
BRANCH_VERSION=${HEAD_REF#release/v}
if [ -z "$BRANCH_VERSION" ] || [ "$BRANCH_VERSION" = "$HEAD_REF" ]; then
echo "::error::PR head ref '$HEAD_REF' is not a release/vX.Y.Z branch."
exit 1
fi
if [ "$BRANCH_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Branch version $BRANCH_VERSION does not match package.json version $PKG_VERSION."
echo "::error::Rename the branch to release/v$PKG_VERSION (or update package.json) so they agree."
exit 1
fi
VERSION="$BRANCH_VERSION"
else
# Manual dispatch: prefer the input, fall back to package.json.
VERSION="${{ inputs.version }}"
if [ -z "$VERSION" ]; then
VERSION="$PKG_VERSION"
fi
if [ "$VERSION" != "$PKG_VERSION" ]; then
echo "::error::Input version $VERSION does not match package.json version $PKG_VERSION."
exit 1
fi
fi
echo "name=$NAME" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Typecheck & build
run: |
npm run typecheck
npm run build
- name: Check whether this version is already on npm
id: check
run: |
NAME="${{ steps.version.outputs.name }}"
VERSION="${{ steps.version.outputs.version }}"
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
echo "Version $VERSION already published — skipping."
echo "publish=false" >> "$GITHUB_OUTPUT"
else
echo "publish=true" >> "$GITHUB_OUTPUT"
fi
- name: Publish to npm
if: steps.check.outputs.publish == 'true'
# Drop --provenance if the repository is private (provenance needs a
# public repo and a `repository` field in package.json).
run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub Release
if: steps.check.outputs.publish == 'true'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
TARGET_SHA="${{ github.sha }}"
# For tag pushes, also publish from the tagged commit itself.
if [ "${{ github.event_name }}" = "push" ]; then
TARGET_SHA="$GITHUB_REF"
fi
gh release create "v$VERSION" \
--title "orbcode v$VERSION" \
--generate-notes \
--target "$TARGET_SHA" \
|| echo "Release v$VERSION already exists."