Skip to content

v0.0.1 candidate - #16

Open
ndenny wants to merge 91 commits into
mainfrom
develop
Open

ndenny wants to merge 91 commits into
mainfrom
develop

Conversation

@ndenny

@ndenny ndenny commented Jul 7, 2026

Copy link
Copy Markdown
Member

No description provided.

Gary-Darnell and others added 30 commits May 28, 2026 12:48
…claude trying basic cli commands instead of the skills
- Remove redundant tests
- Update commands test so we don't trigger ensureProject
…ting

Ds 5672 set up ci build and testing
…robust base64 decode, fail on tag publish without signing secret, safer goreleaser install\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…goreleaser

- upload darwin artifacts from Linux release job
- download/sign/rechecksum darwin archives on macOS
- replace mac assets on the GitHub release

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- remove broken mac_only path gating
- fail fast on all required signing secrets for tags
- validate related signing secrets before import
- use printf for base64 decoding inputs
- pass keychain explicitly to codesign

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- use boolean inputs context for snapshot conditions
- create tag releases as drafts before macOS signing
- finalize release after signed macOS assets are uploaded

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… prov profile

- Add xcrun notarytool step (sign + notarize per binary via zip submission)
- Add APPLE_ID/APPLE_ID_PASSWORD/APPLE_TEAM_ID to preflight secrets check
- Guard workflow_dispatch against non-tag + non-snapshot to prevent broken releases
- Replace secrets.X != '' step conditions with a secrets_check step output
- Remove checkout/setup-go/test from macOS job (pure signing job, no build needed)
- Remove APPLE_PROV_PROFILE handling (not needed for CLI tool signing)
- Simplify base64 decode to base64 -D (always macOS runner)
- Add security set-keychain-settings to prevent auto-lock during notarization
- Add timeout-minutes to both jobs
- Fix .gitignore missing trailing newline

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Skip release-macos job entirely when snapshot=true to avoid
  spinning up a macOS runner unnecessarily
- Pass APPLE_CERT_P12 as an env var in secrets_check rather than
  interpolating the secret directly into shell
- Fix mktemp resource leak in notarization loop: use mktemp -d
  and rm -rf the directory instead of leaking the base tempfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use SNAPSHOT env var in Validate dispatch inputs step instead of
  interpolating ${{ inputs.snapshot }} directly into shell
- Remove inputs.snapshot != true from all step-level conditions in
  release-macos, since the job-level if already gates on this

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously goreleaser ran with --draft which created the GitHub release
as a draft but still triggered the blobs publisher, uploading unsigned
macOS artifacts and a mismatched checksums.txt to GCS immediately.

Fix: run goreleaser with --skip publish on tag pushes so it builds all
artifacts without touching GCS or GitHub. Create the GitHub draft release
manually with gh after the build. Expand the artifact store upload to
include all platforms. In the macOS job, after signing, upload all
artifacts (Linux + Windows + signed macOS + updated checksums) to GCS
before publishing the draft release. GCS is now never written until
signing is complete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without this, a missing or malformed GOOGLE_APPLICATION_CREDENTIALS
secret would only surface late in the macOS job — after the draft
release is created and artifacts are signed — leaving a partial release
state requiring manual cleanup.

The new step validates the secret is present and is valid JSON before
goreleaser runs, matching the existing pattern for Apple signing secrets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch GCP auth to Workload Identity Federation (no long-lived key
  stored as a secret); mounts WIF credentials into the goreleaser-cross
  Docker container via ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN env vars
- Remove duplicate go test step from workflow (goreleaser before.hooks
  already runs it)
- Drop --parallelism 4 to 2 to match ubuntu-latest's 2 vCPUs
- Add comment on v0.* tag pattern explaining it's intentional
- Add brews section to .goreleaser.yml for Homebrew tap publish

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two issues prevented the Homebrew tap from ever being updated:

