Skip to content

Andrewpai/application create - #57

Open
andrewpai wants to merge 37 commits into
nextfrom
andrewpai/application-create
Open

andrewpai wants to merge 37 commits into
nextfrom
andrewpai/application-create

Conversation

@andrewpai

Copy link
Copy Markdown
Contributor

New application:create command to create an application in one of a few standard forms. Also supports --data for passing a JSON application definition to the API for full custom control.

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.

Copilot review overview

🟡 Changes recommended

Global CORS mutation lacks required confirmation, and several command correctness issues remain.

Review effort: Balanced
Findings: 5 Medium severity · 4 Low severity

Open (9)
What changed in this PR

Adds application:create with standard security profiles and custom JSON configuration, alongside CLI safety, automation, documentation, and test improvements.

Changes:

  • Adds application creation with profile defaults, CORS configuration, and custom JSON support.
  • Improves kickstart confirmation, unattended installation, and option naming.
  • Expands unit/integration coverage and supporting documentation.
File Description
src/​utils.ts Adds reusable confirmation handling.
src/​index.ts Formatting-only change.
src/​commands/​kickstart-kill.ts Adds --yes confirmation flow.
src/​commands/​kickstart-install.ts Adds unattended installation options and validation.
src/​commands/​index.ts Exports the new command.
src/​commands/​import-generate.ts Adds kebab-case options and deprecated aliases.
src/​commands/​application-create.ts Implements application creation.
package.json Updates version and test scripts.
package-lock.json Synchronizes package version.
CONTRIBUTING.md Documents contribution and testing policies.
AGENTS.md Expands CLI and safety guidance.
__tests__/​utils.test.js Tests confirmation utilities.
__tests__/​telemetry/​telemetry.test.js Mocks telemetry requests.
__tests__/​integration/​setup.js Extends integration infrastructure.
__tests__/​integration/​application-create/​application-create.integration.test.js Tests application creation against FusionAuth.
__tests__/​commands/​kickstart-kill.test.js Tests destructive-operation gating.
__tests__/​commands/​kickstart-install.test.js Tests installation options and validation.
__tests__/​commands/​import-generate.test.js Tests renamed and deprecated options.
__tests__/​commands/​application-create.test.js Tests application profiles, data, CORS, and output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread __tests__/integration/setup.js Outdated
Comment thread src/commands/application-create.ts
Comment thread src/commands/application-create.ts Outdated
Comment thread src/commands/application-create.ts
Comment thread src/commands/kickstart-install.ts Outdated
Comment thread src/commands/application-create.ts Outdated
Comment thread src/commands/import-generate.ts Outdated
Comment thread src/commands/kickstart-install.ts Outdated
Comment thread src/commands/kickstart-install.ts Outdated
Copilot AI balanced review requested due to automatic review settings September 30, 2026 17:37

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.

Comment thread src/commands/application-create.ts
Copilot AI balanced review requested due to automatic review settings September 30, 2026 17:42

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.

Copilot review overview

🔵 Needs a closer look

Global CORS changes lack required confirmation, while tenant targeting, origin configuration, validation, and macOS readiness contain functional defects.

Review effort: Balanced
Findings: 1 High severity · 5 Medium severity · 1 Low severity

Open (7)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Apply authorized origins to system CORS configuration

src/​commands/​application-create.ts:238

--authorized-origin-url is advertised as CORS configuration, but this only writes the application's OAuth authorizedOriginURLs. ensureCorsHeaders() updates global allowedHeaders and enabled, never corsConfiguration.allowedOrigins, so browser requests from a newly supplied origin remain blocked unless it was already configured separately. Merge these origins into system CORS (with deduplication) or change the option's contract.

Medium severity Honor tenant ID supplied in application data

src/​commands/​application-create.ts:254

Honor a tenant supplied inside --data. The help says --tenant-id overrides --data, but the client receives only the flag value; without the flag, no tenant header is sent and multi-tenant FusionAuth instances may reject the request or target the API key's default tenant even when application.tenantId is present.

Copilot AI balanced review requested due to automatic review settings September 30, 2026 19:21

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.

Copilot review overview

🔵 Needs a closer look

Global CORS changes lack required confirmation, and several command and integration behaviors can produce incorrect results.

Review effort: Balanced
Findings: 1 High severity · 4 Medium severity

Open (5)
Resolved since last review (2)

Copilot AI balanced review requested due to automatic review settings September 30, 2026 19:55

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.

Copilot review overview

🟡 Changes recommended

