Skip to content

fix: correct Copilot CLI config surface and default to stable channel - #77

Merged
austenstone merged 3 commits into
mainfrom
austenstone-action-tune-up
Aug 20, 2026
Merged

fix: correct Copilot CLI config surface and default to stable channel#77
austenstone merged 3 commits into
mainfrom
austenstone-action-tune-up

Conversation

@austenstone

@austenstone austenstone commented Aug 20, 2026

Copy link
Copy Markdown
Owner

What

Fixes three correctness problems in how the action talks to the Copilot CLI, plus a deprecated runtime.

1. Writing user settings to the wrong file (config.jsonsettings.json)

The action wrote copilot-config to ~/.copilot/config.json and overwrote it. The CLI self-documents that file:

// User settings belong in settings.json.
// This file is managed automatically.

config.json holds CLI-managed state — loggedInUsers, installedPlugins, firstLaunchAt. On an ephemeral GitHub-hosted runner that's harmless, but on a persistent or self-hosted runner it destroys the CLI's auth state. Per the config dir reference, user settings were moved to settings.json and legacy config.json values are only auto-migrated on startup.

Now writes settings.json and merges rather than clobbers, so pre-existing runner settings survive.

2. Two invalid values in the default copilot-config

Key Problem
"theme": "auto" auto is not in the theme enum (default, github, dim, high-contrast, colorblind)
"trustedFolders": [] Real key, but it lives in CLI-managed config.json, not settings.json — so it was silently ignored there. Directory trust is handled by --add-dir, which the action already passes.

Docs state invalid values are ignored and surfaced as config problems. Both removed; banner and renderMarkdown are verified-valid and stay.

3. copilot-version defaulted to prerelease

Every consumer of this action was installing bleeding-edge CLI builds (currently 1.0.81-5) instead of stable (1.0.80). One bad prerelease broke every downstream repo.

Default is now latest. Drift detection is not lost — a dedicated prerelease-drift job in the nightly matrix pins copilot-version: prerelease, so a breaking CLI release still gets caught here first, before it reaches consumers.

4. actions/upload-artifact@v4v7

v4 targets Node 20. Every run currently logs:

Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/upload-artifact@v4

Reviewed v5/v6/v7 release notes — no breaking change for this usage (archive defaults to the old zip behavior; multi-path + if-no-files-found unchanged). v6+ needs runner ≥ 2.327.1; hosted runners are on 2.336.0. Supersedes #66.

Testing

  • config test job rewritten: it previously passed render_markdown, theme: "dark", and trusted_folders — all invalid keys/values that asserted nothing. It now seeds a pre-existing setting, then asserts the action's config was merged in and the pre-existing key survived.
  • Merge logic verified locally against both the empty and pre-populated cases.
  • bash -n + shellcheck clean on the embedded script; YAML parses.

Verified against Copilot CLI 1.0.80 and the live docs. Separately confirmed all 44 flags the action passes still exist in the current CLI — no flag drift.


Follow-up: version spec input + the settings.json cutover

Two more fixes landed on this branch after review.

copilot-version now takes a version spec

It defaulted to latest, so every CLI release shipped straight into everyone's
workflows unreviewed. It now defaults to a pinned 1.0.80 and accepts any npm
spec — 1.0.80, 1.x, >=1.0.80, latest, prerelease — matching the
node-version convention from actions/setup-node.

This also fixed a latent bug: the install ran npm install -g @github/copilot@$COPILOT_VERSION
unquoted, so a range like >=1.0.80 was parsed as shell redirection and
created a file named =1.0.80 instead of installing anything. The version-spec
job is the regression test.

version-pin-drift fails only on the nightly schedule when the pinned
default falls behind latest, so PRs aren't blocked every time the CLI ships
but the pin can't silently rot either.

copilot-config was silently dropped on older CLIs

User settings moved out of config.json into settings.json in CLI 1.0.35
(2026-04-23). Writing to settings.json unconditionally meant anyone pinning
below that got their copilot-config silently ignored. The action now
resolves the installed version and writes to whichever file that CLI actually
reads, warning when it takes the legacy path.

Newer config.json files also open with // comments, which jq cannot parse,
so the legacy path strips them before merging. Invalid copilot-config JSON now
fails fast instead of no-opping.

New jobs: config-legacy (pins 1.0.34, asserts config.json) and
config-invalid (asserts the action rejects malformed JSON).

The action wrote user settings to ~/.copilot/config.json, which the CLI
documents as managed state (loggedInUsers, installedPlugins). Clobbering it
destroys auth state on persistent/self-hosted runners. User-editable settings
belong in settings.json, so write there and merge instead of overwrite.

The default copilot-config also carried two values the current CLI schema
rejects: "theme": "auto" is not in the theme enum, and trustedFolders is not a
recognized key (directory trust is handled by --add-dir, which the action
already passes).

Defaulting copilot-version to `prerelease` shipped bleeding-edge CLI builds to
every consumer. Default to `latest` and keep drift detection via a dedicated
nightly prerelease-drift job.

Also bumps actions/upload-artifact v4 -> v7; v4 targets Node 20, which is
deprecated and already force-migrated to Node 24 by the runner.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
austenstone and others added 2 commits August 20, 2026 09:53
npm already resolves ranges, dist-tags, and exact versions from a single
spec, so the latest/prerelease special cases were redundant. The spec is now
quoted because ranges like '>=1.0.80' were being parsed as shell redirection.

Default is pinned to a known-good stable version rather than floating, so a
given action ref installs the same CLI every run. version-pin-drift keeps the
pin honest by failing the nightly build (not PRs) once it falls behind latest.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
User settings moved out of config.json into settings.json in CLI 1.0.35
(2026-04-23). Pins below that never read settings.json, so writing there
silently dropped copilot-config. Detect the resolved version and write to
whichever file the CLI actually reads, stripping the // comments newer
config.json files carry so jq can merge them. Invalid JSON now fails fast
instead of no-opping.
@austenstone
austenstone merged commit d19a807 into main Aug 20, 2026
34 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.

1 participant