Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1f4d73c

Browse files
committedMay 8, 2024··
chore: create smoke-publish-test.sh scripts
This makes it easier to debug this test locally. Previously this was avoided because the test will install npm globally and prune deps which can be disruptive to a local checkout. This is somewhat mitigated now with some cleanup and better messaging when run locally.
1 parent 1524cfd commit 1f4d73c

File tree

9 files changed

+109
-130
lines changed

9 files changed

+109
-130
lines changed
 

‎.github/workflows/ci-release.yml

+2-21
Original file line numberDiff line numberDiff line change
@@ -217,27 +217,8 @@ jobs:
217217
run: node scripts/git-dirty.js
218218
- name: Reset Deps
219219
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
220+
- name: Smoke Publish
221+
run: ./scripts/smoke-publish-test.sh
241222
- name: Conclude Check
242223
uses: LouisBrunner/checks-action@v1.6.0
243224
if: always()

‎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

+4-4
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ class MockRegistry {
357357
})
358358
}
359359

360-
async package ({ manifest, times = 1, query, tarballs }) {
360+
async package ({ manifest, times = 1, query, tarballs, tarballTimes = 1 }) {
361361
let nock = this.nock
362362
const spec = npa(manifest.name)
363363
nock = nock.get(this.fullPath(`/${spec.escapedName}`)).times(times)
@@ -368,17 +368,17 @@ class MockRegistry {
368368
if (tarballs) {
369369
for (const [version, tarball] of Object.entries(tarballs)) {
370370
const m = manifest.versions[version]
371-
nock = await this.tarball({ manifest: m, tarball })
371+
nock = await this.tarball({ manifest: m, tarball, times: tarballTimes })
372372
}
373373
}
374374
this.nock = nock
375375
}
376376

377-
async tarball ({ manifest, tarball }) {
377+
async tarball ({ manifest, tarball, times = 1 }) {
378378
const nock = this.nock
379379
const dist = new URL(manifest.dist.tarball)
380380
const tar = await pacote.tarball(tarball, { Arborist })
381-
nock.get(this.fullPath(dist.pathname)).reply(200, tar)
381+
nock.get(this.fullPath(dist.pathname)).times(times).reply(200, tar)
382382
return nock
383383
}
384384

‎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

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

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

+2-21
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,8 @@
1111
jobCreateCheck=(obj sha="${{ inputs.check-sha }}")
1212
windowsCI=false
1313
}}
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
14+
- name: Smoke Publish
15+
run: ./scripts/smoke-publish-test.sh
3516
- name: Conclude Check
3617
uses: LouisBrunner/checks-action@v1.6.0
3718
if: always()

‎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

+2
Original file line numberDiff line numberDiff line change
@@ -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_NPM, SMOKE_PUBLISH_TARBALL, CI })
79+
7880
const cleanPaths = await getCleanPaths()
7981

8082
// setup fixtures

‎smoke-tests/test/npm-replace-global.js

+2-58
Original file line numberDiff line numberDiff line change
@@ -36,63 +36,6 @@ const setupNpmGlobal = async (t, opts) => {
3636
}
3737
}
3838

39-
t.test('pack and replace global self', async t => {
40-
const {
41-
npm,
42-
npmLocalTarball,
43-
npmPath,
44-
getPaths,
45-
paths: { globalBin, globalNodeModules },
46-
} = await setupNpmGlobal(t, {
47-
testdir: {
48-
project: {
49-
'package.json': { name: 'npm', version: '999.999.999' },
50-
},
51-
},
52-
})
53-
54-
const tarball = await npmLocalTarball()
55-
await npm('install', tarball, '--global')
56-
57-
t.equal(
58-
await fs.realpath(join(globalBin, 'npm')),
59-
setup.WINDOWS ? join(globalBin, 'npm') : join(globalNodeModules, 'npm/bin/npm-cli.js'),
60-
'npm realpath is in the testdir'
61-
)
62-
t.equal(
63-
await fs.realpath(join(globalBin, 'npx')),
64-
setup.WINDOWS ? join(globalBin, 'npx') : join(globalNodeModules, 'npm/bin/npx-cli.js'),
65-
'npx realpath is in the testdir'
66-
)
67-
68-
const prePaths = await getPaths()
69-
t.equal(prePaths.npmRoot, join(globalNodeModules, 'npm'), 'npm root is in the testdir')
70-
t.equal(prePaths.pathNpm, join(globalBin, 'npm'), 'npm bin is in the testdir')
71-
t.equal(prePaths.pathNpx, join(globalBin, 'npx'), 'npx bin is in the testdir')
72-
t.not(prePaths.pathNpm, prePaths.globalNpm, 'npm bin is not the same as the global one')
73-
t.not(prePaths.pathNpx, prePaths.globalNpx, 'npm bin is not the same as the global one')
74-
t.ok(prePaths.nodeModulesContents.length > 1, 'node modules has npm contents')
75-
t.ok(prePaths.nodeModulesContents.includes('node_modules'), 'npm has its node_modules')
76-
77-
t.strictSame(
78-
prePaths.binContents,
79-
['npm', 'npx'].flatMap(p => setup.WINDOWS ? [p, `${p}.cmd`, `${p}.ps1`] : p),
80-
'bin has npm and npx'
81-
)
82-
83-
await npmPath('pack')
84-
await npmPath('install', 'npm-999.999.999.tgz', '--global')
85-
86-
const postPaths = await getPaths()
87-
t.not(prePaths.npmRoot, postPaths.npmRoot, 'npm roots are different')
88-
t.equal(postPaths.pathNpm, postPaths.globalNpm, 'npm bin is the same as the global one')
89-
t.equal(postPaths.pathNpx, postPaths.globalNpx, 'npx bin is the same as the global one')
90-
t.equal(postPaths.pathNpm, prePaths.globalNpm, 'after install npm bin is same as previous global')
91-
t.equal(postPaths.pathNpx, prePaths.globalNpx, 'after install npx bin is same as previous global')
92-
t.strictSame(postPaths.binContents, [], 'bin is empty')
93-
t.strictSame(postPaths.nodeModulesContents, ['package.json'], 'contents is only package.json')
94-
})
95-
9639
t.test('publish and replace global self', async t => {
9740
let publishedPackument = null
9841
const pkg = require('../../package.json')
@@ -121,11 +64,12 @@ t.test('publish and replace global self', async t => {
12164
})
12265
}
12366

124-
const npmInstall = async (useNpm) => {
67+
const npmInstall = async (useNpm, opts) => {
12568
await npmPackage({
12669
manifest: { packuments: [publishedPackument] },
12770
tarballs: { [version]: tarball },
12871
times: 3,
72+
...opts,
12973
})
13074
await fs.rm(cache, { recursive: true, force: true })
13175
await useNpm('install', 'npm@latest', '--global')

0 commit comments

Comments
 (0)
Please sign in to comment.