1. GoReleaser ran with --skip publish on every tag push, so the brews
   publisher never executed. Fix: add a goreleaser publish step in the
   macOS job after the GitHub release is public, skipping only the
   publishers handled manually (blobs, release, announce).

2. GITHUB_TOKEN cannot push to APImetrics/homebrew-tap (different repo).
   Fix: use HOMEBREW_TAP_GITHUB_TOKEN (a PAT/App token with write access
   to the tap) via brews.repository.token in .goreleaser.yml.

Also: upload artifacts.json + metadata.json from the Linux build so the
macOS job has the goreleaser dist metadata needed to run goreleaser
publish. Update artifacts.json checksums in the signing loop so goreleaser
publish uses the signed (not original) macOS archive hashes. Add repo
checkout to release-macos so goreleaser-action can find .goreleaser.yml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses actions/create-github-app-token@v1 to generate a short-lived
installation token at release time instead of storing a long-lived PAT.
The App is installed only on APImetrics/homebrew-tap with Contents:write,
so the blast radius is minimal and no personal account is involved.

Required secrets: GH_APP_ID, GH_APP_PRIVATE_KEY (replace HOMEBREW_TAP_GITHUB_TOKEN).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents all required one-time configuration: GCP Workload Identity
Federation setup (with gcloud commands), GitHub App creation for
Homebrew tap access, Apple signing certificate setup, and a complete
secrets reference table. Also covers how to cut a release and run
snapshot builds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix invalid --skip values in Publish Homebrew formula step: remove
  'build' and 'checksum' (not valid in v2.12.7), replace with correct
  values. In v2, '--skip archive' encompasses the build step; '--skip
  publish' covers both the GitHub release and blob storage publishers.
  Final skip list: before,archive,sign,sbom,publish,announce,validate,notarize
- Add google-github-actions/setup-gcloud@v2 step after WIF auth in
  release-macos to explicitly install gsutil rather than relying on
  runner image pre-installation
- RELEASING.md: note that GH_APP_PRIVATE_KEY must include PEM header
  and footer lines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
python3 -c "..." with a multi-line string placed Python code at zero
indentation inside the run: | literal block, which caused the YAML
parser to treat those lines as outside the block and fail on line 255.

Fix: switch to a heredoc (python3 << 'PYEOF') so Python content stays
at the run block's indentation level (10 spaces), which YAML strips
before passing to the shell, leaving Python with correct zero-indent
top-level code. Variables passed via env vars (PATCH_NAME/PATCH_SHA)
since heredocs don't support sys.argv.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ning

DS-5672: Harden release workflow and add Homebrew tap
… idempotent

- Remove the Authenticate to Google Cloud step from the Linux job —
  goreleaser always runs with --skip publish there so GCS uploads never
  happen from that job; the WIF credential was never used.
- Remove the CREDS_OPTS Docker mount logic that accompanied it.
- Make Create GitHub draft release idempotent: if the release already
  exists (workflow rerun after a partial failure), re-upload artifacts
  with --clobber instead of failing on a duplicate create.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

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

This PR prepares an initial v0.0.1 release candidate by adding AI agent “skills” distribution/onboarding, improving the OAuth login UX and safety, and introducing a full release pipeline (GoReleaser + GitHub Actions) along with updated project docs.

Changes:

  • Add skills command group plus a top-level onboard command, backed by embedded markdown skill workflows.
  • Refresh OAuth auth-code login pages (new HTML/CSS) and escape query params in the error page to prevent reflected XSS.
  • Add release infrastructure: GoReleaser configs, release/develop/quality GitHub workflows, and release documentation.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
skills/skills.go New CLI commands to install embedded skills and print onboarding context.
skills/embed/setup-mcp-monitor.md New agent workflow doc for MCP monitor setup.
skills/embed/setup-browser-monitor.md New agent workflow doc for browser monitor setup.
skills/embed/setup-api-monitor.md New agent workflow doc for API/call monitor setup.
RELEASING.md New release-process documentation and required secrets list.
README.md Replace upstream README with APImetrics CLI usage, flags, and agent integration docs.
oauth/authcode.go Update login success/error pages; escape error query params; improve interactive browser-opening flow.
main.go Wire in skills command initialization; move build config to tagged config files.
config_qc.go Add QC build-time endpoints/client ID via build tags.
config_prod.go Add production endpoints/client ID via prod build tag.
config_dev.go Add local dev endpoints/client ID via dev build tag.
cli/request_test.go Adjust tests for auth hook request base and Retry-After formatting.
cli/interactive_test.go Ensure HTTP basic auth is registered for interactive tests.
cli/cli.go Avoid loading APIs when profile/base URL is empty.
cli/cli_test.go Remove a large suite of CLI tests, leaving cache-focused coverage.
cli/apiconfig.go Guard against empty API base when matching URIs.
cli/apiconfig_test.go Remove several API command tests, leaving editor-missing test coverage.
cli/api.go Persist CLI version onto loaded API metadata.
bulk/commands_test.go Set ProjectID state explicitly for bulk workflow tests.
bench_test.go Import ordering adjustment.
.goreleaser/config.yaml New release GoReleaser configuration (prod builds, archives, checksums).
.goreleaser/config-qc.yaml New QC/snapshot GoReleaser configuration.
.goreleaser.yml Remove old root GoReleaser config in favor of .goreleaser/*.
.gitignore Ignore built binary, .DS_Store, and a secret JSON filename.
.github/workflows/release.yml Add multi-job release workflow (build, sign/notarize, homebrew, winget).
.github/workflows/quality.yml Add PR quality workflow (build + unit tests).
.github/workflows/develop.yml Add develop-branch QC artifact build + optional macOS signing.

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

Comment thread main.go
Comment thread README.md
Comment thread skills/skills.go
Comment thread skills/embed/setup-api-monitor.md
Comment thread skills/embed/setup-browser-monitor.md
Comment thread skills/embed/setup-mcp-monitor.md
Comment thread skills/embed/setup-api-monitor.md
Comment thread oauth/authcode.go
Comment thread skills/skills.go
@ndenny
ndenny disabled auto-merge July 8, 2026 00:33
@ndenny

ndenny commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Disabling auto-merge for now - working out if another fix is required for the release flow

@ndenny
ndenny enabled auto-merge July 8, 2026 00:36
@ndenny

ndenny commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Never mind - the mac signing failed because I had to accept some new t's & c's. All good to go now.

ndenny and others added 19 commits July 9, 2026 15:14
Added documentation link and APIContext Inc attribution.
Enhance README with documentation and attribution
`apimetrics --version` now prints the OpenAPI document version
(info.version) and the date/time the spec was last fetched from the
server, to aid customer support and debugging.

- Persist the spec version in the cached API struct (SpecVersion),
  captured from libopenapi's model.Info.Version (previously discarded).
- Record a `<name>.checked` timestamp in cacheAPI (24h refresh TTL
  unchanged).
- Add a custom cobra version template that appends the two lines.
- Make --version a pure reporting command: it reads the cached spec
  state from disk and skips the network load, so it works offline and
  never triggers an auth prompt.

Fixtures updated: testdata/*/output.yaml now include spec_version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address PR review: versionExtraInfo now only trusts the on-disk cache
when its CLIVersion matches the running binary, mirroring Load's
validity check, so --version won't report a stale spec version/timestamp
after a binary upgrade (the CLI would refetch that cache anyway). Also
skip the cache lookup entirely when api-name is empty.

Add TestVersionExtraInfo covering the no-cache, valid-cache, and
stale-cache (mismatched CLIVersion) paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Loading the OpenAPI spec (the entrypoint and /openapi.json) is done
against public endpoints, but MakeRequest was still applying the
profile's auth, which triggered an interactive login on any invocation
that hit a cache miss -- including `apimetrics`, `apimetrics --help`,
completion, and config commands that never call an API operation.

Add an IgnoreAuth() request option and use it for the two spec-loading
requests in Load, so building the command tree never prompts for login.
Auth is still applied for real API operations (which don't pass the
option).

Add TestIgnoreAuth verifying the auth hook is skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Address PR review: the offline/no-auth skip for --version matched only
the literal "--version" arg, so `--version=true` would still trigger the
network load. Register a version bool on GlobalFlags and read it via the
eager parse, which handles every bool form (--version, --version=true,
--version=false) consistently with Cobra.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update Homebrew installation command for APImetrics CLI
…-cmd

Report OpenAPI spec version and last-check date in --version
Each environment now bakes in its own command name, which also names the
config and cache directories, so the builds can be installed side by side
and stay logged in to different environments at the same time.

- Add qc-stable (build tag `qcstable`) and beta (build tag `beta`)
  configurations. Beta points at beta-client.apimetrics.io but authenticates
  against production Auth0. This also fixes the duplicate build tag that made
  config_qc_stable.go collide with config_qc.go.
- Derive the config and cache directories from the per-build app name, and
  map hyphens to underscores when building the <APPNAME>_CONFIG_DIR and
  <APPNAME>_CACHE_DIR overrides so hyphenated names remain usable.
- Report the environment, API host and config directory in --version.
- Add goreleaser configs for qc-stable and beta, and an environment selector
  to the develop workflow.
- Sign and notarize tagged environment builds: a semver prerelease suffix on
  a v0.* tag (-beta-N, -qc-N, -qc-stable-N) selects the environment and
  publishes a GitHub prerelease. Homebrew and WinGet stay production-only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nfiguration-for-cli

DS-5850 Add qc-stable and beta builds, installable in parallel
Authenticate with an APImetrics service account instead of the browser
login, which is what makes the CLI usable from CI and other headless
environments. Point `--service-account` (or the environment variable
`<APP_NAME>_SERVICE_ACCOUNT`) at the JSON file the web app issues and
every request uses the OAuth 2.0 client credentials grant.

The client credentials grant issues no refresh token (RFC 6749 4.4.3) and
Auth0 rejects `offline_access` for it, so the hour-long access token is
cached and simply re-requested on expiry. Tokens are cached under a key
derived from the credentials rather than the profile, so a service
account never picks up the interactive login's token or another
account's, and rotating a secret invalidates the cache instead of
silently serving the old token.

Also add `--project-id` / `<APP_NAME>_PROJECT_ID`. Service accounts are
granted access to specific projects and headless runs cannot answer the
interactive project picker, so without this the first call in CI hangs on
a prompt. The override applies to a single run and never overwrites the
project saved by `project select`; a non-TTY run with no project now
fails with an actionable message rather than a dead prompt.

Global flags are parsed exactly once, in Run. Parsing them a second time
would append to the repeatable flags, doubling every `-H` and `-q` value,
so the service account and project overrides are applied there rather
than in Init.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Include the audience in the service account's token cache key. The file
format lets a service account name its own audience, so two files sharing
a client id, secret and token URL but naming different audiences would
otherwise share a cache entry and be handed a token minted for the wrong
audience.

Clear the `.refresh` entry in `logout --service-account` alongside the
rest. The client credentials grant issues no refresh token, but
TokenHandler writes one whenever the endpoint returns it and reads it
back when rebuilding a cached token, so leaving it behind would let a
stale entry outlive a logout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 1, 2026 07:53

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

Copilot reviewed 45 out of 46 changed files in this pull request and generated 4 comments.

Suppressed comments (1)

README.md:16

  • "MacOS" should be spelled "macOS" (Apple’s official capitalization).
## MacOS

Comment thread cli/request_test.go
Comment thread README.md
Comment thread skills/skills.go
Comment thread cli/cli_test.go
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.

5 participants