|
| 1 | +# Opens (or updates) the [test-bot] issue for a failing scheduled run. |
| 2 | +# |
| 3 | +# Replaces JasonEtco/create-an-issue, which is still `using: node20`. Composite, so |
| 4 | +# it pulls in no Node runtime at all; `gh` and `jq` are preinstalled on the ubuntu, |
| 5 | +# macos and windows runners, and `shell: bash` gives Git Bash on windows. |
| 6 | +name: Report failure |
| 7 | +description: Open a [test-bot] issue for a failing scheduled run, or update the open one. |
| 8 | + |
| 9 | +inputs: |
| 10 | + title: |
| 11 | + description: Issue title. An open issue with this exact title is updated in place. |
| 12 | + required: true |
| 13 | + platform: |
| 14 | + description: Runner platform the failure was seen on. |
| 15 | + required: true |
| 16 | + python: |
| 17 | + description: Python environment label, e.g. `test11` or `py3.13, pip stable`. |
| 18 | + required: true |
| 19 | + token: |
| 20 | + description: Token carrying issues-write permission. Needed explicitly because checkout runs without persisted credentials. |
| 21 | + required: true |
| 22 | + |
| 23 | +runs: |
| 24 | + using: composite |
| 25 | + steps: |
| 26 | + - shell: bash |
| 27 | + # Every caller-supplied value goes through `env:` rather than `${{ }}` |
| 28 | + # interpolation into the script body, so nothing can be injected into it. |
| 29 | + env: |
| 30 | + GH_TOKEN: ${{ inputs.token }} |
| 31 | + TITLE: ${{ inputs.title }} |
| 32 | + PLATFORM: ${{ inputs.platform }} |
| 33 | + PYTHON: ${{ inputs.python }} |
| 34 | + run: | |
| 35 | + set -euo pipefail |
| 36 | +
|
| 37 | + # printf rather than a heredoc: a heredoc body inside this block scalar |
| 38 | + # would carry its YAML indentation into the issue text. |
| 39 | + body=$(printf '%s\n' \ |
| 40 | + "The ${GITHUB_WORKFLOW} workflow failed on $(date -u '+%Y-%m-%d %H:%M') UTC" \ |
| 41 | + "" \ |
| 42 | + "The most recent failing test was on ${PLATFORM} (${PYTHON})" \ |
| 43 | + "with commit: ${GITHUB_SHA}" \ |
| 44 | + "" \ |
| 45 | + "Full run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \ |
| 46 | + "" \ |
| 47 | + "(This post will be updated if another test fails, as long as this issue remains open.)") |
| 48 | +
|
| 49 | + # Match the title exactly rather than relying on `--search`, whose tokenizer |
| 50 | + # does not treat the leading "[test-bot]" as a literal. |
| 51 | + number=$(gh issue list --state open --label bug --limit 100 --json number,title \ |
| 52 | + | jq -r --arg t "${TITLE}" 'map(select(.title == $t)) | .[0].number // empty') |
| 53 | +
|
| 54 | + if [ -n "${number}" ]; then |
| 55 | + echo "Updating existing issue #${number}" |
| 56 | + gh issue edit "${number}" --body "${body}" |
| 57 | + else |
| 58 | + echo "Opening a new issue" |
| 59 | + gh issue create --title "${TITLE}" --label bug --body "${body}" |
| 60 | + fi |
0 commit comments