chore(deps): track client/.npmrc and run the generator explicitly
Dependency install hooks now stay off in client/, as they already are at the root and in sas/: client/.npmrc is committed with ignore-scripts and save-exact, the root install script runs `npm run postinstall` after installing, and both CI installs pass --ignore-scripts and then run the generator by hand. The client's own postinstall is what creates src/environments/version.ts and the hot icons, so it has to run - it is third-party hooks that do not. CI writes client/.npmrc from the NPMRC secret; the second job now appends rather than overwrites so the tracked policy survives (the first already appended). The archiver guard reads the archive back instead of checking its size: a matcher that takes the top-level file and misses the nested directory clears any size threshold, and that is exactly the failure it exists to catch. It now asserts a.txt and sub/b.txt are both present.
This commit is contained in:
1 parent
786d15ab0f
commit
c97082e468
5 files changed
+32
-16
No files matched your search
@@ -51,9 +51,10 @@ jobs:
|
||||
gpg --batch --yes --passphrase-fd 0 \
|
||||
--output ./libraries/sheet-crypto.tgz \
|
||||
--decrypt ./libraries/sheet-crypto.tgz.gpg
|
||||
# no --ignore-scripts here: the client's install scripts generate
|
||||
# src/environments/version.ts, which the app imports
|
||||
npm ci
|
||||
# dependency hooks stay off (client/.npmrc); the client's own
|
||||
# generator runs explicitly, because the app imports the file it makes
|
||||
npm ci --ignore-scripts
|
||||
npm run postinstall
|
||||
|
||||
- name: Check audit
|
||||
# Audit should fail and stop the CI on any vulnerability in root and sas, and on low+ in client
|
||||
@@ -130,7 +131,7 @@ jobs:
|
||||
- name: Write .npmrc file
|
||||
run: |
|
||||
touch client/.npmrc
|
||||
echo '${{ secrets.NPMRC}}' > client/.npmrc
|
||||
echo '${{ secrets.NPMRC}}' >> client/.npmrc
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
@@ -153,7 +154,10 @@ jobs:
|
||||
cd client
|
||||
# Decrypt and Install sheet
|
||||
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
|
||||
npm ci
|
||||
# dependency hooks stay off (client/.npmrc); the client's own
|
||||
# generator runs explicitly, because the app imports the file it makes
|
||||
npm ci --ignore-scripts
|
||||
npm run postinstall
|
||||
|
||||
- name: Build frontend for web streaming
|
||||
# The server-ci target streams client/dist as the 'clickme' web app (see
|
||||
|
||||
@@ -20,7 +20,6 @@ sasjsbuild
|
||||
sasjsresults
|
||||
.env*
|
||||
.sasjsrc
|
||||
client/.npmrc
|
||||
*~
|
||||
.lighthouseci
|
||||
audit.log
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ignore-scripts=true
|
||||
save-exact=true
|
||||
# dependency install hooks are skipped: the client's own postinstall generates
|
||||
# src/environments/version.ts and the hot icons, so run `npm run postinstall`
|
||||
# after installing (the root install script does this for you)
|
||||
@@ -3,13 +3,17 @@
|
||||
* The override forces minimatch 11 where readdir-glob asks for ^10. An
|
||||
* incompatible API would only show up at runtime, in the one place that walks a
|
||||
* directory through readdir-glob: archiver's directory(), which exceljs uses to
|
||||
* build an xlsx. This archives a small tree and checks the archive holds both
|
||||
* files, so a broken override fails here rather than in a user's download.
|
||||
* build an xlsx.
|
||||
*
|
||||
* The archive is read back and both entries are asserted, because the failure
|
||||
* worth catching is a matcher that takes the top-level file and silently misses
|
||||
* the nested one.
|
||||
*/
|
||||
import fs from 'node:fs'
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { ZipArchive } from 'archiver'
|
||||
import unzipper from 'unzipper'
|
||||
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dc-arch-'))
|
||||
fs.writeFileSync(path.join(dir, 'a.txt'), 'hello')
|
||||
@@ -24,16 +28,20 @@ archive.on('error', (err) => {
|
||||
console.error('archiver error: ' + err.message)
|
||||
process.exit(1)
|
||||
})
|
||||
sink.on('close', () => {
|
||||
const bytes = fs.statSync(out).size
|
||||
/* two tiny files plus central directory; an empty or truncated archive is far
|
||||
smaller, which is what a broken glob matcher would produce */
|
||||
if (bytes < 200) {
|
||||
console.error('archive is too small: ' + bytes + ' bytes')
|
||||
|
||||
sink.on('close', async () => {
|
||||
const listing = await unzipper.Open.file(out)
|
||||
const names = listing.files.map((f) => f.path)
|
||||
const missing = ['a.txt', 'sub/b.txt'].filter((n) => !names.includes(n))
|
||||
if (missing.length) {
|
||||
console.error(
|
||||
'archiver directory walk missed: ' + missing.join(', ') + ' (got: ' + names.join(', ') + ')'
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log('archiver directory walk ok: ' + bytes + ' bytes')
|
||||
console.log('archiver directory walk ok: ' + names.join(', '))
|
||||
})
|
||||
|
||||
archive.pipe(sink)
|
||||
archive.directory(dir, false)
|
||||
archive.finalize()
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
"got": "11.8.6"
|
||||
},
|
||||
"scripts": {
|
||||
"install": "cd client && npm i && cd ../sas && npm i",
|
||||
"install": "cd client && npm i && npm run postinstall && cd ../sas && npm i",
|
||||
"build-frontend": "cd client && npm run build",
|
||||
"lint": "cd client && npm run lint",
|
||||
"lint:fix": "cd client && npm run lint:fix",
|
||||
|
||||
Reference in new issue
Block a user