build-strap 6.1.0-main.174 → 6.1.0-main.176

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,51 +6,39 @@ This project builds itself, so take a look in the `targets/` folder for an examp
6
6
  [![CI Build](https://github.com/murrayju/build-strap/workflows/CI%20Build/badge.svg?branch=main)](https://github.com/murrayju/build-strap/actions?query=workflow%3A%22CI+Build%22)
7
7
  [![version](https://img.shields.io/github/v/tag/murrayju/build-strap.svg?label=version&sort=semver)](https://github.com/murrayju/build-strap/releases/latest)
8
8
  [![npm](https://img.shields.io/npm/v/build-strap)](https://npmjs.org/package/build-strap)
9
- [![dependencies](https://img.shields.io/david/murrayju/build-strap.svg)](https://david-dm.org/murrayju/build-strap)
10
- [![devDependencies](https://img.shields.io/david/dev/murrayju/build-strap.svg)](https://david-dm.org/murrayju/build-strap?type=dev)
11
9
 
12
10
  ## Create a "zero dependency" bootstrapped build
13
- You can set up your project to build with (practically) no pre-requisite dependencies. [nub-strap](https://github.com/murrayju/nub-strap/) downloads a pinned version of [nub](https://nubjs.com) into the project. Nub then provides the pinned versions of node and yarn.
11
+ You can set up your project to build with (practically) no pre-requisite dependencies. [nub-strap](https://github.com/murrayju/nub-strap/) downloads a pinned version of [nub](https://nubjs.com) into the project. Nub then provides the pinned version of node, and is also the package manager.
14
12
  - Copy the `nub` script from nub-strap into the root of your project, and pin the nub version in it.
15
13
 
16
14
  ```
17
15
  curl -o nub https://raw.githubusercontent.com/murrayju/nub-strap/main/nub && chmod +x nub
18
16
  ```
19
17
 
20
- - Pin the node and yarn versions in your `package.json`.
18
+ - Pin the node version in your `package.json`, and set nub as the package manager (`./nub pm use nub` does this, and converts an existing lockfile to `nub.lock`).
21
19
 
22
20
  ```
23
21
  {
24
22
  "devEngines": {
25
- "runtime": { "name": "node", "version": "24.18.0" }
26
- },
27
- "packageManager": "yarn@1.22.22"
23
+ "runtime": { "name": "node", "version": "24.18.0" },
24
+ "packageManager": { "name": "nub", "version": "^0.10.0", "onFail": "ignore" }
25
+ }
28
26
  }
29
27
  ```
30
28
 
31
- - Add a `yarn` script, which runs the pinned yarn with nub.
32
-
33
- ```
34
- #!/bin/bash
35
- set -euo pipefail
36
-
37
- yarnJs=$(./nub pm which)
38
- exec ./nub --node "$yarnJs" "$@"
39
- ```
40
-
41
29
  - Add a `bs` script, which installs dependencies and runs your build targets.
42
30
 
43
31
  ```
44
32
  #!/bin/bash
45
33
 
46
- ./yarn install
34
+ ./nub install
47
35
  exec ./nub ./targets/run.ts "$@"
48
36
  ```
49
37
 
50
38
  ## Add the dependency reference
51
39
  Add `build-strap` to your `package.json` (likely in the `devDependencies` section).
52
40
  ```
53
- yarn add -D build-strap
41
+ ./nub add -D build-strap
54
42
  ```
55
43
 
56
44
  ## Add meta information to your `package.json`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "build-strap",
3
- "version": "6.1.0-main.174",
3
+ "version": "6.1.0-main.176",
4
4
  "description": "Node scripts for building things",
5
5
  "license": "MIT",
6
6
  "author": "Justin Murray <justin@murrayju.com>",
@@ -9,11 +9,12 @@
9
9
  "url": "https://github.com/murrayju/build-strap"
10
10
  },
11
11
  "type": "module",
12
- "main": "./src/index.js",
13
- "types": "./src/index.d.ts",
14
12
  "engines": {
15
13
  "node": ">=24"
16
14
  },
15
+ "resolutions": {
16
+ "minimatch": "^11.0.5"
17
+ },
17
18
  "dependencies": {
18
19
  "bytes": "^3.1.1",
19
20
  "chokidar": "^6.0.0",
@@ -23,14 +24,9 @@
23
24
  "glob": "^14.0.4",
24
25
  "is-reachable": "^6.1.0",
25
26
  "js-yaml": "^5.5.0",
26
- "lodash-es": "^4.17.21",
27
- "moment": "^2.31.0",
28
- "node-fetch": "^3.3.2",
29
27
  "rimraf": "^6.1.4",
30
- "stream-counter": "1",
31
28
  "tar": "^7.1.0"
32
29
  },
33
- "resolutions": {
34
- "minimatch": "^11.0.5"
35
- }
30
+ "main": "./src/index.js",
31
+ "types": "./src/index.d.ts"
36
32
  }
package/src/cert.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import fs from 'fs-extra';
2
- import fetch from 'node-fetch';
3
2
  import os from 'os';
4
3
  import path from 'path';
5
4
  import { spawn } from './cp.js';
@@ -1,2 +1,12 @@
1
- import moment from 'moment';
2
- export const parseDockerDate = (date) => moment(date, 'YYYY-MM-DD HH:mm:ss ZZ').toDate();
1
+ // Docker prints dates in the Go format "2006-01-02 15:04:05.999999999 -0700 MST".
2
+ // We ignore the fractional seconds and the zone name.
3
+ const dockerDatePattern = /^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})(?:\.\d+)? ([+-]\d{2})(\d{2})/;
4
+ // Returns an invalid Date (NaN time) when the text does not match.
5
+ export const parseDockerDate = (date) => {
6
+ const match = dockerDatePattern.exec(date);
7
+ if (!match) {
8
+ return new Date(NaN);
9
+ }
10
+ const [, day, time, offsetHours, offsetMinutes] = match;
11
+ return new Date(`${day}T${time}${offsetHours}:${offsetMinutes}`);
12
+ };
@@ -1,5 +1,3 @@
1
- import { uniq } from 'lodash-es';
2
- import moment from 'moment';
3
1
  import { dockerContainerLs } from './docker.container.js';
4
2
  import { dockerImages, dockerRmi, getDockerRepo, getDockerTags, getUntaggedDockerIds, } from './docker.js';
5
3
  import { buildLog } from './run.js';
@@ -45,22 +43,24 @@ export const dockerImageCleanup = async ({ buildImageIds = [], dryRun = process.
45
43
  const filterLatest = (m) => purgeAll || !/^latest(-\w+)?$/.exec(m.tag);
46
44
  // only match images more than an hour old, AND without a :latest* tag
47
45
  const filterOld = (m) => purgeAll ||
48
- (filterLatest(m) && moment().subtract(1, 'h').isAfter(m.created));
49
- const uniqueList = uniq([
50
- // the things that we know were just built by us
51
- // remove all tags from the given repos with a matching `buildImageIds`, except for :latest*
52
- ...(await flatten(repos.map((r) => buildImageIds.map(async (b) => getDockerTags(b, r, true, filterLatest))))),
53
- // unconditionally delete explicitly passed images/ids
54
- ...images,
55
- // images in the given `repos` without a tag, older than 1hr
56
- ...(await flatten(repos.map(async (r) => getUntaggedDockerIds(r, filterOld)))),
57
- // images with no repo and no tag
58
- ...(await dockerImages(null, (m) => m.repository === '<none>' && m.tag === '<none>' && filterOld(m))).map((m) => m.id),
59
- // any leftover tags from prior builds (only if purgeAll or purgeOld)
60
- ...(purgeAll || purgeOld
61
- ? await flatten(repos.map(async (r) => getDockerTags(null, r, true, filterOld)))
62
- : []),
63
- ]);
46
+ (filterLatest(m) && m.created.getTime() < Date.now() - 60 * 60 * 1000);
47
+ const uniqueList = [
48
+ ...new Set([
49
+ // the things that we know were just built by us
50
+ // remove all tags from the given repos with a matching `buildImageIds`, except for :latest*
51
+ ...(await flatten(repos.map((r) => buildImageIds.map(async (b) => getDockerTags(b, r, true, filterLatest))))),
52
+ // unconditionally delete explicitly passed images/ids
53
+ ...images,
54
+ // images in the given `repos` without a tag, older than 1hr
55
+ ...(await flatten(repos.map(async (r) => getUntaggedDockerIds(r, filterOld)))),
56
+ // images with no repo and no tag
57
+ ...(await dockerImages(null, (m) => m.repository === '<none>' && m.tag === '<none>' && filterOld(m))).map((m) => m.id),
58
+ // any leftover tags from prior builds (only if purgeAll or purgeOld)
59
+ ...(purgeAll || purgeOld
60
+ ? await flatten(repos.map(async (r) => getDockerTags(null, r, true, filterOld)))
61
+ : []),
62
+ ]),
63
+ ];
64
64
  if (dryRun) {
65
65
  buildLog(`Images to delete (dry run):\n ${uniqueList.join('\n ')}`);
66
66
  }
package/src/fetch.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs-extra';
2
- import fetch from 'node-fetch';
3
2
  import path from 'path';
3
+ import { Readable } from 'stream';
4
+ import { pipeline } from 'stream/promises';
4
5
  export const downloadFile = async (url, saveAs, overwrite = true) => {
5
6
  const res = await fetch(url);
6
7
  const { body, ok } = res;
@@ -11,10 +12,5 @@ export const downloadFile = async (url, saveAs, overwrite = true) => {
11
12
  if (overwrite) {
12
13
  await fs.remove(saveAs);
13
14
  }
14
- const fileStream = fs.createWriteStream(saveAs);
15
- await new Promise((resolve, reject) => {
16
- body.pipe(fileStream);
17
- body.on('error', reject);
18
- fileStream.on('finish', resolve);
19
- });
15
+ await pipeline(Readable.fromWeb(body), fs.createWriteStream(saveAs));
20
16
  };
package/src/npm.js CHANGED
@@ -17,7 +17,6 @@ export async function npm({ args = [], npmPath, spawnOptions, } = {}) {
17
17
  const localNpm = path.join(path.dirname(process.execPath), platform() === 'win32' ? '' : '../lib', 'node_modules/npm/bin/npm-cli.js');
18
18
  const spawnOpts = {
19
19
  env: process.env,
20
- shell: true,
21
20
  stdio: 'inherit',
22
21
  ...spawnOptions,
23
22
  };
package/src/tgz.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import crypto from 'crypto';
2
2
  import fs from 'fs-extra';
3
3
  import path from 'path';
4
- import StreamCounter from 'stream-counter';
4
+ import { Writable } from 'stream';
5
5
  import { create } from 'tar';
6
6
  import { buildLog } from './run.js';
7
7
  const generateHash = async (stream, type) => new Promise((resolve, reject) => {
@@ -19,14 +19,17 @@ const generateHash = async (stream, type) => new Promise((resolve, reject) => {
19
19
  });
20
20
  export const generateFileHash = async (filePath, type) => generateHash(fs.createReadStream(filePath), type);
21
21
  const countBytes = async (stream) => new Promise((resolve, reject) => {
22
- const counter = new StreamCounter();
22
+ let byteCount = 0;
23
+ const counter = new Writable({
24
+ write(chunk, _encoding, callback) {
25
+ byteCount += chunk.length;
26
+ callback();
27
+ },
28
+ });
23
29
  stream
24
30
  .pipe(counter)
25
31
  .on('finish', () => {
26
- resolve(counter.bytes);
27
- })
28
- .on('end', () => {
29
- resolve(counter.bytes);
32
+ resolve(byteCount);
30
33
  })
31
34
  .on('error', (err) => {
32
35
  reject(err);
package/src/yarn.js CHANGED
@@ -11,7 +11,6 @@ export async function yarn({ args = [], spawnOptions, } = {}) {
11
11
  const localYarn = path.join(path.dirname(process.execPath), '/node_modules/yarn/bin/yarn.js');
12
12
  const spawnOpts = {
13
13
  env: process.env,
14
- shell: true,
15
14
  stdio: 'inherit',
16
15
  ...spawnOptions,
17
16
  };
@@ -131,7 +130,6 @@ export async function yarnPublish({ npmAuthToken, npmConfig, npmCreds, npmPath,
131
130
  FORCE_COLOR: 'true',
132
131
  NPM_TOKEN: authToken,
133
132
  },
134
- shell: true,
135
133
  stdio: 'inherit',
136
134
  },
137
135
  });