-
Notifications
You must be signed in to change notification settings - Fork 4
137 lines (123 loc) · 5.5 KB
/
Copy pathrelease.yml
File metadata and controls
137 lines (123 loc) · 5.5 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
name: Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+-*"
# Fallback for when a tag push doesn't enqueue a run (GitHub event-delivery
# gaps). Triggers are workflow-wide in Actions, so the tag input is
# re-derived as RELEASE_REF_NAME (see the `ref` step) and every step below
# uses that instead of GITHUB_REF_NAME; the tag is fetched and checked out
# at its exact commit.
workflow_dispatch:
inputs:
tag:
description: "Release tag, e.g. v0.9.0-next.0 (must exist)"
required: true
type: string
# Default to no permissions; elevate per-job (least privilege).
permissions: {}
# Never run two publishes for the same release concurrently (dispatch runs
# carry the branch ref, so key the group on the resolved release ref).
concurrency:
group: release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
cancel-in-progress: false
jobs:
release:
name: Publish to npm + create GitHub Release
runs-on: ubuntu-latest
permissions:
contents: write # create the GitHub Release
id-token: write # npm provenance attestation
steps:
- name: Resolve release ref
id: ref
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "RELEASE_REF_NAME=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
else
echo "RELEASE_REF_NAME=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT"
fi
- uses: actions/checkout@v7
with:
# Manual runs dispatch from a branch (usually main); check out the
# tag's exact commit so tag and package.json agree.
ref: ${{ steps.ref.outputs.RELEASE_REF_NAME }}
fetch-depth: 0
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: "22.x"
registry-url: "https://registry.npmjs.org"
cache: npm
# Hard gate: the git tag must match the version we are about to publish.
# npm publishes package.json's version regardless of the tag, so without
# this a v0.2.0 tag on a 0.1.0 package.json would ship 0.1.0 silently.
- name: Verify tag matches package.json version
run: |
PKG_VERSION="$(node -p "require('./package.json').version")"
TAG_NAME="${{ steps.ref.outputs.RELEASE_REF_NAME }}"
TAG_VERSION="${TAG_NAME#v}"
if [[ "$PKG_VERSION" != "$TAG_VERSION" ]]; then
echo "::error::tag $TAG_NAME (=$TAG_VERSION) does not match package.json version $PKG_VERSION"
exit 1
fi
# Guard against a contributor's global/scoped registry leaking non-npmjs
# "resolved" URLs into the lockfile (which break `npm ci` in CI with E401).
- name: Verify lockfile uses only the public npm registry
run: |
if grep -E '"resolved":[[:space:]]*"https?://' package-lock.json | grep -vq 'https://registry.npmjs.org/'; then
echo "::error::package-lock.json contains non-npmjs resolved URLs:"
grep -nE '"resolved":[[:space:]]*"https?://' package-lock.json | grep -v 'https://registry.npmjs.org/' || true
exit 1
fi
- name: Install dependencies
run: npm ci
- name: Typecheck, test, and build
run: npm run prepublishOnly
# Full integration test: install the opencode CLI, load the plugin, and
# assert it lists the Cursor provider (fallback path without a key; live
# discovery additionally exercised when CURSOR_API_KEY is set).
- name: Integration smoke test
run: bash scripts/integration-test.sh
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
# A tag with a pre-release suffix (e.g. v0.1.0-rc.1) publishes to the
# `next` dist-tag and is flagged as a GitHub pre-release, so `npm install`
# and the repo's "Latest" release keep pointing at the last stable.
- name: Classify release from tag
id: version
run: |
TAG_NAME="${{ steps.ref.outputs.RELEASE_REF_NAME }}"
VERSION="${TAG_NAME#v}"
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
if [[ "$VERSION" == *-* ]]; then
echo "NPM_TAG=next" >> "$GITHUB_OUTPUT"
echo "PRERELEASE=true" >> "$GITHUB_OUTPUT"
else
echo "NPM_TAG=latest" >> "$GITHUB_OUTPUT"
echo "PRERELEASE=false" >> "$GITHUB_OUTPUT"
fi
# Idempotent: re-running the job after a partial failure won't hard-fail
# on npm's 409 for an already-published version.
- name: Publish to npm
run: |
PKG="$(node -p "require('./package.json').name")"
VER="$(node -p "require('./package.json').version")"
if npm view "$PKG@$VER" version >/dev/null 2>&1; then
echo "::notice::$PKG@$VER is already published; skipping publish."
else
npm publish --provenance --access public --tag "${{ steps.version.outputs.NPM_TAG }}"
fi
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
# Dispatch runs carry the branch ref; GITHUB_REF_NAME isn't the tag
# there, so pass the resolved tag explicitly.
tag_name: ${{ steps.ref.outputs.RELEASE_REF_NAME }}
name: "v${{ steps.version.outputs.VERSION }}"
generate_release_notes: true
prerelease: ${{ steps.version.outputs.PRERELEASE }}
make_latest: ${{ steps.version.outputs.PRERELEASE == 'false' }}