Skip to content

Commit e9fdc9a

Browse files
authored
chore: create smoke-publish-test.sh script (#7483)
1 parent 1524cfd commit e9fdc9a

File tree

9 files changed

+144
-107
lines changed

9 files changed

+144
-107
lines changed

.github/workflows/ci-release.yml

+3-39
Original file line numberDiff line numberDiff line change
@@ -162,29 +162,12 @@ jobs:
162162
- name: Linux
163163
os: ubuntu-latest
164164
shell: bash
165-
- name: macOS
166-
os: macos-latest
167-
shell: bash
168-
- name: macOS
169-
os: macos-13
170-
shell: bash
171165
node-version:
172166
- 18.17.0
173167
- 18.x
174168
- 20.5.0
175169
- 20.x
176170
- 22.x
177-
exclude:
178-
- platform: { name: macOS, os: macos-13, shell: bash }
179-
node-version: 18.17.0
180-
- platform: { name: macOS, os: macos-13, shell: bash }
181-
node-version: 18.x
182-
- platform: { name: macOS, os: macos-13, shell: bash }
183-
node-version: 20.5.0
184-
- platform: { name: macOS, os: macos-13, shell: bash }
185-
node-version: 20.x
186-
- platform: { name: macOS, os: macos-13, shell: bash }
187-
node-version: 22.x
188171
runs-on: ${{ matrix.platform.os }}
189172
defaults:
190173
run:
@@ -217,30 +200,11 @@ jobs:
217200
run: node scripts/git-dirty.js
218201
- name: Reset Deps
219202
run: node scripts/resetdeps.js
220-
- name: Pack
221-
env:
222-
SMOKE_PUBLISH_NPM: 1
223-
run: |
224-
NPM_VERSION="$(node . --version)-$GITHUB_SHA.0"
225-
node . version $NPM_VERSION --ignore-scripts
226-
node scripts/publish.js --pack-destination=$RUNNER_TEMP
227-
export SMOKE_PUBLISH_TARBALL="$RUNNER_TEMP/npm-$NPM_VERSION.tgz"
228-
node . install --global $SMOKE_PUBLISH_TARBALL
229-
node . install -w smoke-tests --ignore-scripts --no-audit --no-fund
230-
# call installed npm instead of local source since we are testing
231-
# the packed tarball that we just installed globally
232-
NPM_GLOBAL_VERSION="$(npm --version)"
233-
npm help
234-
if [ "$NPM_GLOBAL_VERSION" == "$NPM_VERSION" ]; then
235-
npm test -w smoke-tests --ignore-scripts
236-
else
237-
echo "global npm is not the correct version for smoke-publish"
238-
echo "found: $NPM_GLOBAL_VERSION, expected: $NPM_VERSION"
239-
exit 1
240-
fi
203+
- name: Smoke Publish
204+
run: ./scripts/smoke-publish-test.sh
241205
- name: Conclude Check
242206
uses: LouisBrunner/checks-action@v1.6.0
243-
if: always()
207+
if: steps.create-check.outputs.check-id && always()
244208
with:
245209
token: ${{ secrets.GITHUB_TOKEN }}
246210
conclusion: ${{ job.status }}

docs/bin/build.js

-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
if (
2-
process.env.SMOKE_PUBLISH_NPM &&
3-
!require('semver').satisfies(process.version, require('../package.json').engines.node)
4-
) {
5-
// The docs tooling is kept in sync between releases and dependencies that are not compatible
6-
// with the lower bound of npm@8 engines are used. When we run the SMOKE_PUBLISH_NPM we are
7-
// testing that npm is able to pack and install itself locally and then run its own smoke tests.
8-
// Packing will run this script automatically so in the cases where the node version is
9-
// not compatible, it is ok to bail on this script since the generated docs are not used in
10-
// the smoke tests.
11-
console.log(`Skipping docs build due to SMOKE_PUBLISH_NPM and ${process.version}`)
12-
return
13-
}
14-
151
const run = require('../lib/build.js')
162
const { paths } = require('../lib/index')
173

mock-registry/lib/index.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ const npa = require('npm-package-arg')
44
const Nock = require('nock')
55
const stringify = require('json-stringify-safe')
66

7+
const logReq = (req, ...keys) => {
8+
const obj = JSON.parse(stringify(req))
9+
const res = {}
10+
for (const [k, v] of Object.entries(obj)) {
11+
if (!keys.includes(k)) {
12+
res[k] = v
13+
}
14+
}
15+
return stringify(res, null, 2)
16+
}
17+
718
class MockRegistry {
819
#tap
920
#nock
@@ -40,7 +51,8 @@ class MockRegistry {
4051
// mocked with a 404, 500, etc.
4152
// XXX: this is opt-in currently because it breaks some existing CLI
4253
// tests. We should work towards making this the default for all tests.
43-
t.fail(`Unmatched request: ${stringify(req, null, 2)}`)
54+
t.comment(logReq(req, 'interceptors', 'socket', 'response', '_events'))
55+
t.fail(`Unmatched request: ${req.method} ${req.path}`)
4456
}
4557
}
4658

scripts/publish.js

+17-11
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ const getPublishes = async ({ force }) => {
7272
}
7373

7474
const main = async (opts) => {
75-
const packOnly = opts.pack || opts.packDestination
76-
const publishes = await getPublishes({ force: packOnly })
75+
const { isLocal, smokePublish, packDestination } = opts
76+
const isPack = !!packDestination
77+
const publishes = await getPublishes({ force: isPack })
7778

7879
if (!publishes.length) {
7980
throw new Error(
@@ -88,12 +89,12 @@ const main = async (opts) => {
8889
}
8990

9091
const confirmMessage = [
91-
`Ready to ${packOnly ? 'pack' : 'publish'} the following packages:`,
92+
`Ready to ${isPack ? 'pack' : 'publish'} the following packages:`,
9293
table.toString(),
93-
packOnly ? null : 'Ok to proceed? ',
94+
isPack ? null : 'Ok to proceed? ',
9495
].filter(Boolean).join('\n')
9596

96-
if (packOnly) {
97+
if (isPack) {
9798
log.info(confirmMessage)
9899
} else {
99100
const confirm = await read({ prompt: confirmMessage, default: 'y' })
@@ -116,21 +117,26 @@ const main = async (opts) => {
116117

117118
await npm('prune', '--omit=dev', '--no-save', '--no-audit', '--no-fund')
118119
await npm('install', '-w', 'docs', '--ignore-scripts', '--no-audit', '--no-fund')
119-
await git.dirty()
120+
if (isLocal && smokePublish) {
121+
log.info(`Skipping git dirty check due to local smoke publish test being run`)
122+
} else {
123+
await git.dirty()
124+
}
120125

121126
for (const publish of publishes) {
122127
const workspace = publish.workspace && `--workspace=${publish.name}`
123-
if (packOnly) {
128+
const publishPkg = (...args) => npm('publish', workspace, `--tag=${publish.tag}`, ...args)
129+
if (isPack) {
124130
await npm(
125131
'pack',
126132
workspace,
127133
opts.packDestination && `--pack-destination=${opts.packDestination}`
128134
)
135+
if (smokePublish) {
136+
await publishPkg('--dry-run')
137+
}
129138
} else {
130-
await npm(
131-
'publish',
132-
workspace,
133-
`--tag=${publish.tag}`,
139+
await publishPkg(
134140
opts.dryRun && '--dry-run',
135141
opts.otp && `--otp=${opts.otp === 'op' ? await op() : opts.otp}`
136142
)

scripts/smoke-publish-test.sh

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env bash
2+
3+
set -eo pipefail
4+
5+
IS_LOCAL="false"
6+
IS_CI="true"
7+
8+
if [ -z "$CI" ]; then
9+
echo "Running locally will overwrite your globally installed npm."
10+
GITHUB_SHA=$(git rev-parse HEAD)
11+
RUNNER_TEMP=$(mktemp -d)
12+
IS_LOCAL="true"
13+
IS_CI="false"
14+
fi
15+
16+
if [ -z "$GITHUB_SHA" ]; then
17+
echo "Error: GITHUB_SHA is required"
18+
exit 1
19+
fi
20+
21+
if [ -z "$RUNNER_TEMP" ]; then
22+
echo "Error: RUNNER_TEMP is required"
23+
exit 1
24+
fi
25+
26+
ORIGINAL_GLOBAL_NPM_VERSION=$(npm --version)
27+
if [ ${#ORIGINAL_GLOBAL_NPM_VERSION} -gt 40 ]; then
28+
echo "Error: Global npm version already contains a git SHA ${ORIGINAL_GLOBAL_NPM_VERSION}"
29+
exit 1
30+
fi
31+
32+
ORIGINAL_LOCAL_NPM_VERSION=$(node . --version)
33+
if [ ${#ORIGINAL_LOCAL_NPM_VERSION} -gt 40 ]; then
34+
echo "Error: Local npm version already contains a git SHA ${ORIGINAL_LOCAL_NPM_VERSION}"
35+
exit 1
36+
fi
37+
NPM_VERSION="$ORIGINAL_LOCAL_NPM_VERSION-$GITHUB_SHA.0"
38+
39+
# Only cleanup locally
40+
if [ "$IS_LOCAL" == "true" ]; then
41+
function cleanup {
42+
npm pkg set version=$ORIGINAL_LOCAL_NPM_VERSION
43+
node scripts/resetdeps.js
44+
if [ "$(git rev-parse HEAD)" != "$GITHUB_SHA" ]; then
45+
echo "==================================="
46+
echo "==================================="
47+
echo "HEAD is on a different commit."
48+
echo "==================================="
49+
echo "==================================="
50+
fi
51+
if [ "$(npm --version)" == "$NPM_VERSION" ]; then
52+
echo "==================================="
53+
echo "==================================="
54+
echo "Global npm version has changed to $NPM_VERSION"
55+
echo "Run the following to change it back"
56+
echo "npm install npm@$ORIGINAL_GLOBAL_NPM_VERSION -g"
57+
echo "==================================="
58+
echo "==================================="
59+
fi
60+
}
61+
trap cleanup EXIT
62+
fi
63+
64+
# Version the local source of npm with the current git sha and
65+
# and pack and install it globally the same way we would if we
66+
# were publishing it to the registry. The only difference is in the
67+
# publish.js script which will only pack and not publish
68+
node . version $NPM_VERSION --ignore-scripts --git-tag-version="$IS_CI"
69+
node scripts/publish.js --pack-destination=$RUNNER_TEMP --smoke-publish=true --is-local="$IS_LOCAL"
70+
NPM_TARBALL="$RUNNER_TEMP/npm-$NPM_VERSION.tgz"
71+
node . install --global $NPM_TARBALL
72+
73+
# Only run the tests if we are sure we have the right version
74+
# otherwise the tests being run are pointless
75+
NPM_GLOBAL_VERSION="$(npm --version)"
76+
if [ "$NPM_GLOBAL_VERSION" != "$NPM_VERSION" ]; then
77+
echo "global npm is not the correct version for smoke-publish"
78+
echo "found: $NPM_GLOBAL_VERSION, expected: $NPM_VERSION"
79+
exit 1
80+
fi
81+
82+
# Install dev deps only for smoke tests so they can be run
83+
node . install -w smoke-tests --ignore-scripts --no-audit --no-fund
84+
# Run smoke tests with env vars so it uses the globally installed tarball we
85+
# just packed/installed. The tacked on args at the end are only used for
86+
# debugging locally when we want to pass args to the smoke-tests to limit the
87+
# files being run or grep a test, etc. Also now set CI=true so we get more
88+
# debug output in our tap tests
89+
CI="true" SMOKE_PUBLISH_TARBALL="$NPM_TARBALL" npm test \
90+
-w smoke-tests \
91+
--ignore-scripts \
92+
-- "$@"

scripts/template-oss/ci-release-yml.hbs

+4-22
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,13 @@
1010
jobCheckout=(obj ref="${{ inputs.ref }}")
1111
jobCreateCheck=(obj sha="${{ inputs.check-sha }}")
1212
windowsCI=false
13+
macCI=false
1314
}}
14-
- name: Pack
15-
env:
16-
SMOKE_PUBLISH_NPM: 1
17-
run: |
18-
NPM_VERSION="$({{ rootNpmPath }} --version)-$GITHUB_SHA.0"
19-
{{ rootNpmPath }} version $NPM_VERSION --ignore-scripts
20-
node scripts/publish.js --pack-destination=$RUNNER_TEMP
21-
export SMOKE_PUBLISH_TARBALL="$RUNNER_TEMP/npm-$NPM_VERSION.tgz"
22-
{{ rootNpmPath }} install --global $SMOKE_PUBLISH_TARBALL
23-
{{ rootNpmPath }} install -w smoke-tests --ignore-scripts --no-audit --no-fund
24-
# call installed npm instead of local source since we are testing
25-
# the packed tarball that we just installed globally
26-
NPM_GLOBAL_VERSION="$(npm --version)"
27-
npm help
28-
if [ "$NPM_GLOBAL_VERSION" == "$NPM_VERSION" ]; then
29-
npm test -w smoke-tests --ignore-scripts
30-
else
31-
echo "global npm is not the correct version for smoke-publish"
32-
echo "found: $NPM_GLOBAL_VERSION, expected: $NPM_VERSION"
33-
exit 1
34-
fi
15+
- name: Smoke Publish
16+
run: ./scripts/smoke-publish-test.sh
3517
- name: Conclude Check
3618
uses: LouisBrunner/checks-action@v1.6.0
37-
if: always()
19+
if: steps.create-check.outputs.check-id && always()
3820
with:
3921
token: $\{{ secrets.GITHUB_TOKEN }}
4022
conclusion: $\{{ job.status }}

scripts/util.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ git.dirty = () => npmGit.isClean({ cwd: CWD }).then(async r => {
132132
return 'git clean'
133133
}
134134
await git('status', '--porcelain=v1', '-uno')
135-
await git('diff')
135+
await git('--no-pager', 'diff')
136136
throw new Error('git dirty')
137137
})
138138

smoke-tests/test/fixtures/setup.js

+9-15
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const MockRegistry = require('@npmcli/mock-registry')
77
const http = require('http')
88
const { createProxy } = require('proxy')
99

10-
const { SMOKE_PUBLISH_NPM, SMOKE_PUBLISH_TARBALL, CI, PATH, Path } = process.env
10+
const { SMOKE_PUBLISH_TARBALL, CI, PATH, Path } = process.env
1111

1212
const DEFAULT_REGISTRY = new URL('https://registry.npmjs.org/')
1313
const MOCK_REGISTRY = new URL('http://smoke-test-registry.club/')
@@ -75,6 +75,8 @@ const getCleanPaths = async () => {
7575

7676
module.exports = async (t, { testdir = {}, debug, mockRegistry = true, useProxy = false } = {}) => {
7777
const debugLog = debug || CI ? (...a) => t.comment(...a) : () => {}
78+
debugLog({ SMOKE_PUBLISH_TARBALL, CI })
79+
7880
const cleanPaths = await getCleanPaths()
7981

8082
// setup fixtures
@@ -170,19 +172,11 @@ module.exports = async (t, { testdir = {}, debug, mockRegistry = true, useProxy
170172
})
171173

172174
// In debug mode, stream stdout and stderr to console so we can debug hanging processes
173-
if (debug) {
174-
p.process.stdout.on('data', (c) => log('STDOUT: ' + c.toString().trim()))
175-
p.process.stderr.on('data', (c) => log('STDERR: ' + c.toString().trim()))
176-
}
175+
p.process.stdout.on('data', (c) => log(c.toString().trim()))
176+
p.process.stderr.on('data', (c) => log(c.toString().trim()))
177177

178178
const { stdout, stderr } = await p
179-
// If not in debug mode, print full stderr and stdout contents separately
180-
if (!debug) {
181-
log(stderr)
182-
log('-'.repeat(40))
183-
log(stdout)
184-
log('='.repeat(40))
185-
}
179+
log('='.repeat(40))
186180

187181
return { stderr, stdout }
188182
}
@@ -225,7 +219,7 @@ module.exports = async (t, { testdir = {}, debug, mockRegistry = true, useProxy
225219

226220
const npmLocal = async (...args) => {
227221
const [{ force = false }] = getOpts(...args)
228-
if (SMOKE_PUBLISH_NPM && !force) {
222+
if (SMOKE_PUBLISH_TARBALL && !force) {
229223
throw new Error('npmLocal cannot be called during smoke-publish')
230224
}
231225
return baseNpm({
@@ -257,7 +251,7 @@ module.exports = async (t, { testdir = {}, debug, mockRegistry = true, useProxy
257251
return {
258252
npmPath,
259253
npmLocal,
260-
npm: SMOKE_PUBLISH_NPM ? npmPath : npm,
254+
npm: SMOKE_PUBLISH_TARBALL ? npmPath : npm,
261255
spawn: baseSpawn,
262256
readFile,
263257
getPath,
@@ -275,6 +269,6 @@ module.exports.testdir = testdirHelper
275269
module.exports.getNpmRoot = getNpmRoot
276270
module.exports.CLI_ROOT = CLI_ROOT
277271
module.exports.WINDOWS = WINDOWS
278-
module.exports.SMOKE_PUBLISH = !!SMOKE_PUBLISH_NPM
272+
module.exports.SMOKE_PUBLISH = !!SMOKE_PUBLISH_TARBALL
279273
module.exports.SMOKE_PUBLISH_TARBALL = SMOKE_PUBLISH_TARBALL
280274
module.exports.MOCK_REGISTRY = MOCK_REGISTRY

0 commit comments

Comments
 (0)