Invalid custom payloads, tenant scoping, misleading errors, and an unstopped failure-path spinner need correction.

Review effort: Balanced
Findings: 2 High severity · 1 Medium severity

Open (3)
Resolved since last review (5)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Validate parsed JSON is a non-null object

src/​commands/​application-create.ts:199

JSON.parse may return null, an array, or a scalar, but the cast accepts all of them as Application. For example, --data null then crashes at application.id, while arrays/scalars can be sent as malformed API payloads. Validate that the parsed value is a non-null, non-array object and return a clear input error before applying overrides.

Comment thread src/commands/application-create.ts
Comment thread src/commands/kickstart-install.ts
Comment thread src/commands/application-create.ts Outdated
mark-robustelli and others added 15 commits September 30, 2026 15:24
- import-generate: detect deprecated flags in --flag=value form, not just bare --flag
- kickstart-install: replace setTimeout-chained install steps with sequential
  awaited steps so errors propagate through try/catch and ordering is
  deterministic; also await createKickstart (was previously fire-and-forget)
- utils: confirmOrExit now requires both stdin and stdout to be TTYs before
  treating the session as interactive, and normalizes confirmation input
  (trims whitespace, accepts y/yes case-insensitively)
- utils.ts: extract isConfirmationAccepted() as a pure, exported function so
  the accept/reject decision logic can be unit tested directly without
  simulating a real TTY
- kickstart-kill.ts: export action() and add an injectable deps parameter
  (isDockerInstalled, confirmOrExit, spawn) so tests can exercise the
  confirmation gating without touching real docker or exiting the process
- add __tests__/utils.test.js covering isConfirmationAccepted and the
  yes-bypass / non-interactive TTY-detection paths of confirmOrExit
- add __tests__/commands/kickstart-kill.test.js covering docker-not-installed,
  CLI_DIR mismatch, --yes bypass, and confirm-rejected gating paths
- wire both new test files into the test and test:unit npm scripts
- extract getDeprecatedFlagUsage(argv) as a pure, exported function so the
  deprecation-detection logic is testable without mocking process.argv or
  console.warn
- export DEPRECATED_FLAGS for use in tests
- add __tests__/commands/import-generate.test.js covering: no deprecated
  flags used, bare --flag and --flag=value forms detected, multiple
  deprecated flags detected together, new kebab-case form not flagged,
  and that both the deprecated and current flag spellings populate the
  same underlying Commander option property
- wire the new test file into the test and test:unit npm scripts
…matical agreement'

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…xecuteApplicationCreate'

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Fix inverted localhost/container-IP fallback order in integration
  test setup's auth-readiness check
- Gate CORS system-configuration mutation behind --yes/confirmOrExit
  per the Risky Operations Policy
- Make --name optional; required only for --profile, preserved from
  --data JSON unless explicitly overridden
- Document that applicationId/clientId are intentionally identical
  (FusionAuth never accepts clientId as input)
- Remove NODE_ENV-conditional exit from executeApplicationCreate so
  it always returns a result per its documented contract; thread the
  raw error through to the CLI wrapper for field-level error detail

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.

Copilot review overview

🔵 Needs a closer look

Integration setup relies on a hard-coded container name and unsafe path handling that break supported development environments.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Resolve the service container ID via Compose instead of hard-coding its name

__tests__/​integration/​setup.js:24

This assumes Compose's default project name. If COMPOSE_PROJECT_NAME is set, the container has a different generated name, both docker inspect calls are silently ignored, and the bridge-IP fallback this change adds cannot work. Resolve the service container ID with docker compose --env-file .env.test ps -q fusionauth instead of hard-coding the generated name.

Medium severity Use fileURLToPath and cwd to support checkout paths containing spaces

__tests__/​integration/​setup.js:25

URL.pathname leaves characters such as spaces percent-encoded, while the compose commands also interpolate this path into an unquoted cd. A checkout under a path containing spaces therefore fails either at writeFileSync(envFile, ...) or in the shell. Convert with fileURLToPath() and pass cwd: COMPOSE_DIR to execAsync rather than building cd command strings.

Copilot AI balanced review requested due to automatic review settings October 1, 2026 23:04

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.

Copilot review overview

🟡 Changes recommended

Custom JSON input needs runtime object validation, and two added comments contradict current execution behavior.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Validate parsed --data input is a non-null object

src/​commands/​application-create.ts:251

JSON.parse can return null, arrays, or primitives, but this unchecked cast lets them through as applications. null then fails at application.id, while other values can produce a non-object API payload, so syntactically valid --data input gets misleading runtime/API errors. Validate that the parsed value is a non-null, non-array object before casting it.

