All notable changes to the github-copier application are documented in this file.
The format is based on Keep a Changelog.
- "Disconnected" chip always visible —
.chip{display:inline-flex}in the author stylesheet overrode the browser's[hidden]{display:none}UA rule; added[hidden]{display:none!important}globally so all hidden elements are correctly concealed.
- Version always showing "dev" —
--set-build-env-varsdoes not propagate to DockerARGvalues in Cloud Run's buildless deploy path. App now readsAPP_VERSIONenv var at startup as a runtime fallback; CI deploy sets it via--set-env-vars. - Disconnected chip diagnosis — heartbeat
catchhandler now logs the fetch error toconsole.errorso the root cause is visible in DevTools when the chip appears.
- Anthropic API key trailing newline — secrets loaded from Secret Manager are now trimmed of surrounding whitespace before use, preventing
invalid header field valueerrors when the secret was stored with a trailing newline.
- Operator UI — comprehensive writer + operator dashboard at
/operator/(OPERATOR_UI_ENABLED=true). Five tabs (Overview, Webhooks, Audit, Workflows, System), sticky status bar, dark mode, keyboard shortcuts, shareable URLs, and a writer/operator mode toggle persisted to localStorage. - GitHub PAT authentication — users sign in with their personal access token; role is derived from their permission on
OPERATOR_AUTH_REPO(admin/maintain → operator, write/triage/read → writer). Operator actions (replay, release, AI settings) require an explicit admin or maintain grant, since most writers havewriteon the auth repo. Replay additionally enforces read access on the source repo for that specific delivery. - AI rule suggester — paste a source path and desired target state, receive a suggested workflow rule with self-verification via the in-process
PatternMatcher. Two providers supported:- Anthropic (hosted) — default for Cloud Run. API key loaded from Secret Manager via
ANTHROPIC_API_KEY_SECRET_NAME. No infra required; operators switch between Haiku / Sonnet / Opus from the UI. - Ollama (local) — for dev or self-hosted deployments. UI manages connection, model pulls, deletes, and active-model switching without a redeploy.
- Anthropic (hosted) — default for Cloud Run. API key loaded from Secret Manager via
- Writer-facing features — workflow browser with per-rule coverage, PR lookup by URL, recent copies feed, file match tester (with clear button and Python-style
(?P<name>)regex translation for in-browser use), PR timeline, and in-app help overlay. - Per-delivery log viewer — context-tagged ring buffer captures logs per webhook delivery, surfaced in an audit drawer alongside the trace and outcome summary.
- Audit event enrichment —
processed_oktraces now include destination repo(s), files matched / uploaded / failed, and commit SHA. - Startup banner — Operator UI, auth repo, AI model, and AI base URL are now surfaced when the app boots (local and Cloud Run).
- MongoDB audit logging enabled in production — the Cloud Run deploy previously forced
AUDIT_ENABLED=false; it is nowtrue, aligning with the v0.3.0 "enabled by default" change. - Operator auth hardened — token-based auth (
OPERATOR_UI_TOKEN) removed entirely; GitHub PAT is the only supported mechanism.OPERATOR_UI_ENABLED=truenow requiresOPERATOR_AUTH_REPOat config load (validated invalidateOperatorAuth). createPullRequestskipped for empty commits —commitFilesToBranchnow returns anerrTreeUnchangedsentinel soaddFilesViaPRno longer calls the GitHub PR API with an unchanged tree (previously 422'd).- MongoDB driver v2 ObjectID decoding — audit reads set
ObjectIDAsHexString: trueto avoid "error decoding key_id" on queries.
- gosec G107 / G704 SSRF findings — GitHub API URL construction in
services/operator_auth.gonow validates path components against strict RE2-compatible whitelists (ghUsernameRe,ghRepoNameRe) and escapes them withurl.PathEscapebefore request construction;slack_notifier.go#nosecannotation extended to coverNewRequestWithContext. - Keyboard-shortcut overlay wouldn't close —
.help-bg[hidden]now wins over the basedisplay:flex. - File match tester returned no matches for Java files — JavaScript
RegExpdoes not support Python-style(?P<name>)named groups; the tester now rewrites(?P<→(?<before compilation.
- Token auth removed — the operator UI no longer accepts a shared bearer token; all access is per-user via GitHub PAT with repo-scoped permission checks.
- Config cache corruption —
CachedConfigLoaderno longer returns stale entries when filtering workflows by source repo.
- Removed unneeded config files from the repository.
- Audit logging enabled — MongoDB audit logging is now enabled by default.
- Missing
#nosec G706annotations — Added suppression comments toLogInfoandLogErrorfor gosec false positives.
- gRPC vulnerability fix — Upgraded
google.golang.org/grpcto v1.79.3 to address CVE-2026-33186.
.golangci.ymlconfig — Pinned linter and formatter configuration (v2 format) for consistent CI and local behavior. Enabled linters:errcheck,govet,ineffassign,staticcheck,unused,misspell,revive.- Structured error alerting —
ErrorEventnow includesDeliveryIDandAttemptsfields. Slack failure notifications include the GitHub delivery ID and attempt count for full traceability. - Integration test for target repo batching —
TestIntegration_TargetRepoBatching_MixedStrategiesverifies that workflows with different commit strategies produce separate operations, while same-strategy workflows batch correctly. - End-to-end integration tests —
TestIntegration_MergedPR_DirectCommitcovers the full webhook-to-commit pipeline; additional tests cover no-matching-workflows, config-load errors, and webhook signature verification. - Config reference doc —
docs/CONFIG-REFERENCE.mdprovides a single-page reference for all environment variables and workflow YAML schema. - Webhook routing guide — Added a "Webhook Routing" section to
docs/LOCAL-TESTING.mddocumenting how to avoid dual-delivery (local + Cloud Run processing the same webhook). - Webhook processing timeout — Background goroutine now applies
context.WithTimeout(configurable viaWEBHOOK_PROCESSING_TIMEOUT_SECONDS, default 300s). - Retry with exponential backoff —
processWebhookWithRetryretries failed webhook processing with configurable max retries and initial delay. Panics are recovered and retried. Slack alert sent after exhaustion. - Graceful partial failure —
processFilesWithWorkflowsprocesses each workflow independently and returns per-workflow errors. One workflow failure no longer blocks others. - Config caching —
CachedConfigLoadercaches resolved workflow configs with a configurable TTL (default 5 min, viaCONFIG_CACHE_TTL_SECONDS). - Parallel file fetching —
ProcessWorkflownow fetches file contents concurrently viaerrgroup(concurrency limit of 5). - PR deduplication —
addFilesViaPRchecks for existingcopier/*PRs before creating new ones; pushes to existing branch and updates metadata instead. - Empty commit prevention —
createCommitTreereturns base tree SHA; commits are skipped when the new tree is identical to HEAD. - Mixed commit strategy fix —
UploadKeynow includesCommitStrategy, separating write operations fordirectvspull_requestworkflows targeting the same repo. Config-time warning for conflicting strategies. - PR metadata overwrite logging — Logs when a subsequent workflow overwrites a batched commit message or PR title.
- Health check probes — Liveness (
/health) and readiness (/ready) endpoints. - Webhook idempotency — In-memory
DeliveryTrackerprevents duplicate processing of the sameX-GitHub-Deliveryheader within a single instance. - Rate limiting — GitHub API retry logic with exponential backoff.
- CLI tools —
config-validator,test-webhook, andtest-pemutilities undercmd/. /configdiagnostic endpoint — Read-only endpoint showing resolved runtime config (secrets redacted) and workflow summary.- Transient vs permanent error classification —
IsPermanentError()detects non-retryable failures (404, 403, config validation, etc.); retry loop skips retries immediately for permanent errors. - Version stamping — Binary version set via
-ldflagsat build time; exposed on/health,/config, startup banner, and-versionflag. - Release script —
scripts/release.shautomates CHANGELOG update, git tagging, push, and GitHub Release creation.
- Go version — Upgraded to Go 1.26.0.
- golangci-lint — Upgraded to v2.9.0 (action v7 in CI).
- go-github — Upgraded to v82; replaced deprecated
github.String/Int/Boolwithgithub.Ptr. - Logging — Migrated to
log/slogwith structured JSON output. - Pre-commit hooks —
golangci-linthook useslanguage: systemwith--fix; requires local v2.9.0 install. - App banner — Now displays version and
EffectiveConfigFile()instead of the legacyConfigFiledefault. - CI deploy trigger — Deployment now triggers on version tag pushes (
v*) instead of every push tomain. Tags stamp the version into the Cloud Run revision. - Legacy config deprecation —
DefaultConfigLoader(single-file config) is marked deprecated with runtime warnings; dead code (ConfigValidator, unused struct fields) removed.
- CI lint/security failures — Resolved
golangci-lintGo version incompatibility,gosectaint analysis false positives (G703–G706), and allerrcheck/staticcheck/unusedissues. - gitleaks false positive — Added
.gitleaksignoreentries for example and test-only PEM keys. - Tightened gosec exclusions — Removed all global
gosecexclusions from CI; sole remaining false positive suppressed with inline#nosec G115.
- Go toolchain directive — Added
toolchain go1.26.0togo.modfor deterministic builds.
- CI/CD pipeline with GitHub Actions (
.github/workflows/ci.yml)- Test job
- Lint job with golangci-lint
- Security scanning with gosec
- Build verification
- Automated deployment to Cloud Run on merge to main (via Workload Identity Federation)
- Pre-commit hooks for secrets detection and Go linting (
.pre-commit-config.yaml) - AGENT.md for AI agent context
- Comprehensive test suite for
workflow_processor.go(843 lines, 94%+ coverage) - Integration test harness for local testing (
scripts/integration-test.sh) - Test environment configuration (
testdata/.env.test)
- Renamed module from
github.com/mongodb/code-example-tooling/code-copiertogithub.com/grove-platform/github-copier - Renamed binary from
examples-copiertogithub-copier - Renamed
test-payloads/totestdata/(Go convention) - All
log.Fatalcalls replaced with proper error returns for graceful error handling FileStateService.filesToDeprecatechanged from single-entry map to slice-based accumulation
- Deprecation file accumulation bug: multiple deprecated files now correctly accumulate instead of overwriting
- Nil pointer dereference bugs across GitHub API calls in:
services/github_read.goservices/github_write_to_source.goservices/main_config_loader.goservices/config_loader.go
- DELETED file status handling: GitHub GraphQL API returns uppercase
DELETEDbut code checked for lowercaseremoved - Graceful shutdown now properly waits for in-flight requests and cleans up resources
- Added gitleaks pre-commit hook for secrets detection
- Added gosec security scanning in CI pipeline
- Webhook service for automated file copying on PR merge
- Pattern matching support: prefix, glob, regex
- Transformation types: move, copy, glob, regex
- Main config system with
$refsupport for distributed workflow configs - Commit strategies: direct commit or pull request
- Health and metrics endpoints
- Slack notifications for operational visibility
- MongoDB audit logging (optional)
- Google Cloud Logging integration
- Dry-run mode for testing