Skip to content
Draft
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
32 changes: 32 additions & 0 deletions .github/workflows/self-test-ci-summary.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI summary self-test

on:
# Doesn't execute untrusted PR code; worst case is a fork PR spending the
# bot's Copilot seat and getting a bot comment, which is an accepted risk.
workflow_run:
workflows:
- QA self-test
- Check policy
types:
- completed

permissions:
pull-requests: write
contents: read
actions: read

jobs:
triage:
if: ${{ github.event.workflow_run.event == 'pull_request' }}
runs-on: ubuntu-latest
steps:
- name: Fetch source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Run CI summary bot on itself
uses: $/ci-summary
with:
pr-number: ${{ github.event.workflow_run.pull_requests[0].number }}
github-token: ${{ secrets.CRAFT_BOT_TOKEN }}
6 changes: 6 additions & 0 deletions .github/zizmor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ rules:
# (e.g. quotes in `sudo env "PATH=$PATH"`) that would be mangled if
# passed through an environment variable instead.
- test-python.yaml
dangerous-triggers:
ignore:
# workflow_run here only reads completion status and posts a comment;
# it never checks out or executes PR code. Accepted risk: a fork PR
# can spend the bot's Copilot seat and get a bot-authored comment.
- self-test-ci-summary.yaml
43 changes: 43 additions & 0 deletions ci-summary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# `ci-summary`

Triages PR CI failures with an LLM and posts a sticky summary comment.

## Example usage

```yaml
name: CI summary
on:
workflow_run:
workflows:
- QA
- Spread
- Check policy
types: [completed]
jobs:
summary:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.event == 'pull_request' }}
steps:
- uses: canonical/starflow/ci-summary@main
with:
pr-number: ${{ github.event.workflow_run.pull_requests[0].number }}
github-token: ${{ secrets.CRAFT_BOT_TOKEN }}
```

## Inputs

### `pr-number`

Pull request number to analyze.

### `github-token`

Token for a bot account with a Copilot seat; `GITHUB_TOKEN` won't work since it has no seat.

### `model`

AI model name for triage reasoning. Defaults to `claude-haiku-5.5`.

### `dry-run`

When `true`, prints the markdown output without posting a comment. Defaults to `false`.
36 changes: 36 additions & 0 deletions ci-summary/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI Test Summary and Failure Triage
description: AI-driven failure triage and sticky comment summary for GitHub Actions CI

inputs:
pr-number:
description: Pull request number to analyze
required: true
github-token:
description: Token for a bot account with a Copilot seat (GITHUB_TOKEN has no seat and won't work)
required: true
model:
description: AI model name for triage reasoning
default: claude-haiku-5.5
required: false
dry-run:
description: When true, prints markdown output without posting a comment
default: "false"
required: false

runs:
using: composite
steps:
- name: Set up uv
uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
with:
enable-cache: true

- name: Run CI Summary Bot
shell: bash
env:
GH_TOKEN: ${{ inputs.github-token }}
AI_MODEL: ${{ inputs.model }}
DRY_RUN: ${{ inputs.dry-run }}
PR_NUMBER: ${{ inputs.pr-number }}
run: |
uv run --python 3.12 "${{ github.action_path }}/triage.py" --pr "$PR_NUMBER"
Loading