Skip to content

Commit a2f5301

Browse files
jsjoeiocode-asher
andauthored
feat: publish beta and development tags on npm (#4769)
* feat: add logic to publish beta/dev npm This adds new log to publish the npm package both while working on PRs and when PRs are merged into main, allowing us to easily test changes in a production-like setting. Co-authored-by: Asher <[email protected]>
1 parent 63f99da commit a2f5301

File tree

6 files changed

+133
-11
lines changed

6 files changed

+133
-11
lines changed

.github/workflows/ci.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,15 @@ jobs:
177177
name: npm-package
178178
path: ./package.tar.gz
179179

180+
- name: Publish npm package with PR number and commit SHA
181+
run: yarn publish:npm
182+
env:
183+
ENVIRONMENT: "development"
184+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
185+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
186+
NPM_TAG: ${{ github.event.number }}
187+
PR_NUMBER_AND_COMMIT_SHA: ${{ github.event.number }}-${{ github.event.pull_request.head.sha }}
188+
180189
# TODO: cache building yarn --production
181190
# possibly 2m30s of savings(?)
182191
# this requires refactoring our release scripts

.github/workflows/npm-brew.yaml

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ jobs:
1616
steps:
1717
- uses: actions/checkout@v2
1818

19-
- name: Run ./ci/steps/publish-npm.sh
20-
run: ./ci/steps/publish-npm.sh
19+
- name: Publish npm package with PR number and commit SHA
20+
run: yarn publish:npm
2121
env:
22+
ENVIRONMENT: "production"
2223
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2324
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
25+
NPM_TAG: "latest"
2426

2527
homebrew:
2628
# The newest version of code-server needs to be available on npm when this runs

.github/workflows/npm-dev.yaml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Publish on npm and tag with "beta"
2+
3+
on:
4+
# Shows the manual trigger in GitHub UI
5+
# helpful as a back-up in case the GitHub Actions Workflow fails
6+
workflow_dispatch:
7+
8+
push:
9+
branches:
10+
- main
11+
12+
jobs:
13+
# NOTE: this job requires curl, jq and yarn
14+
# All of them are included in ubuntu-latest.
15+
npm:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v2
19+
20+
- name: Run ./ci/steps/publish-npm.sh
21+
run: yarn publish:npm
22+
env:
23+
ENVIRONMENT: "staging"
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
26+
NPM_TAG: "beta"
27+
PR_NUMBER_AND_COMMIT_SHA: ${{ github.event.number }}-${{ github.event.pull_request.head.sha }}

ci/steps/publish-npm.sh

+90-7
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,60 @@ set -euo pipefail
44
main() {
55
cd "$(dirname "$0")/../.."
66
source ./ci/lib.sh
7+
source ./ci/steps/steps-lib.sh
78

8-
# npm view won't exit with non-zero so we have to check the output.
9-
local hasVersion
10-
hasVersion=$(npm view "code-server@$VERSION" version)
11-
if [[ $hasVersion == "$VERSION" ]]; then
12-
echo "$VERSION is already published"
13-
return
9+
## Authentication tokens
10+
# Needed to publish on NPM
11+
if ! is_env_var_set "NPM_TOKEN"; then
12+
echo "NPM_TOKEN is not set. Cannot publish to npm without credentials."
13+
exit 1
14+
fi
15+
16+
# NOTE@jsjoeio - only needed if we use the download_artifact
17+
# because we talk to the GitHub API.
18+
# Needed to use GitHub API
19+
if ! is_env_var_set "GITHUB_TOKEN"; then
20+
echo "GITHUB_TOKEN is not set. Cannot download npm release artifact without GitHub credentials."
21+
exit 1
22+
fi
23+
24+
## Environment
25+
# This string is used to determine how we should tag the npm release.
26+
# Environment can be one of three choices:
27+
# "development" - this means we tag with the PR number, allowing
28+
# a developer to install this version with `yarn add code-server@<pr-number>`
29+
# "staging" - this means we tag with `beta`, allowing
30+
# a developer to install this version with `yarn add code-server@beta`
31+
# "production" - this means we tag with `latest` (default), allowing
32+
# a developer to install this version with `yarn add code-server@latest`
33+
if ! is_env_var_set "ENVIRONMENT"; then
34+
echo "ENVIRONMENT is not set. Cannot determine npm tag without ENVIRONMENT."
35+
exit 1
36+
fi
37+
38+
## Publishing Information
39+
# All the variables below are used to determine how we should publish
40+
# the npm package. We also use this information for bumping the version.
41+
# This is because npm won't publish your package unless it's a new version.
42+
# i.e. for development, we bump the version to <current version>-<pr number>-<commit sha>
43+
# example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
44+
# We need the current package.json VERSION
45+
if ! is_env_var_set "VERSION"; then
46+
echo "VERSION is not set. Cannot publish to npm without VERSION."
47+
exit 1
48+
fi
49+
50+
# We need TAG to know what to publish under on npm
51+
# Options are "latest", "beta", or "<pr number >"
52+
# See Environment comments above to know when each is used.
53+
if ! is_env_var_set "NPM_TAG"; then
54+
echo "NPM_TAG is not set. This is needed for tagging the npm release."
55+
exit 1
1456
fi
1557

58+
echo "using tag: $NPM_TAG"
59+
60+
# This allows us to publish to npm in CI workflows
1661
if [[ ${CI-} ]]; then
1762
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
1863
fi
@@ -24,7 +69,45 @@ main() {
2469
# Ignore symlink when publishing npm package
2570
# See: https://github.com/cdr/code-server/pull/3935
2671
echo "node_modules.asar" > release/.npmignore
27-
yarn publish --non-interactive release
72+
73+
# NOTES:@jsjoeio
74+
# We only need to run npm version for "development" and "staging".
75+
# This is because our release:prep script automatically bumps the version
76+
# in the package.json and we commit it as part of the release PR.
77+
if [[ "$ENVIRONMENT" == "production" ]]; then
78+
NPM_VERSION="$VERSION"
79+
else
80+
echo "Not a production environment"
81+
echo "Found environment: $ENVIRONMENT"
82+
echo "Manually bumping npm version..."
83+
84+
if ! is_env_var_set "PR_NUMBER_AND_COMMIT_SHA"; then
85+
echo "PR_NUMBER_AND_COMMIT_SHA is not set. This is needed for setting the npm version in non-production environments."
86+
exit 1
87+
fi
88+
89+
# We modify the version in the package.json
90+
# to be the current version + the PR number + commit SHA
91+
# Example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
92+
NPM_VERSION="$VERSION-$PR_NUMBER_AND_COMMIT_SHA"
93+
pushd release
94+
# NOTE:@jsjoeio
95+
# I originally tried to use `yarn version` but ran into issues and abandoned it.
96+
npm version "$NPM_VERSION"
97+
popd
98+
fi
99+
100+
# We need to make sure we haven't already published the version.
101+
# This is because npm view won't exit with non-zero so we have
102+
# to check the output.
103+
local hasVersion
104+
hasVersion=$(npm view "code-server@$NPM_VERSION" version)
105+
if [[ $hasVersion == "$NPM_VERSION" ]]; then
106+
echo "$NPM_VERSION is already published"
107+
return
108+
fi
109+
110+
yarn publish --non-interactive release --tag "$NPM_TAG"
28111
}
29112

30113
main "$@"

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"test:scripts": "./ci/dev/test-scripts.sh",
2424
"package": "./ci/build/build-packages.sh",
2525
"postinstall": "./ci/dev/postinstall.sh",
26+
"publish:npm": "./ci/steps/publish-npm.sh",
2627
"_audit": "./ci/dev/audit.sh",
2728
"fmt": "./ci/dev/fmt.sh",
2829
"lint": "./ci/dev/lint.sh",

test/unit/node/settings.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe("settings", () => {
1414
testDir = await tmpdir(testName)
1515
})
1616
describe("with invalid JSON in settings file", () => {
17-
let mockSettingsFile = "coder.json"
17+
const mockSettingsFile = "coder.json"
1818
let pathToMockSettingsFile = ""
1919

2020
beforeEach(async () => {
@@ -33,7 +33,7 @@ describe("settings", () => {
3333
})
3434
})
3535
describe("with invalid settings file path", () => {
36-
let mockSettingsFile = "nonExistent.json"
36+
const mockSettingsFile = "nonExistent.json"
3737
let pathToMockSettingsFile = ""
3838

3939
beforeEach(async () => {

0 commit comments

Comments
 (0)