@@ -3,50 +3,238 @@ name: '@nativescript/doctor -> npm'
33on :
44 push :
55 branches : [ 'main' ]
6+ tags :
7+ - ' @nativescript/doctor@*'
68 paths :
79 - ' packages/doctor/**'
810 workflow_dispatch :
11+ inputs :
12+ release_type :
13+ description : >-
14+ Release to cut. Leave empty for a rolling "next" prerelease (no version
15+ bump). "dev" publishes a -dev prerelease (no bump). A semver keyword
16+ (patch/minor/major) or an explicit version (e.g. 2.1.0, 2.1.0-alpha.1)
17+ bumps packages/doctor/package.json, commits + tags
18+ @nativescript/doctor@<version>, then publishes a stable release. A
19+ prerelease version publishes under the dist-tag matching its prerelease
20+ id (alpha/beta/rc); a plain version publishes under "latest".
21+ type : string
22+ required : false
23+ default : ' '
924
10- defaults :
11- run :
12- working-directory : packages/doctor
25+ permissions : read-all
1326
1427env :
1528 NPM_TAG : ' next'
1629
17- permissions :
18- contents : read
19-
2030jobs :
21- release :
31+ build :
32+ name : Build
2233 runs-on : ubuntu-latest
34+ permissions :
35+ contents : write
36+ defaults :
37+ run :
38+ working-directory : packages/doctor
39+ outputs :
40+ npm_version : ${{ steps.npm_version_output.outputs.NPM_VERSION }}
41+ npm_tag : ${{ steps.npm_version_output.outputs.NPM_TAG }}
42+ is_release : ${{ steps.npm_version_output.outputs.IS_RELEASE }}
2343
2444 steps :
25-
2645 - name : Harden the runner (Audit all outbound calls)
2746 uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
2847 with :
2948 egress-policy : audit
3049
3150 - uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
51+ with :
52+ fetch-depth : 0
53+ token : ${{ secrets.GITHUB_TOKEN }}
54+
55+ - uses : actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
56+ with :
57+ node-version : 22.14.0
58+ registry-url : " https://registry.npmjs.org"
3259
3360 - name : Setup
3461 run : npm install
3562
36- - name : Generate Version
63+ - name : Get Current Version
64+ run : |
65+ NPM_VERSION=$(node -e "console.log(require('./package.json').version);")
66+ echo NPM_VERSION=$NPM_VERSION >> $GITHUB_ENV
67+
68+ - name : Bump, commit and tag stable release (manual dispatch)
69+ if : ${{ github.event_name == 'workflow_dispatch' && inputs.release_type != '' && inputs.release_type != 'dev' }}
70+ env :
71+ # env indirection keeps the free-text dispatch input out of shell interpolation
72+ RELEASE_INPUT : ${{ inputs.release_type }}
3773 run : |
38- echo NPM_VERSION=$(node -e "console.log(require('./package.json').version);")-$NPM_TAG-$(date +"%m-%d-%Y")-$GITHUB_RUN_ID >> $GITHUB_ENV
74+ git config user.name "github-actions[bot]"
75+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
76+ # npm version accepts a semver keyword (patch/minor/major) or an explicit
77+ # version; strip an optional leading "v" so v2.1.0 and 2.1.0 both work.
78+ # The tag is written by hand: npm's own v<version> tag namespace belongs
79+ # to the CLI package at the repo root.
80+ npm version "${RELEASE_INPUT#v}" --no-git-tag-version
81+ NPM_VERSION=$(node -e "console.log(require('./package.json').version);")
82+ echo NPM_VERSION=$NPM_VERSION >> $GITHUB_ENV
83+ git add package.json package-lock.json
84+ git commit -m "chore(doctor): release @nativescript/doctor@$NPM_VERSION"
85+ git tag -a "@nativescript/doctor@$NPM_VERSION" -m "@nativescript/doctor@$NPM_VERSION"
86+ git push origin HEAD:${GITHUB_REF_NAME} --follow-tags
3987
40- - name : Bump Version
41- run : npm --no-git-tag-version version $NPM_VERSION
88+ - name : Bump version for dev release
89+ if : ${{ !contains(github.ref, 'refs/tags/') && (github.event_name != 'workflow_dispatch' || inputs.release_type == '' || inputs.release_type == 'dev') }}
90+ env :
91+ NPM_TAG : ${{ github.event_name == 'workflow_dispatch' && inputs.release_type == 'dev' && 'dev' || 'next' }}
92+ # the shared version scripts live at the repo root, whose dependencies
93+ # are not installed here — semver resolves out of this package instead
94+ NODE_PATH : ${{ github.workspace }}/packages/doctor/node_modules
95+ run : |
96+ LAST_TAG=$(git describe --tags --abbrev=0 --match='@nativescript/doctor@*' 2>/dev/null || true)
97+ LAST_TAGGED_VERSION=${LAST_TAG##*@}
98+ # before the first scoped tag exists, the published version in
99+ # package.json is the only baseline to bump past
100+ export LAST_TAGGED_VERSION=${LAST_TAGGED_VERSION:-$NPM_VERSION}
101+ NPM_VERSION=$(node "$GITHUB_WORKSPACE/scripts/get-next-version.js")
102+ echo NPM_VERSION=$NPM_VERSION >> $GITHUB_ENV
103+ npm version $NPM_VERSION --no-git-tag-version
104+
105+ - name : Output NPM Version and tag
106+ id : npm_version_output
107+ env :
108+ # true only for a manual dispatch that cut a real (bumped) release — not
109+ # the empty "next" build or the "dev" channel. Computed in the GitHub
110+ # expression context so the free-text input never reaches the shell.
111+ IS_DISPATCH_RELEASE : ${{ github.event_name == 'workflow_dispatch' && inputs.release_type != '' && inputs.release_type != 'dev' }}
112+ NODE_PATH : ${{ github.workspace }}/packages/doctor/node_modules
113+ run : |
114+ NPM_TAG=$(node "$GITHUB_WORKSPACE/scripts/get-npm-tag.js")
115+ if [[ "${GITHUB_REF}" == refs/tags/* ]] || [[ "$IS_DISPATCH_RELEASE" == "true" ]]; then
116+ IS_RELEASE=true
117+ else
118+ IS_RELEASE=false
119+ fi
120+ echo NPM_VERSION=$NPM_VERSION >> $GITHUB_OUTPUT
121+ echo NPM_TAG=$NPM_TAG >> $GITHUB_OUTPUT
122+ echo IS_RELEASE=$IS_RELEASE >> $GITHUB_OUTPUT
42123
43124 - name : Build @nativescript/doctor
44125 run : npm pack
45126
46- - name : Publish @nativescript/doctor
127+ - name : Upload npm package artifact
128+ uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
129+ with :
130+ name : npm-package-doctor
131+ path : packages/doctor/nativescript-doctor-${{steps.npm_version_output.outputs.NPM_VERSION}}.tgz
132+
133+ publish :
134+ runs-on : ubuntu-latest
135+ environment : npm-publish
136+ needs :
137+ - build
138+ permissions :
139+ contents : read
140+ id-token : write
141+ env :
142+ NPM_VERSION : ${{needs.build.outputs.npm_version}}
143+ NPM_TAG : ${{needs.build.outputs.npm_tag}}
144+ steps :
145+ - name : Harden the runner (Audit all outbound calls)
146+ uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
147+ with :
148+ egress-policy : audit
149+
150+ - uses : actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
151+ with :
152+ node-version : 22.14.0
153+ registry-url : " https://registry.npmjs.org"
154+
155+ - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
156+ with :
157+ name : npm-package-doctor
158+ path : dist
159+
160+ - name : Update npm (required for OIDC trusted publishing)
161+ run : |
162+ npm install -g npm@^11.5.1
163+ npm --version
164+
165+ - name : Publish package (OIDC trusted publishing)
166+ if : ${{ vars.USE_NPM_TOKEN != 'true' }}
167+ run : |
168+ echo "Publishing @nativescript/doctor@$NPM_VERSION to NPM with tag $NPM_TAG via OIDC trusted publishing..."
169+ unset NODE_AUTH_TOKEN
170+ if [ -n "${NPM_CONFIG_USERCONFIG:-}" ]; then
171+ rm -f "$NPM_CONFIG_USERCONFIG"
172+ fi
173+ npm publish ./dist/nativescript-doctor-${{env.NPM_VERSION}}.tgz --tag $NPM_TAG --access public --provenance
47174 env :
48- NPM_TOKEN : ${{ secrets.NPM_PUBLISH_TOKEN }}
175+ NODE_AUTH_TOKEN : " "
176+
177+ - name : Publish package (granular token)
178+ if : ${{ vars.USE_NPM_TOKEN == 'true' }}
179+ run : |
180+ echo "Publishing @nativescript/doctor@$NPM_VERSION to NPM with tag $NPM_TAG via granular token..."
181+ npm publish ./dist/nativescript-doctor-${{env.NPM_VERSION}}.tgz --tag $NPM_TAG --access public --provenance
182+ env :
183+ NODE_AUTH_TOKEN : ${{ secrets.NPM_PUBLISH_TOKEN }}
184+
185+ github-release :
186+ runs-on : ubuntu-latest
187+ # runs for tag pushes and for manual dispatches that bumped a stable release
188+ if : ${{ needs.build.outputs.is_release == 'true' }}
189+ permissions :
190+ contents : write
191+ needs :
192+ - build
193+ env :
194+ NPM_VERSION : ${{needs.build.outputs.npm_version}}
195+ steps :
196+ - name : Harden the runner (Audit all outbound calls)
197+ uses : step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
198+ with :
199+ egress-policy : audit
200+
201+ - uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
202+ with :
203+ fetch-depth : 0
204+ ref : ' refs/tags/@nativescript/doctor@${{needs.build.outputs.npm_version}}'
205+
206+ - uses : actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
207+ with :
208+ node-version : 22.14.0
209+
210+ - name : Setup
211+ working-directory : packages/doctor
212+ run : npm i --ignore-scripts --no-package-lock
213+
214+ - uses : actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
215+ with :
216+ name : npm-package-doctor
217+ path : dist
218+
219+ - name : Generate provenance statement
49220 run : |
50- echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
51- echo "Publishing @nativescript/doctor@$NPM_VERSION to NPM with tag $NPM_TAG..."
52- npm publish nativescript-doctor-$NPM_VERSION.tgz --tag $NPM_TAG
221+ TGZ_PATH=$(ls dist/nativescript-doctor-*.tgz | head -n1)
222+ TGZ_NAME=$(basename "$TGZ_PATH")
223+ TGZ_SHA=$(sha256sum "$TGZ_PATH" | awk '{ print $1 }')
224+ PROV_PATH="dist/${TGZ_NAME%.tgz}.intoto.jsonl"
225+
226+ cat > "$PROV_PATH" <<EOF
227+ {"_type":"https://in-toto.io/Statement/v1","subject":[{"name":"$TGZ_NAME","digest":{"sha256":"$TGZ_SHA"}}],"predicateType":"https://slsa.dev/provenance/v1"}
228+ EOF
229+
230+ - name : Partial Changelog
231+ working-directory : packages/doctor
232+ run : npx conventional-changelog -p angular -r2 --commit-path . --tag-prefix '@nativescript/doctor@' > "$GITHUB_WORKSPACE/body.md"
233+
234+ - uses : ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
235+ with :
236+ tag : ' @nativescript/doctor@${{needs.build.outputs.npm_version}}'
237+ artifacts : " dist/nativescript-doctor-*.tgz,dist/nativescript-doctor-*.intoto.jsonl"
238+ bodyFile : " body.md"
239+ prerelease : ${{needs.build.outputs.npm_tag != 'latest'}}
240+ allowUpdates : true
0 commit comments