From 48a32772f797469c1b5e46da4ac601190bad74f5 Mon Sep 17 00:00:00 2001 From: Aleksandr Kurlov Date: Thu, 13 Aug 2026 14:25:27 +0200 Subject: [PATCH 1/4] Add periodic Konflux retest --- .github/workflows/README.md | 46 +++--- .../periodic-retest-konflux-builds.yml | 148 ++++++++++++++++++ 2 files changed, 166 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/periodic-retest-konflux-builds.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 5c18c29f..57329385 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -59,51 +59,41 @@ jobs: workflow-ref: v1 ``` -## Auto retest failed Konflux builds +## Periodic retest failed Konflux builds ### Overview -When a Konflux build check fails on a pull request, this action will automatically post a `/retest ` comment to trigger a rebuild. It includes retry limits to prevent infinite retry loops and automatically cleans up old retest comments when new commits are pushed. +Periodically scans all open pull requests for failed Konflux build checks and posts a +`/retest ` comment to trigger a rebuild. Retries up to `max_retries` times +per check per commit, then stops. Old retest comments from previous commit cycles are +cleaned up automatically so the retry counter always reflects the current commit only. + +Add the `disable-konflux-auto-retest` label to a PR to opt it out of automatic retesting. ### All options | Input | Description | Required | Default | |-------|-------------|----------|---------| -| `max_retries` | Maximum number of retries for failed builds | No | `3` | -| `check_name_suffix` | Suffix to filter Konflux build check names (e.g., `-on-push`) | No | `-on-push` | -| `retest_command` | Command to trigger Konflux retest (e.g., /retest). Useful to use non default when OpenShift CI uses the same /retest syntax - prevents OpenShift CI from spamming comments saying it does not understand Konflux-specific retest commands. | No | `/retest` | - -## Detailed options - -- **Automatic Retesting**: Posts retest commands when Konflux builds fail -- **Configurable Retry Limit**: Set maximum retry attempts to prevent infinite loops -- **Auto-Cleanup**: Removes old retest comments when new commits are pushed -- **Filtered Checks**: Only retests checks matching a specific name suffix (e.g., `-on-push`) -- **Custom Retest Command**: Configure the command used to trigger retests (default: `/retest`) -- **Disable via Label**: Add the `disable-konflux-auto-retest` label to a PR to skip automatic retesting - +| `max_retries` | Maximum number of retries per failed check per commit | No | `3` | +| `check_name_suffix` | Suffix to filter Konflux check names (e.g. `-on-push`, `-on-pull-request`) | No | `-on-push` | +| `retest_command` | Comment body used to trigger a Konflux retest. Use a non-default value when OpenShift CI shares the same `/retest` syntax, to avoid cross-system noise. | No | `/retest` | +| `konflux_app_id` | GitHub App ID for Red Hat Konflux, used to filter check suites | No | `296509` | ### Usage -Add this to your repository's workflow file (e.g., `.github/workflows/konflux-auto-retest.yml`): +Create a workflow file in your repository (e.g. `.github/workflows/konflux-retest-periodic.yml`): ```yaml -name: Auto-retest Konflux Builds +name: Periodic Retest Failed Konflux Builds on: - check_run: - types: [completed] - pull_request: - types: [synchronize] + schedule: + - cron: '5,15,25,35,45,55 * * * *' # every 10 minutes + workflow_dispatch: jobs: - retest-failed-konflux-builds: - uses: stackrox/actions/.github/workflows/retest-konflux-builds.yml@v1 - permissions: - pull-requests: write - issues: write + retest: + uses: stackrox/actions/.github/workflows/periodic-retest-konflux-builds.yml@main with: - max_retries: 3 check_name_suffix: '-on-push' - retest_command: '/retest' ``` diff --git a/.github/workflows/periodic-retest-konflux-builds.yml b/.github/workflows/periodic-retest-konflux-builds.yml new file mode 100644 index 00000000..66d8ec99 --- /dev/null +++ b/.github/workflows/periodic-retest-konflux-builds.yml @@ -0,0 +1,148 @@ +# NOTE on `issues: write` permission: GitHub treats PR conversation comments as issue comments +# (both share the same /issues/{number}/comments API endpoint). +# The `pull-requests: write` permission only controls review-specific actions (approvals, review comments, dismissals). +# To post a plain comment in a PR conversation, `issues: write` is required. +name: Periodic Retest Failed Konflux Builds + +on: + workflow_call: + inputs: + max_retries: + description: 'Maximum number of retries per failed check per commit' + required: false + type: number + default: 3 + check_name_suffix: + description: 'Suffix to filter Konflux check names (e.g. -on-push, -on-pull-request)' + required: false + type: string + default: '-on-push' + retest_command: + description: 'Comment body used to trigger a Konflux retest' + required: false + type: string + default: '/retest' + konflux_app_id: + description: 'GitHub App ID for Red Hat Konflux, used to filter check suites' + required: false + type: number + default: 296509 + +jobs: + periodic-retest-failed-konflux-builds: + runs-on: ubuntu-latest + + permissions: + pull-requests: write + # We need `issues: write` permission to write conversation comments. + # See top of the file comment for `issues` and conversation comments explanation. + issues: write + # required for fetching checks data via GraphQL API + checks: read + # required for getting check's content + contents: read + + steps: + - name: Scan and retest failed Konflux builds + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MAX_RETRIES: ${{ inputs.max_retries }} + CHECK_NAME_SUFFIX: ${{ inputs.check_name_suffix }} + RETEST_COMMAND: ${{ inputs.retest_command }} + KONFLUX_APP_ID: ${{ inputs.konflux_app_id }} + run: | + set -euo pipefail + + echo "Starting periodic scan for failed Konflux builds..." + + # A single GraphQL query returns all open PRs with failed Konflux check names and + # the last commit time, avoiding per-PR gh-pr-checks calls. + # filterBy:{conclusions:[FAILURE]} only matches completed runs, so in-progress + # re-runs are naturally excluded. + # Konflux ignores /retest commands sent to already-running pipelines, so any duplicate + # comment posted between a /retest and Konflux picking it up is harmless. + # github.repository is expanded by GHA before the shell sees the string; single quotes + # are intentional for jq's $appId. + # shellcheck disable=SC2016 + PR_DATA=$(gh api graphql \ + -F appId="${KONFLUX_APP_ID}" \ + -f query='query($appId: Int!) { + search(query: "repo:${{ github.repository }} is:pr is:open -label:disable-konflux-auto-retest", type: ISSUE, first: 100) { + nodes { ... on PullRequest { number + commits(last: 1) { nodes { commit { + committedDate + # Filtered to a single app, usually 1 Konflux check suite per PR in practice; 10 is a safe ceiling. + checkSuites(first: 10, filterBy: {appId: $appId}) { nodes { + # Konflux exposes one check run per pipeline component; 50 covers even large repos. + checkRuns(first: 50, filterBy: {conclusions: [FAILURE]}) { nodes { + name + completedAt + }} + }} + }}} + }} + } + }' \ + --jq '[.data.search.nodes[] | { + pr: .number, + last_commit: .commits.nodes[0].commit.committedDate, + failed: [.commits.nodes[0].commit.checkSuites.nodes[].checkRuns.nodes[] + | select(.name | ltrimstr("Red Hat Konflux / ") | endswith("'"$CHECK_NAME_SUFFIX"'")) + | {name: (.name | ltrimstr("Red Hat Konflux / ")), completed_at: .completedAt}] + } | select(.failed | length > 0)]') + + PR_COUNT=$(echo "$PR_DATA" | jq 'length') + if [ "$PR_COUNT" -eq 0 ]; then + echo "No open PRs with failed Konflux checks found" + exit 0 + fi + + echo "Found $PR_COUNT PRs with failed Konflux checks" + + echo "$PR_DATA" | jq -c '.[]' | while read -r PR_ENTRY; do + PR_NUMBER=$(echo "$PR_ENTRY" | jq -r '.pr') + LAST_COMMIT_TIME=$(echo "$PR_ENTRY" | jq -r '.last_commit') + echo "" + echo "Processing PR #$PR_NUMBER (last commit: $LAST_COMMIT_TIME)..." + + echo "$PR_ENTRY" | jq -c '.failed[]' | while IFS= read -r CHECK_ENTRY; do + BASE_CHECK_NAME=$(echo "$CHECK_ENTRY" | jq -r '.name') + COMPLETED_AT=$(echo "$CHECK_ENTRY" | jq -r '.completed_at') + + if [ -z "$BASE_CHECK_NAME" ]; then + continue + fi + + echo " Found failed check: $BASE_CHECK_NAME (failed at: $COMPLETED_AT)" + + # Delete retest comments from previous commit cycles so they cannot be + # miscounted against the current commit's retry budget. + gh api --paginate "repos/${{ github.repository }}/issues/$PR_NUMBER/comments" \ + --jq '[.[] | select( + .user.login == "github-actions[bot]" and + (.body | contains("'"$RETEST_COMMAND $BASE_CHECK_NAME"'")) and + .created_at < "'"$LAST_COMMIT_TIME"'" + ) | .id] | .[]' | \ + while read -r COMMENT_ID; do + gh api -X DELETE "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" + done + + # Count retest comments posted since the last commit. + RETRY_COUNT="$(gh api --paginate "repos/${{ github.repository }}/issues/$PR_NUMBER/comments" \ + --jq '[.[] | select( + .user.login == "github-actions[bot]" and + (.body | contains("'"$RETEST_COMMAND $BASE_CHECK_NAME"'")) and + .created_at > "'"$LAST_COMMIT_TIME"'" + )] | length')" + + if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then + echo " Maximum retry limit ($MAX_RETRIES) reached for $BASE_CHECK_NAME on PR #$PR_NUMBER" + else + echo " Retrying $BASE_CHECK_NAME (attempt $((RETRY_COUNT + 1))/$MAX_RETRIES)" + gh pr comment "$PR_NUMBER" --repo ${{ github.repository }} --body "$RETEST_COMMAND $BASE_CHECK_NAME" + fi + done + done + + echo "" + echo "Periodic scan complete" From 26a5ab277638ae771a8f63b59d85f6227dde81d9 Mon Sep 17 00:00:00 2001 From: Aleksandr Kurlov Date: Mon, 24 Aug 2026 07:42:09 +0200 Subject: [PATCH 2/4] review --- .github/workflows/README.md | 5 +- .../periodic-retest-konflux-builds.yml | 120 +++++++++++++----- 2 files changed, 92 insertions(+), 33 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 57329385..da289462 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -75,9 +75,10 @@ Add the `disable-konflux-auto-retest` label to a PR to opt it out of automatic r | Input | Description | Required | Default | |-------|-------------|----------|---------| | `max_retries` | Maximum number of retries per failed check per commit | No | `3` | -| `check_name_suffix` | Suffix to filter Konflux check names (e.g. `-on-push`, `-on-pull-request`) | No | `-on-push` | +| `check_name_suffix` | Suffix to filter Konflux check names (after stripping the app name prefix). Only checks whose name ends with this suffix are retested — e.g. `-on-push` targets build checks and excludes snapshot/validation checks like `create-custom-snapshot` or `checks`. Leave empty to retest all failed Konflux checks. | No | `-on-push` | | `retest_command` | Comment body used to trigger a Konflux retest. Use a non-default value when OpenShift CI shares the same `/retest` syntax, to avoid cross-system noise. | No | `/retest` | | `konflux_app_id` | GitHub App ID for Red Hat Konflux, used to filter check suites | No | `296509` | +| `konflux_app_name_prefix` | Prefix of the GitHub App name used in Konflux check names, including the trailing separator. Varies by cluster — e.g. `Red Hat Konflux / ` for production, `Konflux Staging / ` for staging. | No | `Red Hat Konflux / ` | ### Usage @@ -93,7 +94,7 @@ on: jobs: retest: - uses: stackrox/actions/.github/workflows/periodic-retest-konflux-builds.yml@main + uses: stackrox/actions/.github/workflows/periodic-retest-konflux-builds.yml@v1 with: check_name_suffix: '-on-push' ``` diff --git a/.github/workflows/periodic-retest-konflux-builds.yml b/.github/workflows/periodic-retest-konflux-builds.yml index 66d8ec99..ec9bb107 100644 --- a/.github/workflows/periodic-retest-konflux-builds.yml +++ b/.github/workflows/periodic-retest-konflux-builds.yml @@ -1,5 +1,5 @@ # NOTE on `issues: write` permission: GitHub treats PR conversation comments as issue comments -# (both share the same /issues/{number}/comments API endpoint). +# (both share the same /issues/{number}/comments API endpoint). # The `pull-requests: write` permission only controls review-specific actions (approvals, review comments, dismissals). # To post a plain comment in a PR conversation, `issues: write` is required. name: Periodic Retest Failed Konflux Builds @@ -13,7 +13,11 @@ on: type: number default: 3 check_name_suffix: - description: 'Suffix to filter Konflux check names (e.g. -on-push, -on-pull-request)' + description: > + Suffix to filter Konflux check names (after stripping the app name prefix). + Only checks whose name ends with this suffix are retested — e.g. use '-on-push' + to target build checks and exclude snapshot/validation checks like + 'create-custom-snapshot' or 'checks'. Leave empty to retest all failed Konflux checks. required: false type: string default: '-on-push' @@ -27,6 +31,17 @@ on: required: false type: number default: 296509 + konflux_app_name_prefix: + description: > + Prefix of the GitHub App name used in Konflux check names, including the trailing separator. + Varies by cluster — e.g. 'Red Hat Konflux / ' for production, 'Konflux Staging / ' for staging. + required: false + type: string + default: 'Red Hat Konflux / ' + +concurrency: + group: periodic-retest-konflux-${{ github.repository }} + cancel-in-progress: false jobs: periodic-retest-failed-konflux-builds: @@ -50,47 +65,81 @@ jobs: CHECK_NAME_SUFFIX: ${{ inputs.check_name_suffix }} RETEST_COMMAND: ${{ inputs.retest_command }} KONFLUX_APP_ID: ${{ inputs.konflux_app_id }} + KONFLUX_APP_NAME_PREFIX: ${{ inputs.konflux_app_name_prefix }} run: | set -euo pipefail echo "Starting periodic scan for failed Konflux builds..." - # A single GraphQL query returns all open PRs with failed Konflux check names and + # Reject decimal or negative values: Bash [ -ge ] silently misbehaves on decimals + # and GraphQL Int! rejects non-integers. + if ! [[ "$MAX_RETRIES" =~ ^[1-9][0-9]*$ ]]; then + echo "Error: max_retries must be a positive integer, got: $MAX_RETRIES" + exit 1 + fi + if ! [[ "$KONFLUX_APP_ID" =~ ^[1-9][0-9]*$ ]]; then + echo "Error: konflux_app_id must be a positive integer, got: $KONFLUX_APP_ID" + exit 1 + fi + + # A paginated GraphQL query returns all open PRs with failed Konflux check names and # the last commit time, avoiding per-PR gh-pr-checks calls. # filterBy:{conclusions:[FAILURE]} only matches completed runs, so in-progress # re-runs are naturally excluded. # Konflux ignores /retest commands sent to already-running pipelines, so any duplicate # comment posted between a /retest and Konflux picking it up is harmless. - # github.repository is expanded by GHA before the shell sees the string; single quotes - # are intentional for jq's $appId. - # shellcheck disable=SC2016 - PR_DATA=$(gh api graphql \ - -F appId="${KONFLUX_APP_ID}" \ - -f query='query($appId: Int!) { - search(query: "repo:${{ github.repository }} is:pr is:open -label:disable-konflux-auto-retest", type: ISSUE, first: 100) { - nodes { ... on PullRequest { number - commits(last: 1) { nodes { commit { - committedDate - # Filtered to a single app, usually 1 Konflux check suite per PR in practice; 10 is a safe ceiling. - checkSuites(first: 10, filterBy: {appId: $appId}) { nodes { - # Konflux exposes one check run per pipeline component; 50 covers even large repos. - checkRuns(first: 50, filterBy: {conclusions: [FAILURE]}) { nodes { - name - completedAt + # ${{ github.repository }} is expanded by GHA before the shell sees the string; + # \$appId is a GraphQL variable, not a shell variable. + ALL_PR_DATA="[]" + AFTER_CURSOR="" + HAS_NEXT_PAGE="true" + + while [ "$HAS_NEXT_PAGE" = "true" ]; do + AFTER_ARG="" + [ -n "$AFTER_CURSOR" ] && AFTER_ARG=", after: \"$AFTER_CURSOR\"" + + # shellcheck disable=SC2016 + PAGE_RESULT=$(gh api graphql \ + -F appId="${KONFLUX_APP_ID}" \ + -f query="query(\$appId: Int!) { + search(query: \"repo:${{ github.repository }} is:pr is:open -label:disable-konflux-auto-retest\", type: ISSUE, first: 100${AFTER_ARG}) { + pageInfo { hasNextPage endCursor } + nodes { ... on PullRequest { number + commits(last: 1) { nodes { commit { + oid + committedDate + # Filtered to a single app, usually 1 Konflux check suite per PR in practice; 10 is a safe ceiling. + checkSuites(first: 10, filterBy: {appId: \$appId}) { nodes { + # Konflux exposes one check run per pipeline component; 50 covers even large repos. + checkRuns(first: 50, filterBy: {conclusions: [FAILURE]}) { nodes { + name + completedAt + }} }} - }} - }}} - }} - } - }' \ - --jq '[.data.search.nodes[] | { - pr: .number, - last_commit: .commits.nodes[0].commit.committedDate, - failed: [.commits.nodes[0].commit.checkSuites.nodes[].checkRuns.nodes[] - | select(.name | ltrimstr("Red Hat Konflux / ") | endswith("'"$CHECK_NAME_SUFFIX"'")) - | {name: (.name | ltrimstr("Red Hat Konflux / ")), completed_at: .completedAt}] - } | select(.failed | length > 0)]') + }}} + }} + } + }") + + HAS_NEXT_PAGE=$(echo "$PAGE_RESULT" | jq -r '.data.search.pageInfo.hasNextPage') + AFTER_CURSOR=$(echo "$PAGE_RESULT" | jq -r '.data.search.pageInfo.endCursor // ""') + + PAGE_PR_DATA=$(echo "$PAGE_RESULT" | jq \ + --arg suffix "$CHECK_NAME_SUFFIX" \ + --arg prefix "$KONFLUX_APP_NAME_PREFIX" \ + '[.data.search.nodes[] | { + pr: .number, + head_sha: .commits.nodes[0].commit.oid, + last_commit: .commits.nodes[0].commit.committedDate, + failed: [.commits.nodes[0].commit.checkSuites.nodes[].checkRuns.nodes[] + | select(.name | ltrimstr($prefix) | endswith($suffix)) + | {name: (.name | ltrimstr($prefix)), completed_at: .completedAt}] + } | select(.failed | length > 0)]') + + ALL_PR_DATA=$(jq -n --argjson a "$ALL_PR_DATA" --argjson b "$PAGE_PR_DATA" '$a + $b') + done + PR_DATA="$ALL_PR_DATA" PR_COUNT=$(echo "$PR_DATA" | jq 'length') if [ "$PR_COUNT" -eq 0 ]; then echo "No open PRs with failed Konflux checks found" @@ -102,9 +151,18 @@ jobs: echo "$PR_DATA" | jq -c '.[]' | while read -r PR_ENTRY; do PR_NUMBER=$(echo "$PR_ENTRY" | jq -r '.pr') LAST_COMMIT_TIME=$(echo "$PR_ENTRY" | jq -r '.last_commit') + SNAPSHOT_HEAD=$(echo "$PR_ENTRY" | jq -r '.head_sha') echo "" echo "Processing PR #$PR_NUMBER (last commit: $LAST_COMMIT_TIME)..." + # Revalidate the PR head before mutating comments: a new commit since the query + # snapshot means the failed checks are stale and must not be retested. + CURRENT_HEAD=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER" --jq '.head.sha') + if [ "$CURRENT_HEAD" != "$SNAPSHOT_HEAD" ]; then + echo " PR #$PR_NUMBER head changed since snapshot (was: $SNAPSHOT_HEAD, now: $CURRENT_HEAD), skipping" + continue + fi + echo "$PR_ENTRY" | jq -c '.failed[]' | while IFS= read -r CHECK_ENTRY; do BASE_CHECK_NAME=$(echo "$CHECK_ENTRY" | jq -r '.name') COMPLETED_AT=$(echo "$CHECK_ENTRY" | jq -r '.completed_at') From 1adfee869389df9e1047f0f5a8fd23e4ee22416b Mon Sep 17 00:00:00 2001 From: Aleksandr Kurlov Date: Mon, 24 Aug 2026 08:07:18 +0200 Subject: [PATCH 3/4] derive prefix --- .github/workflows/README.md | 4 ++-- .../periodic-retest-konflux-builds.yml | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index da289462..4594f73c 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -77,8 +77,7 @@ Add the `disable-konflux-auto-retest` label to a PR to opt it out of automatic r | `max_retries` | Maximum number of retries per failed check per commit | No | `3` | | `check_name_suffix` | Suffix to filter Konflux check names (after stripping the app name prefix). Only checks whose name ends with this suffix are retested — e.g. `-on-push` targets build checks and excludes snapshot/validation checks like `create-custom-snapshot` or `checks`. Leave empty to retest all failed Konflux checks. | No | `-on-push` | | `retest_command` | Comment body used to trigger a Konflux retest. Use a non-default value when OpenShift CI shares the same `/retest` syntax, to avoid cross-system noise. | No | `/retest` | -| `konflux_app_id` | GitHub App ID for Red Hat Konflux, used to filter check suites | No | `296509` | -| `konflux_app_name_prefix` | Prefix of the GitHub App name used in Konflux check names, including the trailing separator. Varies by cluster — e.g. `Red Hat Konflux / ` for production, `Konflux Staging / ` for staging. | No | `Red Hat Konflux / ` | +| `konflux_app_id` | GitHub App ID for Red Hat Konflux, used to filter check suites. The app name is resolved automatically from this ID via the GitHub API. | No | `296509` | ### Usage @@ -96,5 +95,6 @@ jobs: retest: uses: stackrox/actions/.github/workflows/periodic-retest-konflux-builds.yml@v1 with: + max_retries: 3 check_name_suffix: '-on-push' ``` diff --git a/.github/workflows/periodic-retest-konflux-builds.yml b/.github/workflows/periodic-retest-konflux-builds.yml index ec9bb107..e9378d94 100644 --- a/.github/workflows/periodic-retest-konflux-builds.yml +++ b/.github/workflows/periodic-retest-konflux-builds.yml @@ -31,14 +31,6 @@ on: required: false type: number default: 296509 - konflux_app_name_prefix: - description: > - Prefix of the GitHub App name used in Konflux check names, including the trailing separator. - Varies by cluster — e.g. 'Red Hat Konflux / ' for production, 'Konflux Staging / ' for staging. - required: false - type: string - default: 'Red Hat Konflux / ' - concurrency: group: periodic-retest-konflux-${{ github.repository }} cancel-in-progress: false @@ -65,7 +57,6 @@ jobs: CHECK_NAME_SUFFIX: ${{ inputs.check_name_suffix }} RETEST_COMMAND: ${{ inputs.retest_command }} KONFLUX_APP_ID: ${{ inputs.konflux_app_id }} - KONFLUX_APP_NAME_PREFIX: ${{ inputs.konflux_app_name_prefix }} run: | set -euo pipefail @@ -93,6 +84,7 @@ jobs: ALL_PR_DATA="[]" AFTER_CURSOR="" HAS_NEXT_PAGE="true" + APP_PREFIX="" while [ "$HAS_NEXT_PAGE" = "true" ]; do AFTER_ARG="" @@ -110,6 +102,7 @@ jobs: committedDate # Filtered to a single app, usually 1 Konflux check suite per PR in practice; 10 is a safe ceiling. checkSuites(first: 10, filterBy: {appId: \$appId}) { nodes { + app { name } # Konflux exposes one check run per pipeline component; 50 covers even large repos. checkRuns(first: 50, filterBy: {conclusions: [FAILURE]}) { nodes { name @@ -124,9 +117,17 @@ jobs: HAS_NEXT_PAGE=$(echo "$PAGE_RESULT" | jq -r '.data.search.pageInfo.hasNextPage') AFTER_CURSOR=$(echo "$PAGE_RESULT" | jq -r '.data.search.pageInfo.endCursor // ""') + # Derive the app name prefix from the first check suite found in this page. + # All suites are from the same app (filtered by appId), so the first one suffices. + if [ -z "$APP_PREFIX" ]; then + FOUND_APP_NAME=$(echo "$PAGE_RESULT" | jq -r \ + '[.data.search.nodes[].commits.nodes[0].commit.checkSuites.nodes[].app.name] | first // ""') + [ -n "$FOUND_APP_NAME" ] && APP_PREFIX="${FOUND_APP_NAME} / " + fi + PAGE_PR_DATA=$(echo "$PAGE_RESULT" | jq \ --arg suffix "$CHECK_NAME_SUFFIX" \ - --arg prefix "$KONFLUX_APP_NAME_PREFIX" \ + --arg prefix "$APP_PREFIX" \ '[.data.search.nodes[] | { pr: .number, head_sha: .commits.nodes[0].commit.oid, From 43791df2b05de5dc83614661c277ae708bbc5d3b Mon Sep 17 00:00:00 2001 From: Aleksandr Kurlov Date: Mon, 24 Aug 2026 08:08:03 +0200 Subject: [PATCH 4/4] flip konflux non conforma filter --- .github/workflows/README.md | 5 +++-- .../workflows/periodic-retest-konflux-builds.yml | 16 +++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 4594f73c..71995e9a 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -75,7 +75,7 @@ Add the `disable-konflux-auto-retest` label to a PR to opt it out of automatic r | Input | Description | Required | Default | |-------|-------------|----------|---------| | `max_retries` | Maximum number of retries per failed check per commit | No | `3` | -| `check_name_suffix` | Suffix to filter Konflux check names (after stripping the app name prefix). Only checks whose name ends with this suffix are retested — e.g. `-on-push` targets build checks and excludes snapshot/validation checks like `create-custom-snapshot` or `checks`. Leave empty to retest all failed Konflux checks. | No | `-on-push` | +| `check_name_exclude_pattern` | Regex pattern matched against Konflux check names (after stripping the app name prefix). Matching checks are skipped. Leave empty to retest all failed checks. | No | `conforma` | | `retest_command` | Comment body used to trigger a Konflux retest. Use a non-default value when OpenShift CI shares the same `/retest` syntax, to avoid cross-system noise. | No | `/retest` | | `konflux_app_id` | GitHub App ID for Red Hat Konflux, used to filter check suites. The app name is resolved automatically from this ID via the GitHub API. | No | `296509` | @@ -96,5 +96,6 @@ jobs: uses: stackrox/actions/.github/workflows/periodic-retest-konflux-builds.yml@v1 with: max_retries: 3 - check_name_suffix: '-on-push' + check_name_exclude_pattern: 'conforma' + retest_command: '/konflux-retest' ``` diff --git a/.github/workflows/periodic-retest-konflux-builds.yml b/.github/workflows/periodic-retest-konflux-builds.yml index e9378d94..d8d5af59 100644 --- a/.github/workflows/periodic-retest-konflux-builds.yml +++ b/.github/workflows/periodic-retest-konflux-builds.yml @@ -12,15 +12,13 @@ on: required: false type: number default: 3 - check_name_suffix: + check_name_exclude_pattern: description: > - Suffix to filter Konflux check names (after stripping the app name prefix). - Only checks whose name ends with this suffix are retested — e.g. use '-on-push' - to target build checks and exclude snapshot/validation checks like - 'create-custom-snapshot' or 'checks'. Leave empty to retest all failed Konflux checks. + Regex pattern (jq `test()`) matched against Konflux check names after stripping the app + name prefix. Matching checks are skipped. Leave empty to retest all failed checks. required: false type: string - default: '-on-push' + default: 'conforma' retest_command: description: 'Comment body used to trigger a Konflux retest' required: false @@ -54,7 +52,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MAX_RETRIES: ${{ inputs.max_retries }} - CHECK_NAME_SUFFIX: ${{ inputs.check_name_suffix }} + CHECK_NAME_EXCLUDE_PATTERN: ${{ inputs.check_name_exclude_pattern }} RETEST_COMMAND: ${{ inputs.retest_command }} KONFLUX_APP_ID: ${{ inputs.konflux_app_id }} run: | @@ -126,14 +124,14 @@ jobs: fi PAGE_PR_DATA=$(echo "$PAGE_RESULT" | jq \ - --arg suffix "$CHECK_NAME_SUFFIX" \ + --arg exclude "$CHECK_NAME_EXCLUDE_PATTERN" \ --arg prefix "$APP_PREFIX" \ '[.data.search.nodes[] | { pr: .number, head_sha: .commits.nodes[0].commit.oid, last_commit: .commits.nodes[0].commit.committedDate, failed: [.commits.nodes[0].commit.checkSuites.nodes[].checkRuns.nodes[] - | select(.name | ltrimstr($prefix) | endswith($suffix)) + | select(.name | ltrimstr($prefix) | if $exclude == "" then true else test($exclude) | not end) | {name: (.name | ltrimstr($prefix)), completed_at: .completedAt}] } | select(.failed | length > 0)]')