Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 15 additions & 50 deletions .github/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ workflows (`> …`, prefixed `_`) are called via `uses:`.
| `publish-release.yml` | workflow_dispatch | — |
| `merge-release.yml` | workflow_dispatch | — |
| `build-native-only.yml` | push/PR/release when msg/label has `build:native:only` | `_build-native-only` |
| `claude-code-interactive.yml` | `@claude` mentions + workflow_dispatch | `_claude-code` (interactive) |
| `claude-code-automation-pr-review.yml` | PR with `claude` label or `ready_for_review` | `_claude-code` (automation) |
| `claude-code-automation-operational-excellence-weekly.yml` | schedule + workflow_dispatch | `_claude-code` (automation) |
| `scheduled-testing-staging-hourly.yml` | cron `0 * * * *` | `_scheduled-test-hourly` (staging) |
| `scheduled-testing-staging-daily.yml` | cron `0 12 * * *` | `_scheduled-test-daily` (staging) |
| `scheduled-testing-production-hourly.yml` | cron `0 * * * *` | `_scheduled-test-hourly` (production) |
Expand All @@ -31,7 +28,7 @@ workflows (`> …`, prefixed `_`) are called via `uses:`.

Reusable: `_lint`, `_docs`, `_audit`, `_test`, `_codeql`,
`_ketryx_report_and_check`, `_package-publish`, `_build-native-only`,
`_claude-code`, `_scheduled-audit`, `_scheduled-test-hourly`,
`_scheduled-audit`, `_scheduled-test-hourly`,
`_scheduled-test-daily`, `_scheduled-test-stress`.
(`stress-testing-staging.yml.paused` is currently disabled.)

Expand Down Expand Up @@ -119,63 +116,31 @@ Runners: `ubuntu-latest` (stable) plus experimental `ubuntu-24.04-arm`,
`macos-latest`, `macos-15-intel`, `windows-latest` (UPX), `windows-11-arm`.
Output: `aignostics.7z` per platform. Local: `make dist_native`.

## Claude Code (`_claude-code.yml`)

One reusable workflow, two modes via the `mode` input:

- **interactive** — full git history (`fetch-depth: 0`).
`claude-code-interactive.yml` triggers it on `@claude` mentions
(issue/PR comments, reviews, issues, PRs) and `workflow_dispatch`. It passes
only `mode` and `track_progress` — there are **no** `prompt`/`max_turns`/
`environment` inputs to fill in.
- **automation** — shallow history (`fetch-depth: 1`), runs a fixed `prompt`.
`claude-code-automation-pr-review.yml` triggers it when a PR carries the
`claude` label or becomes `ready_for_review`. `max_turns` is not set, so it
uses the `_claude-code.yml` default (200). Review tools include
`mcp__github_inline_comment__create_inline_comment` and posts a
`claude:review:passed` / `claude:review:failed` verdict label.

`_claude-code.yml` inputs: `mode` (required), `prompt`, `max_turns` (default
`200`), `allowed_tools` (default defined in the workflow — read it there rather
than copying), `track_progress`, `use_sticky_comment`. Model is
`claude-sonnet-4-5-20250929`.

**Setup**: installs `uv`, dev tools (`_install_dev_tools.bash`),
`uv sync --all-extras --locked`, headless display. Only secret available is
`ANTHROPIC_API_KEY` — Claude Code workflows intentionally have **no** platform
or GCP credentials.

## Scheduled jobs

- **Testing** — staging and production each run **hourly** (`0 * * * *`, via
`_scheduled-test-hourly.yml`) and **daily at 12:00 UTC** (`0 12 * * *`, via
`_scheduled-test-daily.yml`). Run `make test_scheduled`, send a BetterStack
heartbeat. Staging → `https://platform-staging.aignostics.com`, production →
`_scheduled-test-daily.yml`) and run `make test_scheduled`. Staging →
`https://platform-staging.aignostics.com`, production →
`https://platform.aignostics.com`.
- **Audit** — hourly (`_scheduled-audit.yml`): `pip-audit`, `pip-licenses`,
Trivy SBOM scan + BetterStack heartbeat.
Trivy SBOM scan.
- **CodeQL** — weekly Tue 03:22 (`_codeql.yml`).

### BetterStack heartbeats

