mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-24 23:22:38 +08:00
ci: Add additional alerts for CI failures (#37398)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
cubic-dev-ai[bot]
parent
691bf7bdfc
commit
a0585d84ba
+11
-5
@@ -805,14 +805,20 @@ Embargoed security work happens in `n8n-io/n8n-private`. `sec-sync-public-to-pri
|
||||
runs hourly there (and on `workflow_dispatch` with `force` for conflict recovery),
|
||||
mirroring public `master` and `1.x` into private with `reset --hard` +
|
||||
`--force-with-lease` — skipping a branch when private is ahead, ignoring `chore: Bundle`
|
||||
commits when judging "ahead". Fixes are never committed to private `master`/`1.x`
|
||||
directly: `ci-restrict-private-merges.yml` requires PRs into them to come from the
|
||||
long-lived integration branches `bundle/2.x` and `bundle/1.x` (a `bundle/2.x` merge is
|
||||
commits when judging "ahead". A skipped branch, or a hard failure, is reported to
|
||||
`#alerts-build`: a non-`chore: Bundle` commit on private `master`/`1.x` leaves the mirror
|
||||
stuck every hour until it is removed or a `force` dispatch overwrites it. Fixes are never
|
||||
committed to private `master`/`1.x` directly: `ci-restrict-private-merges.yml` requires
|
||||
PRs into them to come from the long-lived integration
|
||||
branches `bundle/2.x` and `bundle/1.x` (a `bundle/2.x` merge is
|
||||
backported to `bundle/1.x` by `util-backport-bundle.yml`). Once a bundle branch is merged
|
||||
into private `master`/`1.x` as a `chore: Bundle/*` PR, `sec-publish-fix.yml` /
|
||||
`sec-publish-fix-1x.yml` cherry-pick that commit onto a fresh branch in the public repo and
|
||||
open the PR there. That PR **must stay a single-parent squash** — the publish step is a bare
|
||||
`git cherry-pick` of `HEAD`, which aborts on a merge commit.
|
||||
`git cherry-pick` of `HEAD`, which aborts on a merge commit. A `chore: Bundle/*` PR whose
|
||||
*Required Checks* go red holds back every fix batched into it, so `ci-pull-requests.yml`
|
||||
posts to `#alerts-build` when that gate fails on a PR opened *from* `bundle/2.x` or
|
||||
`bundle/1.x` (link only, no PR title, since the branch is embargoed).
|
||||
|
||||
`sec-sync-bundle-branches.yml` keeps those branches current, daily plus whenever a PR is
|
||||
merged into one (and on `workflow_dispatch`). It **merges the base into** the bundle branch
|
||||
@@ -886,7 +892,7 @@ If notify is a step inside an existing checked-out job, skip the `checkout` and
|
||||
| `QBOT_SLACK_TOKEN` | QBot | Default — engineering / build / security |
|
||||
| `RELEASE_HELPER_SLACK_TOKEN` | Release Helper | `#releases` (C036AELNMV0) |
|
||||
|
||||
Adding a new channel requires inviting the bot first; the first run otherwise fails loudly with `not_in_channel`. Private-repo workflows (`sec-publish-fix*.yml`) need `QBOT_SLACK_TOKEN` set in `n8n-io/n8n-private`; the scripts themselves are mirrored by `sec-sync-public-to-private.yml`.
|
||||
Adding a new channel requires inviting the bot first; the first run otherwise fails loudly with `not_in_channel`. Private-repo workflows (`sec-publish-fix*.yml`, `sec-sync-public-to-private.yml`, and the bundle-PR alert in `ci-pull-requests.yml`) need `QBOT_SLACK_TOKEN` set in `n8n-io/n8n-private`; the scripts themselves are mirrored by `sec-sync-public-to-private.yml`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -412,6 +412,33 @@ jobs:
|
||||
mode: validate
|
||||
job-results: ${{ toJSON(needs) }}
|
||||
|
||||
# A red `chore: Bundle/*` PR blocks publishing every fix batched into it, so the
|
||||
# failure is announced instead of waiting to be noticed. Only fires in n8n-private,
|
||||
# where bundle branches exist.
|
||||
notify-bundle-pr-failure:
|
||||
name: Notify Slack on bundle PR failure
|
||||
needs: required-checks
|
||||
if: >-
|
||||
always() &&
|
||||
needs.required-checks.result == 'failure' &&
|
||||
(github.head_ref == 'bundle/2.x' || github.head_ref == 'bundle/1.x')
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
sparse-checkout: .github/scripts/slack
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Notify Slack
|
||||
env:
|
||||
SLACK_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
node .github/scripts/slack/notify.mjs \
|
||||
--channel '#alerts-build' \
|
||||
--text "<${PR_URL}|Required Checks failed on the ${HEAD_REF} PR> - the batched fixes stay unpublished until it is green."
|
||||
|
||||
# Posts a QA metrics comparison comment on the PR.
|
||||
# Runs after all checks so any job can emit metrics before this reports.
|
||||
post-qa-metrics-comment:
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
# Scheduled runs only sync if private is not ahead of public.
|
||||
# Manual runs always sync (for conflict recovery after failed cherry-pick).
|
||||
#
|
||||
# A skipped branch or a hard failure is reported to #alerts-build.
|
||||
#
|
||||
# The bundle/* integration branches are kept current by sec-sync-bundle-branches.yml.
|
||||
|
||||
name: 'Security: Sync from Public'
|
||||
@@ -44,6 +46,7 @@ jobs:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Sync master from public
|
||||
id: sync-master
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
FORCE: ${{ inputs.force }}
|
||||
@@ -56,9 +59,11 @@ jobs:
|
||||
if [ "$AHEAD_COUNT" -gt 0 ]; then
|
||||
if [ "$EVENT_NAME" = "schedule" ]; then
|
||||
echo "Private is $AHEAD_COUNT commit(s) ahead of public, skipping scheduled sync"
|
||||
echo "ahead_count=$AHEAD_COUNT" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
elif [ "$FORCE" != "true" ]; then
|
||||
echo "Private is $AHEAD_COUNT commit(s) ahead of public, skipping (force not enabled)"
|
||||
echo "ahead_count=$AHEAD_COUNT" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
else
|
||||
echo "Private is $AHEAD_COUNT commit(s) ahead of public, force syncing anyway"
|
||||
@@ -69,6 +74,7 @@ jobs:
|
||||
git push origin master --force-with-lease
|
||||
|
||||
- name: Sync 1.x from public
|
||||
id: sync-1x
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
FORCE: ${{ inputs.force }}
|
||||
@@ -82,9 +88,11 @@ jobs:
|
||||
if [ "$AHEAD_COUNT" -gt 0 ]; then
|
||||
if [ "$EVENT_NAME" = "schedule" ]; then
|
||||
echo "Private 1.x is $AHEAD_COUNT commit(s) ahead of public, skipping scheduled sync"
|
||||
echo "ahead_count=$AHEAD_COUNT" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
elif [ "$FORCE" != "true" ]; then
|
||||
echo "Private 1.x is $AHEAD_COUNT commit(s) ahead of public, skipping (force not enabled)"
|
||||
echo "ahead_count=$AHEAD_COUNT" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
else
|
||||
echo "Private 1.x is $AHEAD_COUNT commit(s) ahead of public, force syncing anyway"
|
||||
@@ -114,3 +122,37 @@ jobs:
|
||||
|
||||
echo "Missing: ${MISSING[*]} - dispatching Security: Sync Bundle Branches"
|
||||
gh workflow run sec-sync-bundle-branches.yml --ref master
|
||||
|
||||
- name: Notify Slack on failure
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }}
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
node .github/scripts/slack/notify.mjs \
|
||||
--channel '#alerts-build' \
|
||||
--text "<${RUN_URL}|Public → private sync failed>"
|
||||
|
||||
- name: Notify Slack on skipped sync
|
||||
continue-on-error: true
|
||||
if: ${{ !cancelled() && (steps.sync-master.outputs.ahead_count || steps.sync-1x.outputs.ahead_count) }}
|
||||
env:
|
||||
SLACK_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }}
|
||||
MASTER_AHEAD: ${{ steps.sync-master.outputs.ahead_count }}
|
||||
ONE_X_AHEAD: ${{ steps.sync-1x.outputs.ahead_count }}
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
run: |
|
||||
DETAILS=''
|
||||
if [ -n "$MASTER_AHEAD" ]; then
|
||||
DETAILS="master is $MASTER_AHEAD commit(s) ahead"
|
||||
fi
|
||||
if [ -n "$ONE_X_AHEAD" ]; then
|
||||
[ -z "$DETAILS" ] || DETAILS="$DETAILS, "
|
||||
DETAILS="${DETAILS}1.x is $ONE_X_AHEAD commit(s) ahead"
|
||||
fi
|
||||
|
||||
# Non-Bundle commits on private master/1.x keep the sync skipped until they are removed or force-synced
|
||||
node .github/scripts/slack/notify.mjs \
|
||||
--channel '#alerts-build' \
|
||||
--text "<${RUN_URL}|Public → private sync skipped>: ${DETAILS} of public. Re-run with force once resolved."
|
||||
|
||||
Reference in New Issue
Block a user