Skip to content

Commit a96ed90

Browse files
committed
docs: update architecture and matrix status; improve clarity and accuracy
refactor: streamline imports and enhance file handling in core modules test: enhance unit tests with additional fs utilities and assertions
1 parent 9781c17 commit a96ed90

10 files changed

Lines changed: 39 additions & 50 deletions

File tree

docs/architecture.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Living reference for how `pkg-action` is put together. Updated whenever
44
structure changes; pipeline intent lives here so `packages/build/src/main.ts`
55
can stay focused on wiring.
66

7-
> Status: authoritative for v1.0 candidate (2026-04-23). If this file and the
8-
> code disagree, the code wins and this file is a bug.
7+
> Reflects the v1.0 candidate (as of 2026-04-23). Code is the source of
8+
> truth — if this file and the code disagree, the file is stale, file a fix.
99
1010
---
1111

docs/matrix.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ hardware that matches the target — so you never rely on cross-compilation.
88

99
## Status
1010

11-
> **M2under construction.** See [`STATUS.yaml`](../STATUS.yaml) for the
12-
> current milestone state. Pin a commit SHA if you depend on this before
13-
> `v1.0.0`.
11+
> **ALPHAready for early adopters.** Surface is stable for M2; see
12+
> [`STATUS.yaml`](../STATUS.yaml) for full milestone state. Pin a commit
13+
> SHA if you depend on this before `v1.0.0`.
1414
1515
## Inputs
1616

