Skip to content

Commit 51a676d

Browse files
committed
chore: aligned CICD with js-quic
WIP: updated prebuild script WIP: ignored binding.gyp so that `npm i` doesn't trigger build WIP: added all optional deps WIP: update package lock optional deps WIP: removed unneeded optional deps WIP: removed trailing comma in package.json WIP: fixed prebuild WIP: added recursive to mkdir to avoid errors on exist
1 parent a8383c2 commit 51a676d

10 files changed

+297
-54
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
/builds
88
# node-gyp
99
/build
10-
# prebuildify
11-
/prebuilds
10+
/prebuild
11+
/prepublishOnly
1212

1313
# Logs
1414
logs

.gitlab-ci.yml

+11-8
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ check:test:
8383
coverage_format: cobertura
8484
path: ./tmp/coverage/cobertura-coverage.xml
8585
paths:
86-
- ./prebuilds/
86+
- ./prebuild/
8787
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
8888
rules:
8989
# Runs on feature commits and ignores version commits
@@ -193,7 +193,7 @@ build:windows:
193193
coverage_format: cobertura
194194
path: ./tmp/coverage/cobertura-coverage.xml
195195
paths:
196-
- ./prebuilds/
196+
- ./prebuild/
197197
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
198198
rules:
199199
# Runs on staging commits and ignores version commits
@@ -243,6 +243,9 @@ build:prerelease:
243243
- build:macos
244244
# Don't interrupt publishing job
245245
interruptible: false
246+
variables:
247+
# Set the prerelease tag for prepublishOnly script
248+
npm_config_tag: 'prerelease'
246249
script:
247250
- echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ./.npmrc
248251
- echo 'Publishing library prerelease'
@@ -251,12 +254,12 @@ build:prerelease:
251254
npm publish --tag prerelease --access public;
252255
'
253256
- >
254-
for d in prebuilds/*; do
257+
for d in prebuild/*; do
255258
tar \
256259
--create \
257260
--verbose \
258-
--file="prebuilds/$(basename $d).tar" \
259-
--directory=prebuilds \
261+
--file="prebuild/$(basename $d).tar" \
262+
--directory=prebuild \
260263
"$(basename $d)";
261264
done
262265
after_script:
@@ -323,12 +326,12 @@ release:distribution:
323326
npm publish --access public;
324327
'
325328
- >
326-
for d in prebuilds/*; do
329+
for d in /*; do
327330
tar \
328331
--create \
329332
--verbose \
330-
--file="prebuilds/$(basename $d).tar" \
331-
--directory=prebuilds \
333+
--file="prebuild/$(basename $d).tar" \
334+
--directory=prebuild \
332335
"$(basename $d)";
333336
done
334337
after_script:

.npmignore

+4
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@
1212
/benches
1313
/build
1414
/builds
15+
/prebuild
16+
/prepublishOnly
17+
/binding.gyp
1518
/dist/tsbuildinfo
19+

package-lock.json

+4-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121
"gypfile": true,
2222
"scripts": {
2323
"prepare": "tsc -p ./tsconfig.build.json",
24-
"install": "node-gyp-build",
2524
"prebuild": "node ./scripts/prebuild.js",
2625
"build": "shx rm -rf ./dist && tsc -p ./tsconfig.build.json",
26+
"version": "node ./scripts/version.js",
2727
"postversion": "npm install --package-lock-only --ignore-scripts --silent",
28+
"prepublishOnly": "node ./scripts/prepublishOnly.js",
2829
"ts-node": "ts-node",
2930
"test": "jest",
3031
"lint": "eslint '{src,tests,scripts,benches}/**/*.{js,ts}'",
@@ -41,8 +42,10 @@
4142
"@matrixai/table": "^1.2.0",
4243
"@matrixai/timer": "^1.1.1",
4344
"canonicalize": "^2.0.0",
44-
"ip-num": "^1.5.1",
45-
"node-gyp-build": "^4.6.0"
45+
"ip-num": "^1.5.1"
46+
},
47+
"optionalDependencies": {
48+
"@matrixai/mdns-linux-x64": "1.0.0"
4649
},
4750
"devDependencies": {
4851
"@fast-check/jest": "^1.6.2",

scripts/prebuild.js

+12-16
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,17 @@ async function main(argv = process.argv) {
3636
while (argv.length > 0) {
3737
const option = argv.shift();
3838
let match;
39-
if ((match = option.match(/--nodedir(?:=(.+)|$)/))) {
40-
nodedir = match[1] ?? argv.shift();
41-
} else if ((match = option.match(/--devdir(?:=(.+)|$)/))) {
42-
devdir = match[1] ?? argv.shift();
43-
} else if ((match = option.match(/--arch(?:=(.+)|$)/))) {
39+
if ((match = option.match(/--arch(?:=(.+)|$)/))) {
4440
arch = match[1] ?? argv.shift();
41+
} else if ((match = option.match(/--production$/))) {
42+
production = true;
4543
} else {
4644
restArgs.push(option);
4745
}
4846
}
47+
if (arch == null) {
48+
arch = process.env.npm_config_arch ?? os.arch();
49+
}
4950

5051
if (nodedir == null) {
5152
nodedir = process.env.npm_config_nodedir;
@@ -60,7 +61,7 @@ async function main(argv = process.argv) {
6061
}
6162

6263
// If `nodedir` is specified, this means the headers are already part of the node source code
63-
// When using `nix`, alwys specify the `nodedir` to avoid downloading from the internet in the middle of `nix-build`
64+
// When using `nix`, always specify the `nodedir` to avoid downloading from the internet in the middle of `nix-build`
6465
if (nodedir == null) {
6566
// If `devdir` is not specified, node-gyp will place headers into default cache
6667
// Linux: `$XDG_CACHE_HOME/node-gyp` or `$HOME/.cache/node-gyp`
@@ -129,24 +130,19 @@ async function main(argv = process.argv) {
129130

130131
const projectRoot = path.join(__dirname, '..');
131132
const buildsPath = path.join(projectRoot, 'build', 'Release');
132-
const prebuildsPath = path.join(projectRoot, 'prebuilds');
133+
const prebuildsPath = path.join(projectRoot, 'prebuild');
133134

134135
const buildNames = await fs.promises.readdir(buildsPath);
135136
const buildName = buildNames.find((filename) => /\.node$/.test(filename));
136137
const buildPath = path.join(buildsPath, buildName);
137138

138-
const prebuildTuple = `${platform}-${arch}`;
139-
// Tags are dot separated `<runtime>.<abi>.<othertag>`
140-
// <runtime>: node | electron | node-webkit
141-
// <abi>: napi | abi\d+
142-
// Other tags depends on node-gyp-build parser
143-
const prebuildTags = ['node', 'napi'].join('.');
139+
const prebuildName = `mdns-${platform}-${arch}`;
144140
// The path must end with `.node`
145141
const prebuildPath =
146-
path.join(prebuildsPath, prebuildTuple, prebuildTags) + '.node';
142+
path.join(prebuildsPath, prebuildName) + '.node';
147143

148-
await fs.promises.mkdir(path.join(prebuildsPath, prebuildTuple), {
149-
recursive: true,
144+
await fs.promises.mkdir(prebuildsPath, {
145+
recursive: true
150146
});
151147

152148
console.error(`Copying ${buildPath} to ${prebuildPath}`);

scripts/prepublishOnly.js

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* This runs before `npm publish` command.
5+
* This will take the native objects in `prebuild/`
6+
* and create native packages under `prepublishOnly/`.
7+
*
8+
* For example:
9+
*
10+
* /prepublishOnly
11+
* /@org
12+
* /name-linux-x64
13+
* /package.json
14+
* /node.napi.node
15+
* /README.md
16+
*/
17+
18+
const os = require('os');
19+
const fs = require('fs');
20+
const path = require('path');
21+
const process = require('process');
22+
const childProcess = require('child_process');
23+
const packageJSON = require('../package.json');
24+
25+
const platform = os.platform();
26+
27+
/* eslint-disable no-console */
28+
async function main(argv = process.argv) {
29+
argv = argv.slice(2);
30+
let tag;
31+
let dryRun = false;
32+
const restArgs = [];
33+
while (argv.length > 0) {
34+
const option = argv.shift();
35+
let match;
36+
if ((match = option.match(/--tag(?:=(.+)|$)/))) {
37+
tag = match[1] ?? argv.shift();
38+
} else if ((match = option.match(/--dry-run$/))) {
39+
dryRun = true;
40+
} else {
41+
restArgs.push(option);
42+
}
43+
}
44+
if (tag == null) {
45+
tag = process.env.npm_config_tag;
46+
}
47+
const projectRoot = path.join(__dirname, '..');
48+
const prebuildPath = path.join(projectRoot, 'prebuild');
49+
const prepublishOnlyPath = path.join(projectRoot, 'prepublishOnly');
50+
const buildNames = (await fs.promises.readdir(prebuildPath)).filter(
51+
(filename) => /^(?:[^-]+)-(?:[^-]+)-(?:[^-]+)$/.test(filename),
52+
);
53+
if (buildNames.length < 1) {
54+
console.error(
55+
'You must prebuild at least 1 native object with the filename of `name-platform-arch` before prepublish',
56+
);
57+
process.exitCode = 1;
58+
return process.exitCode;
59+
}
60+
// Extract out the org name, this may be undefined
61+
const orgName = packageJSON.name.match(/^@[^/]+/)?.[0];
62+
for (const buildName of buildNames) {
63+
// This is `name-platform-arch`
64+
const name = path.basename(buildName, '.node');
65+
// This is `@org/name-platform-arch`, uses `posix` to force usage of `/`
66+
const packageName = path.posix.join(orgName ?? '', name);
67+
const constraints = name.match(
68+
/^(?:[^-]+)-(?<platform>[^-]+)-(?<arch>[^-]+)$/,
69+
);
70+
// This will be `prebuild/name-platform-arch.node`
71+
const buildPath = path.join(prebuildPath, buildName);
72+
// This will be `prepublishOnly/@org/name-platform-arch`
73+
const packagePath = path.join(prepublishOnlyPath, packageName);
74+
console.error('Packaging:', packagePath);
75+
try {
76+
await fs.promises.rm(packagePath, {
77+
recursive: true,
78+
});
79+
} catch (e) {
80+
if (e.code !== 'ENOENT') throw e;
81+
}
82+
await fs.promises.mkdir(packagePath, { recursive: true });
83+
const nativePackageJSON = {
84+
name: packageName,
85+
version: packageJSON.version,
86+
homepage: packageJSON.homepage,
87+
author: packageJSON.author,
88+
contributors: packageJSON.contributors,
89+
description: packageJSON.description,
90+
keywords: packageJSON.keywords,
91+
license: packageJSON.license,
92+
repository: packageJSON.repository,
93+
main: 'node.napi.node',
94+
os: [constraints.groups.platform],
95+
cpu: [...constraints.groups.arch.split('+')],
96+
};
97+
const packageJSONPath = path.join(packagePath, 'package.json');
98+
console.error(`Writing ${packageJSONPath}`);
99+
const packageJSONString = JSON.stringify(nativePackageJSON, null, 2);
100+
console.error(packageJSONString);
101+
await fs.promises.writeFile(packageJSONPath, packageJSONString, {
102+
encoding: 'utf-8',
103+
});
104+
const packageReadmePath = path.join(packagePath, 'README.md');
105+
console.error(`Writing ${packageReadmePath}`);
106+
const packageReadme = `# ${packageName}\n`;
107+
console.error(packageReadme);
108+
await fs.promises.writeFile(packageReadmePath, packageReadme, {
109+
encoding: 'utf-8',
110+
});
111+
const packageBuildPath = path.join(packagePath, 'node.napi.node');
112+
console.error(`Copying ${buildPath} to ${packageBuildPath}`);
113+
await fs.promises.copyFile(buildPath, packageBuildPath);
114+
const publishArgs = [
115+
'publish',
116+
packagePath,
117+
...(tag != null ? [`--tag=${tag}`] : []),
118+
'--access=public',
119+
...(dryRun ? ['--dry-run'] : []),
120+
];
121+
console.error('Running npm publish:');
122+
console.error(['npm', ...publishArgs].join(' '));
123+
childProcess.execFileSync('npm', publishArgs, {
124+
stdio: ['inherit', 'inherit', 'inherit'],
125+
windowsHide: true,
126+
encoding: 'utf-8',
127+
shell: platform === 'win32' ? true : false,
128+
});
129+
}
130+
}
131+
/* eslint-enable no-console */
132+
133+
void main();

0 commit comments

Comments
 (0)