Repository navigation
Report triage #63
Workflow file for this run
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
| # .github/workflows/release-triage.yml | |
| # | |
| # Manual triage for freeze week / release promotions. | |
| # Actions tab -> "Report triage" -> Run workflow -> type the release tag. | |
| # Creates ONE Taiga user story tagged "release-<tag>" containing one task | |
| # per failure cluster. Re-running with the same tag adds only NEW clusters | |
| # to the SAME story (no duplicates) thanks to the per-release state file. | |
| # Tick close_only to sweep and close resolved tasks instead, without filing anything new. | |
| name: Report triage | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: 'Release tag (e.g. 2.17) — story will be tagged release-<tag>' | |
| required: true | |
| report_run_id: | |
| description: 'Override: specific run id to triage (default: last scheduled daily run on main)' | |
| required: false | |
| group_by: | |
| description: 'Task granularity inside the release story. folder: snapshot failures bundled per immediate parent folder (claimable per-folder for splitting snapshot-update work); functional bugs stay one-per-cluster' | |
| required: false | |
| default: 'cluster' | |
| type: choice | |
| options: | |
| - cluster | |
| - file | |
| - folder | |
| epic_ref: | |
| description: 'Optional: Taiga epic ref (number only, e.g. 118) to link the story under' | |
| required: false | |
| reset_state: | |
| description: 'Reset this release tag: forget all previous triage state (delete the old story in Taiga yourself first)' | |
| required: false | |
| default: false | |
| type: boolean | |
| close_only: | |
| description: 'Close-only sweep: close tasks whose error is no longer failing — files nothing new. Do not combine with reset_state.' | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: read | |
| actions: read # required for gh run list | |
| jobs: | |
| triage: | |
| runs-on: ubuntu-latest | |
| environment: PRE # grants access to MATTERMOST_WEBHOOK_DAILY_REPORT (environment secret) | |
| steps: | |
| - name: Reject reset_state + close_only together | |
| if: ${{ inputs.reset_state == true && inputs.close_only == true }} | |
| run: | | |
| echo "reset_state wipes triage state right before close_only would need it to find what's resolved — pick one." >&2 | |
| exit 1 | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v6 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ secrets.AWS_REGION }} | |
| - name: Resolve report to triage | |
| id: report | |
| run: | | |
| if [ -n "${{ inputs.report_run_id }}" ]; then | |
| RUN_ID="${{ inputs.report_run_id }}" | |
| echo "Using manually provided run: $RUN_ID" | |
| else | |
| # Last finished *scheduled* daily run on main (completed, not success: | |
| # the test step fails the workflow on failing nights by design) | |
| RUN_ID=$(gh run list \ | |
| --workflow "$DAILY_WORKFLOW" \ | |
| --branch main \ | |
| --event schedule \ | |
| --status completed \ | |
| --limit 1 \ | |
| --json databaseId \ | |
| --jq '.[0].databaseId') | |
| if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then | |
| echo "No completed scheduled daily run found on main"; exit 1 | |
| fi | |
| echo "Using last scheduled daily run on main: $RUN_ID" | |
| fi | |
| echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" | |
| aws s3 cp "s3://kaleidos-qa-reports/run-$RUN_ID/results.json" results.json | |
| aws s3 cp "s3://kaleidos-qa-reports/run-$RUN_ID-enterprise/results.json" results-enterprise.json 2>/dev/null \ | |
| && echo "Found enterprise results for this run — will be triaged alongside the standard suite." \ | |
| || echo "No enterprise results for this run (older run, or the enterprise job didn't run/upload) — triaging standard suite only." | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| DAILY_WORKFLOW: playwright_pre_daily.yml # "Daily Penpot Regression Tests on PRE" | |
| - name: Fetch app version for this run | |
| id: appver | |
| run: | | |
| VERSION=$(aws s3 cp "s3://kaleidos-qa-reports/run-${{ steps.report.outputs.run_id }}/app-version.txt" - 2>/dev/null || echo "") | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "App version for this run: ${VERSION:-<not recorded>}" | |
| - name: Reset per-release triage state | |
| if: ${{ inputs.reset_state == true }} | |
| run: | | |
| aws s3 rm "s3://kaleidos-qa-reports/triage/state-release-${{ inputs.release_tag }}.json" || echo "no state to delete" | |
| echo "State for release ${{ inputs.release_tag }} reset — all failures will be treated as new." | |
| - name: Pull per-release triage state | |
| run: | | |
| mkdir -p .triage | |
| aws s3 cp "s3://kaleidos-qa-reports/triage/state-release-${{ inputs.release_tag }}.json" \ | |
| .triage/state.json || echo "first triage for this release" | |
| - name: Run report triage | |
| run: | | |
| CLOSE_ONLY_FLAG="" | |
| if [ "${{ inputs.close_only }}" = "true" ]; then | |
| CLOSE_ONLY_FLAG="--close-only" | |
| echo "Close-only sweep: closing resolved tasks, filing nothing new." | |
| fi | |
| ENTERPRISE_RESULTS_FLAG="" | |
| if [ -f results-enterprise.json ]; then | |
| ENTERPRISE_RESULTS_FLAG="--results results-enterprise.json" | |
| fi | |
| npx tsx scripts/triage.ts \ | |
| --results results.json \ | |
| $ENTERPRISE_RESULTS_FLAG \ | |
| --state .triage/state.json \ | |
| --release "${{ inputs.release_tag }}" \ | |
| --group-by "${{ inputs.group_by || 'cluster' }}" \ | |
| --epic-ref "${{ inputs.epic_ref }}" \ | |
| --app-version "${{ steps.appver.outputs.version }}" \ | |
| --run-id "${{ steps.report.outputs.run_id }}" \ | |
| --report-url "https://kaleidos-qa-reports.s3.eu-west-1.amazonaws.com/run-${{ steps.report.outputs.run_id }}/index.html" \ | |
| $CLOSE_ONLY_FLAG | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} # raises GitHub API rate limit for the app-repo changelog fetch | |
| # APP_REPO: penpot/penpot # default; override if the app repo moves | |
| TAIGA_CLOSE_ASSIGNEE: qa.integrations.bot # resolved tasks are assigned to this user when auto-closed | |
| # TAIGA_CLOSED_STATUS: Closed # default; override if the project's closed task status is named differently | |
| TAIGA_URL: ${{ secrets.TAIGA_URL }} # https://api.taiga.io on Taiga cloud | |
| TAIGA_PUBLIC_URL: ${{ vars.TAIGA_PUBLIC_URL }} # https://tree.taiga.io — used for links in the digest | |
| TAIGA_USERNAME: ${{ secrets.TAIGA_USERNAME }} | |
| TAIGA_PASSWORD: ${{ secrets.TAIGA_PASSWORD }} | |
| TAIGA_PROJECT: ${{ vars.TAIGA_PROJECT }} | |
| TAIGA_TAGS: 'needs-triage' # release-<tag> is added automatically | |
| MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_DAILY_REPORT }} # PRE environment secret -> Autotests Reports channel | |
| # DRY_RUN: "1" | |
| - name: Push per-release triage state | |
| if: always() | |
| run: | | |
| if [ -f .triage/state.json ]; then | |
| aws s3 cp .triage/state.json \ | |
| "s3://kaleidos-qa-reports/triage/state-release-${{ inputs.release_tag }}.json" | |
| else | |
| echo "No state file to push (dry run leaves no trace)" | |
| fi | |
| - name: Digest to job summary | |
| if: always() | |
| run: cat .triage/digest.md >> "$GITHUB_STEP_SUMMARY" |