Low severity Correct comment about confirmOrExit behavior

__tests__/​commands/​application-create.test.js:756

This states the opposite of the documented behavior in src/commands/application-create.ts:260-267: production calls may exit through confirmOrExit; only this test's mocked process.exit turns that path into a returned result. Update the comment so it does not reintroduce the contract that was intentionally removed.

Comment thread src/commands/kickstart-install.ts Outdated
JSON.parse can return null, arrays, or primitives, but parseData() cast
the result straight to Application unchecked. Traced the actual failure
modes: --data 'null' crashed downstream with an opaque
"Cannot read properties of null (reading 'id')" TypeError; arrays and
primitives silently passed through property assignments and produced
nonsensical API payloads sent to FusionAuth, surfacing as confusing
server-side errors instead of a clear client-side validation message.

Added a shape check right after JSON.parse, throwing a clear Error
consistent with parseData()'s other validation errors. Added three
unit tests covering null/array/primitive --data input.

Also fixed two stale comments:
- A test comment claiming confirmOrExit() "never exits the process
  itself" — this directly contradicted the JSDoc on
  executeApplicationCreate (and the earlier fix in 7bb5071): production
  calls CAN still exit via confirmOrExit(); only this specific test's
  mocked process.exit turns that into a returned result.
- The resolveResourcesDir() JSDoc (from 52ae42e) describing its src/
  layout fallback as "npm start running this file via tsx", which my
  very next commit (bd81c93, restoring the build-first start script)
  made inaccurate. Reworded to describe direct source execution
  generically, independent of npm start.
Copilot AI balanced review requested due to automatic review settings October 1, 2026 23:54
@andrewpai

Copy link
Copy Markdown
Contributor Author

Re: "Validate parsed --data input is a non-null object" (application-create.ts:251, previously-missed finding, no dedicated inline thread).

Confirmed by tracing the actual failure modes: --data 'null' crashed downstream with an opaque Cannot read properties of null (reading 'id') TypeError; arrays and primitives silently passed through property assignments and produced nonsensical API payloads sent to FusionAuth, surfacing as confusing server-side errors instead of a clear client-side validation message.

Fixed in a648f1c: added a shape check right after JSON.parse in parseData(), throwing a clear error consistent with its other validation errors. Added 3 unit tests (null/array/primitive) and verified the full suite still passes.

@andrewpai

Copy link
Copy Markdown
Contributor Author

Re: "Correct comment about confirmOrExit behavior" (__tests__/commands/application-create.test.js:756, previously-missed finding, no dedicated inline thread).

Agreed — this comment said the opposite of the documented contract. Fixed in a648f1c: reworded to accurately state that production calls can still exit via confirmOrExit() for a non-interactive caller without yes=true; this test only gets a returned result because process.exit is mocked.

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.

Copilot review overview

🔵 Needs a closer look

The new option help incorrectly promises CORS configuration in modes where only the application-level allowlist is updated.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Clarify CORS option scope across profiles

src/​commands/​application-create.ts:470

This help text promises CORS behavior in every mode, but system CORS is changed only for --profile spa; in --data, native, and webapp modes this option only sets application.oauthConfiguration.authorizedOriginURLs (which the tests identify as a separate hosted-page allowlist). Clarify the scope so users do not assume this flag configured cross-origin API access when it did not.

The old text ('for CORS') implied this flag configures cross-origin
API access in every mode, but system CORS is only touched for
--profile spa. In --data, native, and webapp modes it only sets
application.oauthConfiguration.authorizedOriginURLs, a separate
application-level allowlist. Reworded to make the scope explicit.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 02:19
@andrewpai

Copy link
Copy Markdown
Contributor Author

Re: "Clarify CORS option scope across profiles" (application-create.ts:470, previously-missed finding, no dedicated inline thread).

Agreed — verified the actual scope across all modes: --profile spa sets application.oauthConfiguration.authorizedOriginURLs and adds the origin to the system CORS allowlist; --profile native, --profile webapp, and --data mode only set the application-level field, never touching system CORS.

Fixed in 2e4ae58: reworded the --help text to 'Authorized origin URLs for the application; also added to the system CORS allowlist for --profile spa'.

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.

Copilot review overview

🟡 Changes recommended

SPA CORS setup omits Content-Type, and direct errors are printed twice.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Avoid duplicate reporting of direct parseData errors

src/​commands/​application-create.ts:417