Scheduled test/audit jobs POST a metadata JSON payload to
`{HEARTBEAT_URL}/{EXIT_CODE}` (0 = success) so BetterStack alerts on failures or
missed beats. If the URL secret is unset the step logs a warning and continues.
Secrets: `BETTERSTACK_AUDIT_HEARTBEAT_URL`,
`BETTERSTACK_HEARTBEAT_URL_{STAGING,PRODUCTION}` (hourly),
`BETTERSTACK_HEARTBEAT_URL_FLOWS_{STAGING,PRODUCTION}` (daily).

## Environments & secrets

**Staging** (`platform-staging.aignostics.com`) is the default for all PR CI and
E2E. **Production** (`platform.aignostics.com`) is used only by scheduled jobs
and release validation — never in PR CI.

GitHub secrets: `ANTHROPIC_API_KEY`,
`AIGNOSTICS_CLIENT_ID_DEVICE_{STAGING,PRODUCTION}`,
`AIGNOSTICS_REFRESH_TOKEN_{STAGING,PRODUCTION}`, the BetterStack URLs above,
`CODECOV_TOKEN`, `SONAR_TOKEN`, `SENTRY_DSN`/`SENTRY_AUTH_TOKEN`,
`UV_PUBLISH_TOKEN`, `KETRYX_PROJECT`/`KETRYX_API_KEY`, `SLACK_*_RELEASE_ANNOUNCEMENT`.
GitHub secrets: `AIGNOSTICS_REFRESH_TOKEN_{STAGING,PRODUCTION}`, `CODECOV_TOKEN`,
`SONAR_TOKEN`, `UV_PUBLISH_TOKEN`, `KETRYX_API_KEY`.

GitHub variables: `KETRYX_PROJECT`.

CI logs in with the refresh token, which uses the public interactive client ID
from `src/aignostics/platform/_constants.py`. Only the device flow reads
`AIGNOSTICS_CLIENT_ID_DEVICE`, so CI does not set it.

Local `.env` for E2E:

Expand Down Expand Up @@ -206,9 +171,9 @@ can push.
Reproduce locally with the same make targets CI uses: `make lint`,
`make test_unit` / `test_integration` / `test_e2e` (E2E needs `.env`),
`make dist_native`, `uv run pip-audit`. Coverage minimum is enforced via
Codecov (see `codecov.yml`). For scheduled-job failures, check the BetterStack
dashboard and the workflow run logs (usual causes: API changes in the target
environment, expired credentials).
Codecov (see `codecov.yml`). For scheduled-job failures, check the workflow run
logs (usual causes: API changes in the target environment, expired
credentials).

Run scheduled workflows manually:

Expand Down
12 changes: 0 additions & 12 deletions .github/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,6 @@
color: "1d76db"

# AI Assistant Labels
- name: claude
description: Trigger Claude Code automation
color: "b41d8f"

- name: claude:review:passed
description: Automated Claude PR review found no blocking issues on the current head commit
color: "0e8a16"

- name: claude:review:failed
description: Automated Claude PR review found blocking issues on the current head commit
color: "b60205"

- name: copilot
description: GitHub Copilot related
color: "e6dac6"
Expand Down
107 changes: 0 additions & 107 deletions .github/workflows/_claude-code.yml

This file was deleted.

8 changes: 2 additions & 6 deletions .github/workflows/_install_dev_tools.bash
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ TRIVY_VERSION=v0.76.1
case "$(uname -m)" in
x86_64)
trivy_arch="64bit"
TRIVY_SHA256="c7cbe3137fb8a48a17574bede3dd6beb16742d1e9772929940fc90082c39d9c0" # trivy_0.76.1_Linux-64bit.tar.gz
TRIVY_SHA256="c7cbe3137fb8a48a17574bede3dd6beb16742d1e9772929940fc90082c39d9c0" # trivy_0.76.1_Linux-64bit.tar.gz # pragma: allowlist secret
;;
aarch64 | arm64)
trivy_arch="ARM64"
TRIVY_SHA256="e174dff2a6dba5e3ae41f8d0537a6324405bd08132497340304c6b20e0f16a1f" # trivy_0.76.1_Linux-ARM64.tar.gz
TRIVY_SHA256="e174dff2a6dba5e3ae41f8d0537a6324405bd08132497340304c6b20e0f16a1f" # trivy_0.76.1_Linux-ARM64.tar.gz # pragma: allowlist secret
;;
*)
echo "No Trivy checksum for architecture $(uname -m)" >&2
Expand All @@ -47,10 +47,6 @@ sudo install -m 0755 "${trivy_tmp}/trivy" /usr/local/bin/trivy
rm -rf "${trivy_tmp}"
trivy --version

