feat: add github-actions-deploy solution - #233
Merged
Merged
Conversation
Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Catalog entity, deploy health scorecard, GitHub Actions workflow template, and README for the GitHub Actions deploy tracking solution. Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Provides prompt collection with env var fallback, Y/N confirmation,
idempotency state tracking via ~/.cortex/setup-{solution}.json, step
execution with progress display, and post_steps() hook for subclasses.
Linear: CX-6
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Required by github-actions-deploy setup script to encrypt secrets before storing them via the GitHub API (libsodium sealed box). Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Interactive wizard that creates a GitHub repo, seeds the Cortex deploy workflow, sets CORTEX_API_KEY and CORTEX_BASE_URL secrets, and optionally triggers the first workflow run. All steps are idempotent. Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ey bytes() - _create_repo now raises RuntimeError on any non-200, non-404 response when checking repo existence (previously proceeded to POST on any non-200) - Remove unused `from typing import Optional` import from setup.py - Use bytes() instead of private ._public_key attribute when serializing the nacl PublicKey in test_set_secret - Add test_create_repo_raises_on_unexpected_status to cover 403 case Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New `cortex solutions post-install -s <solution>` subcommand - `cortex solutions install` prompts for post-install setup when setup.py present - `--skip-post-install-setup` flag bypasses the prompt - Helper functions _has_post_install and _run_post_install_script for reuse Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add test coverage for --skip-post-install-setup flag (skips script, prints 'Run setup later' message) - Add test coverage for install prompt when setup.py present (user answers 'y', script is called) - Add is_flag=True to --skip-post-install-setup Option - Remove dead code: inner `if not setup_path.exists()` branch inside as_file() block in _run_post_install_script (unreachable; outer except FileNotFoundError already handles missing file) Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
deploys() is not a valid Cortex CQL function. Replace with customMetrics(key="deploy-count", lookback=...) expressions, and update the GitHub Actions workflow template to post a deploy-count metric alongside the deploy event so the scorecard evaluates correctly. Linear: CX-6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use OSC 8 hyperlinks in post_steps output (clickable in iTerm2) - Secret prompts now hidden via getpass (no echo on terminal) - API key and base URL pre-filled from active CLI session - Show "Use current Cortex API key?" / "Use current Cortex base URL?" instead of generic env var prompts - Install hook shows solution-specific SETUP_DESCRIPTION instead of generic message - Pass CLI client context to post-install script for both install and post-install commands Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use /admin/resources?tag=<tag> instead of /catalog/<tag> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… CX-6 - New workflow: github-actions-trigger-deploy (HTTP_REQUEST_ASYNC) Triggers GitHub Actions dispatch and waits for callback from the workflow run. Surfaces conclusion, sha, and run URL in the Cortex workflow result. - Updated cortex-deploy.yml template: Accepts optional cortex_callback_url workflow_dispatch input. Final step in notify-cortex job POSTs back to the callback URL on success, completing the async Cortex workflow run with structured output. - Updated setup.py post_steps(): Replaces direct GitHub API trigger with Cortex workflow run via API. Polls for COMPLETED/FAILED/CANCELLED status (up to 5 min). Marks first_deploy in persistent state on success. Non-fatal on failure — prints retry instructions instead of exiting. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When backup.import_tenant() raises (e.g. invalid workflow YAML), _run_import_with_toggle was silently swallowing all captured output. Now flushes the buffer to real stdout before re-raising, so errors are always visible. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cortex only allows a-z, 0-9, and hyphens in workflow variable slugs. github_token/github_owner/repo_name → github-token/github-owner/repo-name Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Cortex workflow run API expects variable values as top-level keys in initialContext, not nested under a "variables" wrapper. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…for CX-6
- collect_prompts: fetch GitHub integrations from Cortex API first.
If found, present numbered list (default = isDefault), no GITHUB_TOKEN prompt.
If none, fall through to GITHUB_TOKEN prompt as before.
- Setup steps (create repo, seed, set secrets) use GITHUB_TOKEN from env var
silently when an integration is configured; error naturally if not set.
- Workflow YAML: replace github-token variable + Authorization header with
integrationAlias: "{{variables.github-integration}}" (no raw token in workflow)
- post_steps: when integration selected, triggers via Cortex workflow (async,
waits for callback); when no integration, triggers GitHub API directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- integration: GitHub (required alongside integrationAlias)
- URL is relative (base URL prepended by integration automatically)
- headers: {} (empty object, not list)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The callback URL requires auth like any Cortex API endpoint. Uses the CORTEX_API_KEY repo secret already set during post-install. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ions deploy
- Move trigger-github-deploy.yaml to _templates/ (Cortex validates integrationAlias
at import time and rejects template variable expressions like {{variables.xxx}})
- Add setup step to import the Cortex workflow with the selected alias substituted
- Add always() to callback step so it fires even if deploy registration fails
- Add required status/message fields to Cortex callback payload
- Update runResponseTemplate to use variables (result is null for HTTP_REQUEST_ASYNC
when initial request returns 204 with no body)
- Fix headers: {} required even with integration auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
actions is a list in the workflow run response, not a dict. Also remove stale [5/5] step numbers that became inaccurate when the import step was added. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…a in template
- Map GitHub job.status to SUCCESS/FAILURE/CANCELLED before POSTing callback
(was hardcoded SUCCESS, causing Cortex to show success on failed GH Actions runs)
- Add conclusion, sha, run_id, run_url to callback output payload
- Update runResponseTemplate to render conclusion, SHA, and direct run link
via {{actions.trigger-deploy.outputs.output.*}} (callback output path)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…) CQL Deploy data is already captured via the deploys API — no need for a redundant custom metric. Scorecard rules now use deploys(lookback=...) directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… template path Three bugs fixed: - Fragile multi-line -d string caused output:null in callback; switch to jq - job.status reflected notify-cortex infra failures, not build outcome; use needs.build.result so only actual build failures report FAILURE - Template used outputs.output.* (wrong); correct path is outputs.result.output.* since Cortex stores the callback payload in result for HTTP_REQUEST_ASYNC Also adds continue-on-error on the register-deploy step so a Cortex API error doesn't pollute the callback status. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sends two intermediate IN_PROGRESS updates (10s apart) before the final SUCCESS/FAILURE/CANCELLED callback, demonstrating Cortex's support for streaming progress updates from async actions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t to 120s Cortex callback endpoint only accepts terminal statuses (SUCCESS/FAILURE/CANCELLED). IN_PROGRESS caused a 4xx, killing the step before the terminal callback could fire. Reduced timeoutInSeconds from 300 to 120 — GH Actions run completes in ~20-30s. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove trigger-github-deploy.yaml (variables+branch pattern preserved in skill) - Rename deploy-from-entity.yaml → github-actions-deploy.yaml, tag → github-actions-deploy - setup.py: single import step, entityId lookup before entity-scoped run
Add cortex-async-callback and cortex-register-deploy as local composite actions seeded into .github/actions/. cortex-deploy.yml now uses both. setup.py seeds all three files via a generic _seed_file helper.
…ipping integration select
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tput.sha Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n response cid Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…esponseTemplate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…apt section Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e in API Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n link Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
github-actions-deploysolution bundle: entity, scorecard, Cortex workflow, and GitHub Actions workflow (cortex-deploy.yml)cortex solutions post-installsubcommand for running setup later~/.cortex/solutions/with--no-promptreplay supportcortex-async-callbackandcortex-register-deploySolutionSetupbase class for future solution setup scriptsTest plan
just test tests/test_setup_base.py— base class unit testsjust test tests/test_github_actions_setup.py— setup script unit testsjust test tests/test_solutions_postinstall.py— post-install command testscortex solutions install -s github-actions-deploy --skip-post-install-setup— install without setupcortex solutions post-install -s github-actions-deploy— interactive setupcortex solutions post-install -s github-actions-deploy --no-prompt— non-interactive replay🤖 Generated with Claude Code