Direct Errors from parseData (malformed JSON, unreadable @file, invalid shape) are stored as both error and rawError. The action then passes both to errorAndExit, and reportError prints the same message once as msg and again as error.message. Preserve rawError only when unwrapping produced distinct structured detail (or the rejection was not already an Error).

Comment thread src/commands/application-create.ts Outdated
Content-Type is only CORS-safelisted for application/x-www-form-urlencoded,
multipart/form-data, or text/plain -- not application/json. A SPA sending
JSON would still fail preflight after this command reported CORS as
"configured", since Content-Type wasn't in the guaranteed header set.
Added it to REQUIRED_CORS_HEADERS and updated the comments that
described these as "DPoP-related" headers (Content-Type is about JSON
bodies not being safelisted, not DPoP specifically). Updated test
fixtures that previously hardcoded the old 3-header "fully compliant"
set, and the integration test's local REQUIRED_CORS_HEADERS constant,
so they continue to validate the correct full set. Verified via a full
local docker-based integration run.

Also fixed unwrapError() printing the same error message twice.
Direct, never-wrapped Errors (e.g. parseData()'s validation errors)
have no distinct .cause, so unwrapError() fell back to returning the
same Error object as rawError -- which errorAndExit()/reportError()
then printed a second time via its generic 'message' in error branch.
Reproduced this empirically before and after the fix. unwrapError()
now returns undefined in that case, while still preserving a
genuinely-wrapped error's distinct cause, or a rejection that was
never an Error at all (e.g. a raw ClientResponse-shaped object).
Added a regression test asserting rawError is undefined for a direct
validation error.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 13:51
@andrewpai

Copy link
Copy Markdown
Contributor Author

Re: "Avoid duplicate reporting of direct parseData errors" (application-create.ts:417, previously-missed finding, no dedicated inline thread).

Confirmed empirically — reproduced the exact duplicate output described: reportError() printed the same message once directly and once via its generic 'message' in error branch, since unwrapError() fell back to returning the same (never-wrapped) Error object as rawError.

Fixed in ef9c0fa per the suggested approach: unwrapError() now returns undefined for a direct, never-wrapped Error (nothing extra to report beyond the message), while still preserving a genuinely-wrapped error's distinct .cause, or a rejection that was never an Error at all. Added a regression test asserting rawError is undefined for a direct validation error, and re-verified the duplicate output is gone.

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.

Copilot review overview

🔵 Needs a closer look

The kickstart resource test claims both layouts are covered but never exercises the built distribution branch.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Test the dist resources path in addition to the source fallback

__tests__/​commands/​kickstart-install.test.js:354

This test only exercises the source fallback: it imports src/commands/kickstart-install.js through tsx, so __dirname is always src/commands, even when CI built dist first. The new dist/commands/resources branch is therefore untested despite this comment claiming both layouts are covered. Please test the resolver with controllable base directories (or import the built module in a dedicated build test) so both branches are exercised.

The existing test imported src/commands/kickstart-install.js via tsx,
so __dirname was always .../src/commands for the whole test run --
meaning the dist-layout branch (and the error-throw path) had zero
coverage, despite the test's comment claiming both layouts were
covered.

Added a baseDir parameter to resolveResourcesDir() (defaulting to the
real __dirname, so production behavior is unchanged) so tests can
exercise all three outcomes -- dist found, src fallback found, neither
found -- against controlled, synthetic temp directories instead of
depending on the real repo's build state.

Also added a separate test that imports the actual compiled
dist/commands/kickstart-install.js and verifies resolveResourcesDir()
resolves correctly against the real build output, confirming the
copy-files build step actually produces a working dist/commands/resources
directory. Skips gracefully (not fails) when dist/ hasn't been built
yet, so test:unit still works without requiring a build first --
meaningful in CI, which always builds before testing.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 15:03
@andrewpai

Copy link
Copy Markdown
Contributor Author

Re: "Test the dist resources path in addition to the source fallback" (kickstart-install.test.js:354, previously-missed finding, no dedicated inline thread).

Confirmed — this test always imports src/commands/kickstart-install.js via tsx, so __dirname was fixed to .../src/commands for the whole run. I verified directly that calling the function from that import only ever exercised the src-fallback branch; the dist-layout branch (and the error-throw path) had zero coverage despite the comment's claim.

Fixed in 1bd1254: added an injectable baseDir parameter to resolveResourcesDir() (defaulting to the real __dirname, so production behavior is unchanged), and replaced the old test with 4 synthetic temp-directory tests covering all three logic branches (dist found / src fallback found / neither found, including the previously-untested throw path). Also added a separate test that imports the real compiled dist/commands/kickstart-install.js directly and verifies it resolves correctly against the actual build output — this one skips gracefully (not fails) if dist/ hasn't been built yet, so test:unit still works without requiring a build first, while still being meaningful in CI (which always builds before testing).

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.

Copilot review overview

🔵 Needs a closer look

The bridge-IP fallback depends on a generated Docker container name that is not stable across Compose project configurations.

Review effort: Balanced
Findings: None

Previously missed (1)

In code that hasn't changed since last review

Medium severity Resolve FusionAuth container ID via Compose instead of generated name

__tests__/​integration/​setup.js:24

This fallback relies on Docker Compose's generated container name, but the compose file does not declare container_name; the name changes when the project name is overridden (for example with COMPOSE_PROJECT_NAME). In that case both docker inspect calls silently fail and URL resolution falls back to localhost, defeating the new bridge-IP fallback. Resolve the fusionauth service container ID via docker compose ps -q fusionauth and inspect that ID in both lookup paths instead of hard-coding the generated name.

Two previously-missed findings from the same review, neither acted on
across two review cycles -- not a deliberate decision, just missed.

CONTAINER_NAME hard-coded Docker Compose's default generated container
name ('{project}-{service}-{index}'). If COMPOSE_PROJECT_NAME is set,
the real container name differs, both docker inspect calls silently
fail (caught by empty catch blocks), and the bridge-IP fallback this
PR added is defeated without any visible error. Replaced with
resolveContainerId(), which resolves the real ID via
`docker compose ps -q fusionauth`, independent of naming conventions.
Verified end-to-end via a full local docker-based integration run --
the bridge-IP fallback message still appears correctly, confirming
the dynamic resolution works.

COMPOSE_DIR used new URL(...).pathname, which leaves special characters
like spaces percent-encoded (e.g. '%20') rather than decoding them --
not a valid filesystem path component. Verified empirically that
fileURLToPath() correctly decodes it instead. Also replaced the
`cd ${COMPOSE_DIR} && ...` string-concatenation pattern (5 call sites)
with execAsync(cmd, { cwd: COMPOSE_DIR }), avoiding shell-quoting
issues with the path entirely rather than just moving them around.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 15:55
@andrewpai

Copy link
Copy Markdown
Contributor Author

Re: "Resolve FusionAuth container ID via Compose instead of generated name" (setup.js:24, previously-missed finding, now recurring across two review cycles).

For transparency: this one was not a deliberate decision to skip — it was simply missed. It only ever surfaced as a summary-only "previously missed" bullet with no dedicated inline thread to reply to directly, and it slipped through across both rounds.

Confirmed the issue is real: CONTAINER_NAME hard-coded Compose's default generated name; if COMPOSE_PROJECT_NAME is set, the real name differs and both docker inspect calls silently fail, defeating the bridge-IP fallback with no visible error.

Fixed in da3659d: added resolveContainerId(), which resolves the real container ID via docker compose ps -q fusionauth instead of guessing the name. Verified end-to-end via a full local docker-based integration run — the bridge-IP fallback still engages correctly.

While investigating, I also found a second, closely related finding from the same review that was equally unaddressed ("Use fileURLToPath and cwd to support checkout paths containing spaces", setup.js:25) and fixed that in the same commit: COMPOSE_DIR now uses fileURLToPath() instead of .pathname (verified empirically that .pathname left spaces percent-encoded rather than decoding them), and all 5 cd ${COMPOSE_DIR} && ... call sites now use execAsync(cmd, { cwd: COMPOSE_DIR }) instead, avoiding shell-quoting issues with the path entirely.

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.

Copilot review overview

🔵 Needs a closer look

Duplicate supplied origins can pollute global CORS configuration, and new resource tests leak temporary directories.

Review effort: Balanced
Findings: None

Previously missed (2)

In code that hasn't changed since last review

Medium severity Deduplicate authorized origins before updating CORS configuration

src/​commands/​application-create.ts:195

When --authorized-origin-url contains the same origin more than once, each copy passes this filter because it is compared only with the pre-existing allowlist. The patch then writes duplicate entries into the system-wide CORS configuration. Deduplicate the supplied origins before computing the additions.

Low severity Clean up temporary directories created by tests

__tests__/​commands/​kickstart-install.test.js:363

Each test in this block creates a directory under the system temp directory, but none of those directories are removed. Repeated local and CI runs therefore leave four directory trees behind per run; track them and clean them after each test.

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.

3 participants