packages/build/dist/index.mjs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14498,7 +14498,8 @@ function getState(name) {
1449814498

1449914499
// packages/build/src/main.ts
1450014500
import { mkdir as mkdir3, rename as rename3, stat as stat4 } from "node:fs/promises";
14501-
import { basename as pathBasename, dirname as dirname4, join as join7, resolve as pathResolve } from "node:path";
14501+
import { tmpdir as tmpdir2 } from "node:os";
14502+
import { basename as pathBasename, dirname as dirname5, join as join7, resolve as pathResolve } from "node:path";
1450214503

1450314504
// packages/core/src/errors.ts
1450414505
var PkgActionError = class extends Error {
@@ -15277,8 +15278,9 @@ async function exists2(path4) {
1527715278
// packages/core/src/archive.ts
1527815279
var import_yazl = __toESM(require_yazl(), 1);
1527915280
import { createWriteStream } from "node:fs";
15280-
import { stat as stat3 } from "node:fs/promises";
15281-
import { basename as basename4 } from "node:path";
15281+
import { mkdtemp, rm as rm3, stat as stat3, symlink as symlink2, utimes } from "node:fs/promises";
15282+
import { tmpdir } from "node:os";
15283+
import { basename as basename4, dirname as dirname4 } from "node:path";
1528215284
import { pipeline as pipeline2 } from "node:stream/promises";
1528315285
async function archive(req, deps) {
1528415286
let entry = req.entryName ?? basename4(req.inputPath), mode = req.mode ?? 493;
@@ -15300,7 +15302,7 @@ async function archive(req, deps) {
1530015302
}
1530115303
var REPRO_MTIME = new Date(Date.UTC(2020, 0, 1, 0, 0, 0)), REPRO_MTIME_TAR = "2020-01-01 00:00:00 UTC";
1530215304
async function shellTar(inputPath, outputPath, compression, entry, deps) {
15303-
let { dirname: dirname5 } = await import("node:path"), { mkdtemp, symlink: symlink2, utimes, rm: rm3 } = await import("node:fs/promises"), { tmpdir } = await import("node:os"), compressFlag = compression === "gz" ? "-z" : "-J", stageDir, workDir = dirname5(inputPath), fileName = basename4(inputPath);
15305+
let compressFlag = compression === "gz" ? "-z" : "-J", stageDir, workDir = dirname4(inputPath), fileName = basename4(inputPath);
1530415306
if (entry !== basename4(inputPath)) {
1530515307
stageDir = await mkdtemp(`${tmpdir()}/pkgaction-tar-`);
1530615308
let linkPath = `${stageDir}/${entry}`;
@@ -15344,7 +15346,7 @@ async function writeZip(inputPath, outputPath, entry, mode) {
1534415346
}
1534515347
}
1534615348
async function shell7z(inputPath, outputPath, entry, deps) {
15347-
let { dirname: dirname5 } = await import("node:path"), { mkdtemp, symlink: symlink2, rm: rm3 } = await import("node:fs/promises"), { tmpdir } = await import("node:os"), stageDir, workDir = dirname5(inputPath), fileName = basename4(inputPath);
15349+
let stageDir, workDir = dirname4(inputPath), fileName = basename4(inputPath);
1534815350
if (entry !== basename4(inputPath)) {
1534915351
stageDir = await mkdtemp(`${tmpdir()}/pkgaction-7z-`);
1535015352
let linkPath = `${stageDir}/${entry}`;
@@ -15548,13 +15550,13 @@ function normalizeFileIcons(file) {
1554815550
return [...out.values()].sort((a, b) => a.id - b.id);
1554915551
}
1555015552
async function parseWindowsMetadataInputs(opts = {}) {
15551-
let env = opts.env ?? process.env, readFile2 = opts.readFile ?? ((path4) => import("node:fs/promises").then((m) => m.readFile(path4, "utf8"))), prefix = opts.prefix ?? "windows-", read = (name) => readInputRaw(env, `${prefix}${name}`), fileRaw = read("metadata-file"), iconRaw = read("icon"), productName = read("product-name"), productVersion = read("product-version"), fileVersion = read("file-version"), fileDescription = read("file-description"), companyName = read("company-name"), legalCopyright = read("legal-copyright"), originalFilename = read("original-filename"), internalName = read("internal-name"), comments = read("comments"), manifestPath = read("manifest"), langRaw = read("lang"), codepageRaw = read("codepage");
15553+
let env = opts.env ?? process.env, readFile3 = opts.readFile ?? ((path4) => import("node:fs/promises").then((m) => m.readFile(path4, "utf8"))), prefix = opts.prefix ?? "windows-", read = (name) => readInputRaw(env, `${prefix}${name}`), fileRaw = read("metadata-file"), iconRaw = read("icon"), productName = read("product-name"), productVersion = read("product-version"), fileVersion = read("file-version"), fileDescription = read("file-description"), companyName = read("company-name"), legalCopyright = read("legal-copyright"), originalFilename = read("original-filename"), internalName = read("internal-name"), comments = read("comments"), manifestPath = read("manifest"), langRaw = read("lang"), codepageRaw = read("codepage");
1555215554
if (!(fileRaw !== void 0 || iconRaw !== void 0 || productName !== void 0 || productVersion !== void 0 || fileVersion !== void 0 || fileDescription !== void 0 || companyName !== void 0 || legalCopyright !== void 0 || originalFilename !== void 0 || internalName !== void 0 || comments !== void 0 || manifestPath !== void 0)) return null;
1555315555
let fileData;
1555415556
if (fileRaw !== void 0) {
1555515557
let contents;
1555615558
try {
15557-
contents = await readFile2(fileRaw);
15559+
contents = await readFile3(fileRaw);
1555815560
} catch (err) {
1555915561
throw new ValidationError(`Failed to read windows-metadata-file "${fileRaw}".`, {
1556015562
cause: err
@@ -15597,6 +15599,9 @@ function parseUint16(raw, inputName) {
1559715599
return n;
1559815600
}
1559915601

15602+
// packages/core/src/windows-metadata-apply.ts
15603+
import { readFile as readFile2, writeFile as writeFile3 } from "node:fs/promises";
15604+
1560015605
// node_modules/pe-library/dist/format/FormatBase.js
1560115606
var FormatBase = (
1560215607
/** @class */
@@ -18968,13 +18973,9 @@ var SpcPeImageAttributeTypeAndOptionalValue = (
1896818973

1896918974
// packages/core/src/windows-metadata-apply.ts
1897018975
var RT_MANIFEST = 24, defaultDeps = {
18971-
readFile: async (p) => {
18972-
let { readFile: readFile2 } = await import("node:fs/promises");
18973-
return readFile2(p);
18974-
},
18976+
readFile: (p) => readFile2(p),
1897518977
writeFile: async (p, d) => {
18976-
let { writeFile: writeFile4 } = await import("node:fs/promises");
18977-
await writeFile4(p, d);
18978+
await writeFile3(p, d);
1897818979
}
1897918980
};
1898018981
function toArrayBuffer(u) {
@@ -19044,7 +19045,7 @@ async function writeManifest(res, meta, deps) {
1904419045
}
1904519046

1904619047
// packages/core/src/signing.ts
19047-
import { writeFile as writeFile3 } from "node:fs/promises";
19048+
import { writeFile as writeFile4 } from "node:fs/promises";
1904819049
import { join as join6 } from "node:path";
1904919050
import { randomBytes } from "node:crypto";
1905019051
function parseSigningInputs(opts = {}) {
@@ -19134,7 +19135,7 @@ async function runCheckedTool(deps, command, args, label, opts = {}) {
1913419135
}
1913519136
async function writeSecretBase64(deps, tempDir, base64, extension) {
1913619137
let path4 = join6(tempDir, `${randomBytes(8).toString("hex")}.${extension}`), bytes = Buffer.from(base64, "base64");
19137-
return await (deps.writeFile ?? ((p, d) => writeFile3(p, d, { mode: 384 })))(path4, bytes), path4;
19138+
return await (deps.writeFile ?? ((p, d) => writeFile4(p, d, { mode: 384 })))(path4, bytes), path4;
1913819139
}
1913919140
async function signMacos(binaryPath, cfg, deps) {
1914019141
let keychainPath = join6(
@@ -19299,14 +19300,14 @@ async function main() {
1929919300
if (cfg !== void 0) {
1930019301
let absCfg = pathResolve(workspace, cfg);
1930119302
if (pathBasename(absCfg).toLowerCase() === "package.json")
19302-
return dirname4(absCfg);
19303+
return dirname5(absCfg);
1930319304
}
1930419305
return workspace;
1930519306
})(), project = await readProjectInfo(projectDir);
1930619307
logger.info(`[pkg-action] project dir: ${projectDir}`), logger.info(`[pkg-action] project: ${project.name}@${project.version}`);
1930719308
let resolvedTargets = inputs.build.targets === "host" ? [hostTarget()] : [...inputs.build.targets];
1930819309
logger.info(`[pkg-action] targets: ${resolvedTargets.map(formatTarget).join(", ")}`);
19309-
let runnerTemp = process.env.RUNNER_TEMP ?? (await import("node:os")).tmpdir(), invocationDir = await createInvocationTemp(runnerTemp);
19310+
let runnerTemp = process.env.RUNNER_TEMP ?? tmpdir2(), invocationDir = await createInvocationTemp(runnerTemp);
1931019311
saveState("invocationDir", invocationDir);
1931119312
let pkgOutputDir = join7(invocationDir, "pkg-out");
1931219313
await mkdir3(pkgOutputDir, { recursive: !0 });

packages/build/src/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import * as core from '@actions/core';
2828
import { mkdir, rename, stat } from 'node:fs/promises';
29+
import { tmpdir } from 'node:os';
2930
import { basename as pathBasename, dirname, join, resolve as pathResolve } from 'node:path';
3031
import {
3132
actionsLogger,
@@ -144,7 +145,7 @@ async function main(): Promise<void> {
144145
logger.info(`[pkg-action] targets: ${resolvedTargets.map(formatTarget).join(', ')}`);
145146

146147
// 4. Invocation-scoped temp dir + output dir.
147-
const runnerTemp = process.env['RUNNER_TEMP'] ?? (await import('node:os')).tmpdir();
148+
const runnerTemp = process.env['RUNNER_TEMP'] ?? tmpdir();
148149
const invocationDir = await createInvocationTemp(runnerTemp);
149150
core.saveState('invocationDir', invocationDir);
150151
const pkgOutputDir = join(invocationDir, 'pkg-out');

packages/core/src/archive.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
// but the input is tiny enough that run-to-run differences are cosmetic.
1515

1616
import { createWriteStream } from 'node:fs';
17-
import { stat } from 'node:fs/promises';
18-
import { basename } from 'node:path';
17+
import { mkdtemp, rm, stat, symlink, utimes } from 'node:fs/promises';
18+
import { tmpdir } from 'node:os';
19+
import { basename, dirname } from 'node:path';
1920
import { pipeline } from 'node:stream/promises';
2021
import yazl from 'yazl';
2122
import type { ExecFn } from './pkg-runner.ts';
@@ -96,10 +97,6 @@ async function shellTar(
9697
// rename inside the archive only if caller asked for a different entry name.
9798
// For the common case (entry === basename(inputPath)) we just tar the file
9899
// as-is. For renames we stage a symlink with the desired name.
99-
const { dirname } = await import('node:path');
100-
const { mkdtemp, symlink, utimes, rm } = await import('node:fs/promises');
101-
const { tmpdir } = await import('node:os');
102-
103100
const compressFlag = compression === 'gz' ? '-z' : '-J';
104101
let stageDir: string | undefined;
105102
let workDir = dirname(inputPath);
@@ -179,10 +176,6 @@ async function shell7z(
179176
entry: string,
180177
deps: ArchiveDeps,
181178
): Promise<void> {
182-
const { dirname } = await import('node:path');
183-
const { mkdtemp, symlink, rm } = await import('node:fs/promises');
184-
const { tmpdir } = await import('node:os');
185-
186179
let stageDir: string | undefined;
187180
let workDir = dirname(inputPath);
188181
let fileName = basename(inputPath);

packages/core/src/windows-metadata-apply.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// own resedit integration emits, so re-running the sub-action is
1818
// idempotent.
1919

20+
import { readFile, writeFile } from 'node:fs/promises';
2021
import { Data, NtExecutable, NtExecutableResource, Resource } from 'resedit';
2122
import { ResEditError } from './errors.ts';
2223
import { padVersionQuad, type IconSpec, type WindowsMetadataInputs } from './windows-metadata.ts';
@@ -30,12 +31,8 @@ export interface WindowsMetadataApplyDeps {
3031
}
3132

3233
const defaultDeps: WindowsMetadataApplyDeps = {
33-
readFile: async (p) => {
34-
const { readFile } = await import('node:fs/promises');
35-
return readFile(p);
36-
},
34+
readFile: (p) => readFile(p),
3735
writeFile: async (p, d) => {
38-
const { writeFile } = await import('node:fs/promises');
3936
await writeFile(p, d);
4037
},
4138
};

packages/core/test/unit/archive.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { test } from 'node:test';
77
import { strictEqual, ok, rejects } from 'node:assert/strict';
8-
import { mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises';
8+
import { mkdtemp, readFile, rm, stat, utimes, writeFile } from 'node:fs/promises';
99
import { tmpdir } from 'node:os';
1010
import { join } from 'node:path';
1111
import { archive } from '../../src/archive.ts';
@@ -142,7 +142,6 @@ test('archive: tar normalizes the source mtime in addition to --mtime', async ()
142142
await withTempPair(async (inputPath, outputPath) => {
143143
// Pre-bump the input mtime to a recent timestamp; archive() must overwrite it.
144144
const bumped = new Date(Date.UTC(2025, 5, 15, 12, 0, 0));
145-
const { utimes } = await import('node:fs/promises');
146145
await utimes(inputPath, bumped, bumped);
147146

148147
const exec: ExecFn = async () => ({ exitCode: 0, stdout: '', stderr: '' });

packages/core/test/unit/checksum.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { test } from 'node:test';
22
import { strictEqual, ok, rejects } from 'node:assert/strict';
3+
import { createHash } from 'node:crypto';
34
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
45
import { tmpdir } from 'node:os';
56
import { join } from 'node:path';
@@ -80,7 +81,6 @@ test('computeChecksum streams multi-chunk input correctly', async () => {
8081
const digest = await computeChecksum(path, 'sha256');
8182
strictEqual(digest.length, 64);
8283
// Compute directly in-memory for cross-check.
83-
const { createHash } = await import('node:crypto');
8484
const expected = createHash('sha256').update(payload).digest('hex');
8585
strictEqual(digest, expected);
8686
});

packages/core/test/unit/fs-utils.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { test } from 'node:test';
22
import { strictEqual, ok } from 'node:assert/strict';
3-
import { mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises';
3+
import { mkdtemp, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
44
import { tmpdir } from 'node:os';
55
import { join } from 'node:path';
66
import {
@@ -47,7 +47,6 @@ test('atomicWriteFile leaves no .tmp- sibling on success', async () => {
4747
await withTempParent(async (parent) => {
4848
const target = join(parent, 'a.bin');
4949
await atomicWriteFile(target, new Uint8Array([1, 2, 3]));
50-
const { readdir } = await import('node:fs/promises');
5150
const entries = await readdir(parent);
5251
strictEqual(entries.filter((e) => e.includes('.tmp-')).length, 0);
5352
strictEqual(entries.length, 1);

packages/windows-metadata/dist/index.mjs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13759,13 +13759,13 @@ function normalizeFileIcons(file) {
1375913759
return [...out.values()].sort((a, b) => a.id - b.id);
1376013760
}
1376113761
async function parseWindowsMetadataInputs(opts = {}) {
13762-
let env = opts.env ?? process.env, readFile = opts.readFile ?? ((path) => import("node:fs/promises").then((m) => m.readFile(path, "utf8"))), prefix = opts.prefix ?? "windows-", read = (name) => readInputRaw(env, `${prefix}${name}`), fileRaw = read("metadata-file"), iconRaw = read("icon"), productName = read("product-name"), productVersion = read("product-version"), fileVersion = read("file-version"), fileDescription = read("file-description"), companyName = read("company-name"), legalCopyright = read("legal-copyright"), originalFilename = read("original-filename"), internalName = read("internal-name"), comments = read("comments"), manifestPath = read("manifest"), langRaw = read("lang"), codepageRaw = read("codepage");
13762+
let env = opts.env ?? process.env, readFile2 = opts.readFile ?? ((path) => import("node:fs/promises").then((m) => m.readFile(path, "utf8"))), prefix = opts.prefix ?? "windows-", read = (name) => readInputRaw(env, `${prefix}${name}`), fileRaw = read("metadata-file"), iconRaw = read("icon"), productName = read("product-name"), productVersion = read("product-version"), fileVersion = read("file-version"), fileDescription = read("file-description"), companyName = read("company-name"), legalCopyright = read("legal-copyright"), originalFilename = read("original-filename"), internalName = read("internal-name"), comments = read("comments"), manifestPath = read("manifest"), langRaw = read("lang"), codepageRaw = read("codepage");
1376313763
if (!(fileRaw !== void 0 || iconRaw !== void 0 || productName !== void 0 || productVersion !== void 0 || fileVersion !== void 0 || fileDescription !== void 0 || companyName !== void 0 || legalCopyright !== void 0 || originalFilename !== void 0 || internalName !== void 0 || comments !== void 0 || manifestPath !== void 0)) return null;
1376413764
let fileData;
1376513765
if (fileRaw !== void 0) {
1376613766
let contents;
1376713767
try {
13768-
contents = await readFile(fileRaw);
13768+
contents = await readFile2(fileRaw);
1376913769
} catch (err) {
1377013770
throw new ValidationError(`Failed to read windows-metadata-file "${fileRaw}".`, {
1377113771
cause: err
@@ -13808,6 +13808,9 @@ function parseUint16(raw, inputName) {
1380813808
return n;
1380913809
}
1381013810

13811+
// packages/core/src/windows-metadata-apply.ts
13812+
import { readFile, writeFile as writeFile2 } from "node:fs/promises";
13813+
1381113814
// node_modules/pe-library/dist/format/FormatBase.js
1381213815
var FormatBase = (
1381313816
/** @class */
@@ -17179,12 +17182,8 @@ var SpcPeImageAttributeTypeAndOptionalValue = (
1717917182

1718017183
// packages/core/src/windows-metadata-apply.ts
1718117184
var RT_MANIFEST = 24, defaultDeps = {
17182-
readFile: async (p) => {
17183-
let { readFile } = await import("node:fs/promises");
17184-
return readFile(p);
17185-
},
17185+
readFile: (p) => readFile(p),
1718617186
writeFile: async (p, d) => {
17187-
let { writeFile: writeFile2 } = await import("node:fs/promises");
1718817187
await writeFile2(p, d);
1718917188
}
1719017189
};

0 commit comments

Comments
 (0)