# Install further tools not project specific
# Download Sentry CLI securely: enforce HTTPS, disable redirects
wget --secure-protocol=TLSv1_2 --max-redirect=0 -qO - https://sentry.io/get-cli/ | SENTRY_CLI_VERSION="2.57.0" sh

# Install project specific tools
.github/workflows/_install_dev_tools_project.bash

Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/_ketryx_report_and_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ on:
required: false
type: string
secrets:
KETRYX_PROJECT:
required: false
KETRYX_API_KEY:
required: false

Expand Down Expand Up @@ -78,7 +76,7 @@ jobs:
continue-on-error: ${{ github.event_name == 'pull_request' }}
uses: Ketryx/ketryx-github-action@e7ad6ff71022a4e8158477c4458778bf4d93353b # v2.0.0
with:
project: ${{ secrets.KETRYX_PROJECT }}
project: ${{ vars.KETRYX_PROJECT }}
api-key: ${{ secrets.KETRYX_API_KEY }}
commit-sha: ${{ inputs.version == '' && inputs.commit-sha || '' }}
version: ${{ inputs.version }}
Expand Down
48 changes: 0 additions & 48 deletions .github/workflows/_package-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ on:
secrets:
UV_PUBLISH_TOKEN:
required: true
SLACK_WEBHOOK_URL_RELEASE_ANNOUNCEMENT:
required: true
SLACK_CHANNEL_ID_RELEASE_ANNOUNCEMENT:
required: true
SENTRY_AUTH_TOKEN:
required: true

env:
# https://gist.github.com/NodeJSmith/e7e37f2d3f162456869f015f842bcf15
Expand Down Expand Up @@ -222,48 +216,6 @@ jobs:
gh release create "$GH_REF_NAME" ./dist/* ./dist_native_zipped/* ./audit-results/* \
--notes-file "$GIT_CLIFF_CHANGELOG"

- name: Inform Sentry about release
uses: getsentry/action-release@6fb9aeade7061441cf3864e34fbe11a1457ad7dc # v3.7.1
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }}
with:
environment: production
release: ${{ github.ref_name }}

- name: Convert release notes from Markdown to Slack mrkdwn
shell: bash
env:
GIT_CLIFF_CONTENT: ${{ steps.git-cliff.outputs.content }}
run: |
# Convert Markdown links [text](url) to Slack mrkdwn <url|text>
# Convert bold **text** to *text*
NOTES_CONVERTED=$(printf '%s\n' "$GIT_CLIFF_CONTENT" | \
sed -E 's/\[([^]]+)\]\(([^)]+)\)/<\2|\1>/g' | \
sed -E 's/\*\*([^*]+)\*\*/*\1*/g')
RELEASE_URL="${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}"
if [ "$(printf '%s' "$NOTES_CONVERTED" | wc -c)" -gt 2700 ]; then
NOTES_TRUNCATED=$(printf '%s' "$NOTES_CONVERTED" | head -c 2700)
NOTES_CONVERTED="${NOTES_TRUNCATED}"$'\n'"...<${RELEASE_URL}|Read full release notes>"
fi
# JSON-escape: backslashes first, then double quotes, then collapse newlines to \n
NOTES=$(printf '%s' "$NOTES_CONVERTED" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
echo "SLACK_RELEASE_NOTES=$NOTES" >> "$GITHUB_ENV"

- name: Release Announcement
uses: slackapi/slack-github-action@dcb1066f776dd043e64d0e8ba94ca15cc7e1875d # v4.0.0
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL_RELEASE_ANNOUNCEMENT }}
webhook-type: webhook-trigger
payload: |
{
"repository": "${{ github.repository }}",
"version": "${{ steps.git-cliff.outputs.version }}",
"release_notes": "${{ env.SLACK_RELEASE_NOTES }}",
"channel_id": "${{ secrets.SLACK_CHANNEL_ID_RELEASE_ANNOUNCEMENT }}"
}

- name: Allow other workflows to trigger on release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
Loading
Loading