Skip to content

fix(release): isolate per-package tarball in shared distDir (v1.9.1)#45

Merged
danielmeppiel merged 1 commit into
mainfrom
fix/pack-json-v1.9.1
May 19, 2026
Merged

fix(release): isolate per-package tarball in shared distDir (v1.9.1)#45
danielmeppiel merged 1 commit into
mainfrom
fix/pack-json-v1.9.1

Conversation

@danielmeppiel

Copy link
Copy Markdown
Collaborator

TL;DR

In monorepo releases, every per-package apm pack after the first emitted a spurious produced N tarballs; expected 1 warning. The grace-window heuristic mistook prior packages' tarballs in the shared dist/ directory as freshly produced. Snapshot before/after the pack call and accept only files this invocation actually touched.

Problem (WHY)

packPackage() selected the produced tarball by mtime: any file in distDir with mtime >= packStart - 1s was "fresh by this invocation." In a monorepo loop, sequential per-package packs complete in well under a second, so plugin N saw plugin 1..N-1's tarballs inside the grace window. Each pack after the first warned produced N tarballs; expected 1.

Empirically reproduced on DevExpGbb/zava-agent-config@v6.1.1 (run 26079513903), which packs 7 plugins into one dist/ directory and emitted 6 spurious warnings per release.

Approach (WHAT)

Snapshot the set of tarballs in distDir and their mtimes before invoking apm pack. After the pack returns, "produced by this call" = new in after OR existed in before and mtime advanced. The warning now fires only on a genuine producer-side anomaly (one pack invocation touching multiple tarballs); the test suite's existing overwrite-regression case still passes.

Implementation (HOW)

  • src/release.ts packPackage() rewritten to use the before/after diff (~25 LOC delta).
  • listTarballs retained: it is still needed to enumerate the snapshot and to format error messages.
  • New regression test returns only the tarball produced by this invocation in a shared distDir (monorepo regression): pre-seeds distDir with sibling-A and sibling-B tarballs, then asserts the returned path is only the freshly-produced one and the warning does not trigger.

Validation evidence

  • npm run lint: clean
  • npm test: 182 passed (5 suites), including the new regression
  • npm run build: dist/ regenerated via ncc 0.38.4

Release

  • package.json bumped 1.9.0 → 1.9.1
  • CHANGELOG.md entry under [1.9.1]
  • Tag v1.9.1 after merge; v1 floating tag and GitHub release are handled automatically by .github/workflows/ci.yml's release job on tag push.

How to test

git clone git@github.com:microsoft/apm-action.git && cd apm-action
git fetch origin fix/pack-json-v1.9.1 && git checkout fix/pack-json-v1.9.1
npm ci && npm test -- --testPathPattern=release

The monorepo regression case (returns only the tarball produced by this invocation in a shared distDir) is the new assertion.

The mtime grace-window heuristic in packPackage() classified prior
packages' tarballs as 'fresh by this invocation' in monorepo runs,
emitting one spurious 'produced N tarballs; expected 1' warning per
package after the first. Snapshot the directory before the pack call
and accept only files that are new in 'after' or whose mtime advanced.

Empirically reproduced on DevExpGbb/zava-agent-config@v6.1.1
(run 26079513903), which packs 7 plugins into one dist/ directory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 19, 2026 06:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes packPackage() tarball selection during monorepo releases where multiple sequential apm pack invocations share a single dist/ directory, preventing spurious “produced N tarballs; expected 1” warnings caused by an mtime grace-window heuristic.

Changes:

  • Update packPackage() to snapshot tarballs/mtimes before and after apm pack, and select only tarballs created/modified by the current invocation.
  • Add a regression test covering shared distDir monorepo behavior.
  • Bump release metadata (version + changelog) and regenerate dist/ outputs.
Show a summary per file
File Description
src/release.ts Switch tarball detection from time-window heuristic to before/after snapshot diff to isolate the tarball produced by the current pack call.
src/tests/release.test.ts Add monorepo regression test for shared distDir tarball isolation.
package.json Bump package version to 1.9.1.
package-lock.json Update lockfile version fields to 1.9.1.
dist/release.d.ts Regenerate typings reflecting updated packPackage() docs/behavior.
dist/index.js Regenerate bundled JS reflecting updated packPackage() implementation.
CHANGELOG.md Add 1.9.1 entry and update compare links for the release.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/7 changed files
  • Comments generated: 2

Comment thread src/release.ts
Comment on lines 341 to +346
core.warning(
`apm pack in ${dir} produced ${fresh.length} tarballs; expected 1. `
+ `Using the most recently modified: ${fresh[0]}`,
`apm pack in ${dir} produced ${touched.length} tarballs; expected 1. `
+ `Using the most recently modified: ${touched.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs)[0]}`,
);
}
return fresh[0];
return touched.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs)[0];
Comment on lines +341 to +346
const result = await packPackage(tmpDir, distDir);
expect(result).toBe(newTarball);
// Sibling files must still exist on disk (we did not delete them).
expect(fs.existsSync(priorA)).toBe(true);
expect(fs.existsSync(priorB)).toBe(true);
});
@danielmeppiel danielmeppiel merged commit e5650fb into main May 19, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants