Skip to content

v0.0.1 candidate#16

Open
ndenny wants to merge 75 commits into
mainfrom
develop
Open

v0.0.1 candidate#16
ndenny wants to merge 75 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>
ndenny and others added 19 commits June 12, 2026 13:31
The welcome banner string already ends with a newline, so Fprintln
appended a redundant one. Switch to Fprint to satisfy go vet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This branch replaced the auto-discovered root .goreleaser.yml with two
env-specific configs but placed them under dist/, which is gitignored,
so they never reached CI — the release job failed with
"open dist/config.yaml: no such file or directory". (goreleaser's
--clean also wipes dist/ at startup, so committing them there would not
work either.) Relocate both to a tracked .goreleaser/ directory and
point the release and develop workflows at the new paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The [Y/n] prompt read from stdin but only checked that stderr was a
terminal. If a request body was piped into stdin while stderr was a
TTY, the prompt would consume its first line. Check stdin instead,
matching the manual-code path that protects piped input.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- ServeHTTP now HTML-escapes the error/error_description query params
  before interpolating them into the error page, preventing reflected
  XSS via the localhost redirect URL.
- The release tag guard fetches origin/main* explicitly before
  git branch --contains, since tag pushes don't populate remote-tracking
  refs and the check would otherwise fail on legitimate main tags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Snapshot (--snapshot) dispatches now build with config-qc.yaml so they
produce QC binaries, and the resulting dist artifacts are uploaded to the
workflow run as qc-snapshot-artifacts for download. Previously snapshot
runs used the prod config and uploaded nothing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Snapshot runs previously bundled every artifact under a single
qc-snapshot-artifacts entry, which GitHub serves as one combined zip.
Upload each platform archive (and checksums.txt) as its own artifact so
the Actions run lists them individually. Non-snapshot release runs keep
the combined release-artifacts bundle the macOS job depends on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously the release-macos job was gated off entirely for snapshot
(QC) builds, so snapshot darwin archives were never signed and only the
unsigned placeholders from the build job were available.

Now the macOS job runs for snapshot dispatches too: it pulls the
individually-uploaded QC artifacts, signs/notarizes the darwin archives,
and re-uploads the signed archives (and updated checksums.txt) as
individual assets, overwriting the unsigned placeholders. The tag-release
path is unchanged — it still downloads the combined release-artifacts
bundle and produces macos-signed-artifacts. The artifacts.json checksum
patch is skipped when that file is absent (snapshot builds).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merges to develop run develop.yml on every push, so notarizing the macOS
builds each time wastes time and Apple notary quota — those are internal
QC artifacts, not externally distributed. Drop the notarytool submit step
and the now-unused APPLE_ID/APPLE_ID_PASSWORD/APPLE_TEAM_ID env vars,
keeping codesign + verify. Notarization is retained for snapshot
dispatches and tagged releases in release.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Prod build and a QC build
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…eases

Use github release assets instead of GCS
Copilot AI review requested due to automatic review settings July 7, 2026 23:36
@ndenny ndenny enabled auto-merge July 7, 2026 23:36

Copilot AI left a comment

Copy link
Copy Markdown

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
"apicontext.com/apimetrics/skills"
)

var version string = "dev"
Comment thread README.md

## Passing Input

All create and update commands read a JSON body from **stdin** using a heredoc. There is no `--body`, `--data`, or `-d` flag.
Comment thread skills/skills.go

b.WriteString("## Critical facts\n\n")
b.WriteString("- Commands are flat, not grouped: use `create-call`, not `calls create`\n")
b.WriteString("- All create commands read JSON from stdin using heredoc syntax — there is no `--body`, `--data`, or `-d` flag\n")

## Input format

All `apimetrics` create commands read JSON from stdin. Use heredoc syntax:

## Input format

All `apimetrics` create commands read JSON from stdin. Use heredoc syntax:

## Input format

All `apimetrics` create commands read JSON from stdin. Use heredoc syntax:

`frequency` is in seconds. Common values: `60` (1 min), `300` (5 min), `3600` (1 hour).

**Validation gate:** Confirm the schedule lists the monitor ID in its targets before proceeding.
Comment thread oauth/authcode.go
Comment on lines 235 to 240
if err := r.URL.Query().Get("error"); err != "" {
details := r.URL.Query().Get("error_description")
rendered := strings.Replace(strings.Replace(htmlError, "$ERROR", err, 1), "$DETAILS", details, 1)
// Escape the query params before interpolating into HTML to avoid
// reflected XSS via the localhost redirect URL.
rendered := strings.Replace(strings.Replace(htmlError, "$ERROR", html.EscapeString(err), 1), "$DETAILS", html.EscapeString(details), 1)
w.Write([]byte(rendered))
Comment thread skills/skills.go
Comment on lines +74 to +78
func resolveTarget(claudeCode, codex bool, dir string) (string, agent, error) {
count := 0
if claudeCode {
count++
}
@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 added 3 commits July 9, 2026 15:14
Added documentation link and APIContext Inc attribution.
Enhance README with documentation and attribution
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