From f42dd9662887e7998c1486f0b3ef7a2ec14c458b Mon Sep 17 00:00:00 2001 From: foxhoundn Date: Wed, 4 Nov 2026 13:46:45 +0100 Subject: [PATCH] ci: no Qlip build on a develop push; restart pings on the main webhook A push to develop ran the story suite with QLIP_UPLOAD_TOKEN set, so every merge uploaded a Qlip build. The Qlip server promotes a merged PR's accepted baselines onto develop itself, so the next PR already diffs against them; the develop build only ever added an unowned pending build whose accepts moved a flaky capture onto trunk. The token is now set for a pull request only; the suite still runs on develop and, with no token, qlip captures without uploading. With no build on a develop push, the Discord message carried a "[Qlip visual tests]()" link to nowhere. qlip-build-link.sh now prints the whole link as `link=`, which is empty when no build was uploaded, and the messages use that. The "please do not restart Qorus on Rippy" warning and its "safe to restart" follow-up posted through the development channel's webhook and were a constant ping there. They use DISCORD_WEBHOOK now, like every other notification in the file. Version 0.10.71, the one bump this PR makes. Closes qoretechnologies/toolkit-react#158 Co-Authored-By: Claude Fable 5.1 --- .github/scripts/qlip-build-link.sh | 6 ++++-- .github/workflows/tests.yml | 20 +++++++++++++------- __tests__/qlipBuildLinkScript.test.ts | 14 ++++++++++---- package.json | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/.github/scripts/qlip-build-link.sh b/.github/scripts/qlip-build-link.sh index a1f92fc5..9b6ca8be 100755 --- a/.github/scripts/qlip-build-link.sh +++ b/.github/scripts/qlip-build-link.sh @@ -9,8 +9,9 @@ # from that line. It ends at the first space or colon: taking everything up to the space kept the colon, and the # link went to build `20261010-104435:`, which does not exist. # -# Prints GITHUB_OUTPUT lines `build_id=` and `url=` (the dashboard's builds are global: /builds/), or nothing -# when no build was uploaded. +# Prints GITHUB_OUTPUT lines `build_id=`, `url=` (the dashboard's builds are global: /builds/) and `link=` +# (the Discord message's "🔍 [Qlip visual tests](url)"), or nothing when no build was uploaded: a push to develop +# uploads none, and its message then simply has no link, instead of a `[Qlip visual tests]()` that goes nowhere. set -eu log=${1:?usage: qlip-build-link.sh } @@ -26,4 +27,5 @@ echo "Resolved qlip build='${build_id:-}' server='${server}'" >&2 if [ -n "$build_id" ]; then echo "build_id=$build_id" echo "url=$server/builds/$build_id" + echo "link=🔍 [Qlip visual tests]($server/builds/$build_id)" fi diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 80cfef10..5de7139a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,9 +25,13 @@ jobs: env: QORUS_TOKEN: ${{ secrets.QORUS_TOKEN }} REACT_APP_QORUS_TOKEN: ${{ secrets.QORUS_TOKEN }} - # Upload token for qlip visual snapshots (Storybook interaction tests). + # Upload token for qlip visual snapshots (Storybook interaction tests), + # for a pull request only. A push to develop runs the same suite but + # uploads nothing: the Qlip server promotes a merged PR's accepted + # baselines onto develop itself, so a develop build only ever added an + # unowned pending build whose accepts moved a flaky capture onto trunk. # When unset, qlip still captures snapshots but skips the upload. - QLIP_UPLOAD_TOKEN: ${{ secrets.QLIP_UPLOAD_TOKEN }} + QLIP_UPLOAD_TOKEN: ${{ github.event_name == 'pull_request' && secrets.QLIP_UPLOAD_TOKEN || '' }} # Steps represent a sequence of tasks that will be executed as part of the job steps: # Get current time for the commit @@ -98,10 +102,11 @@ jobs: with: node-version: 22.19.0 - # Notify Discord to not restart server + # Notify Discord to not restart server. The normal channel, like every other notification here: + # through the development channel's webhook this and "safe to restart" were a constant ping in the chat. - name: Discord Warning env: - DISCORD_WEBHOOK: ${{secrets.DISCORD_WEBHOOK_DEV}} + DISCORD_WEBHOOK: ${{secrets.DISCORD_WEBHOOK}} # Mention someone in the embeds DISCORD_EMBEDS: '[{ "color":16711680, "description": ":exclamation: Tests started, **please do not restart Qorus on Rippy** for the next 30 minutes." }]' DISCORD_AVATAR: "https://github.com/qoretechnologies/qorus-vscode/blob/95ad81fa8654fe83bb41f68f4de42ae088298e59/public/q-symbol-small.png?raw=true" @@ -139,6 +144,7 @@ jobs: # The qlip build this run uploaded, for the Discord message's link (qlip-build-link.sh reads it from # qlip's upload line). Runs even on test failure (qlip captures-on-error, so the build still exists). + # A push to develop uploads no build, and its message carries no link. - name: Resolve qlip build link id: qlip if: always() @@ -168,7 +174,7 @@ jobs: - name: Discord notification success env: DISCORD_WEBHOOK: ${{secrets.DISCORD_WEBHOOK}} - DISCORD_EMBEDS: '[{ "author": { "icon_url": "https://avatars.githubusercontent.com/${{ github.actor }}", "name": "${{ github.actor }}", "url": "https://github.com/${{github.actor}}" },"url": "https://github.com/${{github.repository}}/commit/${{github.sha}}","fields": [{ "name": "Commit Message", "value": "${{ steps.get_head_commit_message.outputs.HEAD_COMMIT_MESSAGE }}"},{ "name": "Repository", "value": "[${{github.event.repository.name}}](${{github.event.repository.clone_url}})", "inline": true },{ "name": "Branch", "value": "[${{github.ref_name}}](https://github.com/${{github.repository}}/pull/${{github.ref_name}})", "inline": true },{ "name": "Event", "value": "${{github.event_name}}", "inline": true },{ "name": "Author", "value": "[${{github.actor}}](https://github.com/${{github.actor}})", "inline": true },{ "name": "Job", "value": "${{github.job}}", "inline": true},{ "name": "Version", "value": "${{ steps.published.outputs.field }}", "inline": true},{ "name": "", "value": "🤖 [Github Action](https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}}) 🔍 [Qlip visual tests](${{ steps.qlip.outputs.url }})"}],"color":65280,"footer":{"text": "Published at ${{steps.current_time.outputs.readableTime}}"}}]' + DISCORD_EMBEDS: '[{ "author": { "icon_url": "https://avatars.githubusercontent.com/${{ github.actor }}", "name": "${{ github.actor }}", "url": "https://github.com/${{github.actor}}" },"url": "https://github.com/${{github.repository}}/commit/${{github.sha}}","fields": [{ "name": "Commit Message", "value": "${{ steps.get_head_commit_message.outputs.HEAD_COMMIT_MESSAGE }}"},{ "name": "Repository", "value": "[${{github.event.repository.name}}](${{github.event.repository.clone_url}})", "inline": true },{ "name": "Branch", "value": "[${{github.ref_name}}](https://github.com/${{github.repository}}/pull/${{github.ref_name}})", "inline": true },{ "name": "Event", "value": "${{github.event_name}}", "inline": true },{ "name": "Author", "value": "[${{github.actor}}](https://github.com/${{github.actor}})", "inline": true },{ "name": "Job", "value": "${{github.job}}", "inline": true},{ "name": "Version", "value": "${{ steps.published.outputs.field }}", "inline": true},{ "name": "", "value": "🤖 [Github Action](https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}}) ${{ steps.qlip.outputs.link }}"}],"color":65280,"footer":{"text": "Published at ${{steps.current_time.outputs.readableTime}}"}}]' DISCORD_AVATAR: "https://github.com/qoretechnologies/qorus-vscode/blob/95ad81fa8654fe83bb41f68f4de42ae088298e59/public/q-symbol-small.png?raw=true" uses: Ilshidur/action-discord@0.3.2 with: @@ -181,7 +187,7 @@ jobs: - name: Discord notification failure env: DISCORD_WEBHOOK: ${{secrets.DISCORD_WEBHOOK}} - DISCORD_EMBEDS: '[{ "author": { "icon_url": "https://avatars.githubusercontent.com/${{ github.actor }}", "name": "${{ github.actor }}", "url": "https://github.com/${{github.actor}}" },"url": "https://github.com/${{github.repository}}/commit/${{github.sha}}","fields": [{ "name": "Commit Message", "value": "${{ steps.get_head_commit_message.outputs.HEAD_COMMIT_MESSAGE }}"},{ "name": "Repository", "value": "[${{github.event.repository.name}}](${{github.event.repository.clone_url}})", "inline": true },{ "name": "Branch", "value": "[${{github.ref_name}}](https://github.com/${{github.repository}}/pull/${{github.ref_name}})", "inline": true },{ "name": "Event", "value": "${{github.event_name}}", "inline": true },{ "name": "Author", "value": "[${{github.actor}}](https://github.com/${{github.actor}})", "inline": true },{ "name": "Job", "value": "${{github.job}}", "inline": true },{ "name": "Version", "value": "${{ steps.published.outputs.field }}", "inline": true},{ "name": "", "value": "🤖 [Github Action](https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}}) 🔍 [Qlip visual tests](${{ steps.qlip.outputs.url }})"}],"color":16711680,"footer":{"text": "Published at ${{steps.current_time.outputs.readableTime}}"}}]' + DISCORD_EMBEDS: '[{ "author": { "icon_url": "https://avatars.githubusercontent.com/${{ github.actor }}", "name": "${{ github.actor }}", "url": "https://github.com/${{github.actor}}" },"url": "https://github.com/${{github.repository}}/commit/${{github.sha}}","fields": [{ "name": "Commit Message", "value": "${{ steps.get_head_commit_message.outputs.HEAD_COMMIT_MESSAGE }}"},{ "name": "Repository", "value": "[${{github.event.repository.name}}](${{github.event.repository.clone_url}})", "inline": true },{ "name": "Branch", "value": "[${{github.ref_name}}](https://github.com/${{github.repository}}/pull/${{github.ref_name}})", "inline": true },{ "name": "Event", "value": "${{github.event_name}}", "inline": true },{ "name": "Author", "value": "[${{github.actor}}](https://github.com/${{github.actor}})", "inline": true },{ "name": "Job", "value": "${{github.job}}", "inline": true },{ "name": "Version", "value": "${{ steps.published.outputs.field }}", "inline": true},{ "name": "", "value": "🤖 [Github Action](https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}}) ${{ steps.qlip.outputs.link }}"}],"color":16711680,"footer":{"text": "Published at ${{steps.current_time.outputs.readableTime}}"}}]' DISCORD_AVATAR: "https://github.com/qoretechnologies/qorus-vscode/blob/95ad81fa8654fe83bb41f68f4de42ae088298e59/public/q-symbol-small.png?raw=true" uses: Ilshidur/action-discord@0.3.2 with: @@ -190,7 +196,7 @@ jobs: - name: Discord notification safe to restart env: - DISCORD_WEBHOOK: ${{secrets.DISCORD_WEBHOOK_DEV}} + DISCORD_WEBHOOK: ${{secrets.DISCORD_WEBHOOK}} DISCORD_EMBEDS: '[{ "color":65280, "description": ":white_check_mark: Tests action finished. It is now safe to restart Qorus on Rippy." }]' DISCORD_AVATAR: "https://github.com/qoretechnologies/qorus-vscode/blob/95ad81fa8654fe83bb41f68f4de42ae088298e59/public/q-symbol-small.png?raw=true" uses: Ilshidur/action-discord@0.3.2 diff --git a/__tests__/qlipBuildLinkScript.test.ts b/__tests__/qlipBuildLinkScript.test.ts index 7d62e00a..fcf98680 100644 --- a/__tests__/qlipBuildLinkScript.test.ts +++ b/__tests__/qlipBuildLinkScript.test.ts @@ -47,6 +47,7 @@ describe('qlip-build-link.sh', () => { [ 'build_id=20261010-104435', 'url=https://qlip.qoretechnologies.com/builds/20261010-104435', + 'link=🔍 [Qlip visual tests](https://qlip.qoretechnologies.com/builds/20261010-104435)', ].join('\n') ); }); @@ -57,20 +58,25 @@ describe('qlip-build-link.sh', () => { '[qlip] uploaded build 20260629-123456 (12 fragments, 3 new) → https://qlip.example.com\n' ) ).toBe( - ['build_id=20260629-123456', 'url=https://qlip.example.com/builds/20260629-123456'].join('\n') + [ + 'build_id=20260629-123456', + 'url=https://qlip.example.com/builds/20260629-123456', + 'link=🔍 [Qlip visual tests](https://qlip.example.com/builds/20260629-123456)', + ].join('\n') ); }); - it('names no build when none was uploaded, or the stories never ran', () => { + it('names no build, and no link, when none was uploaded (a push to develop), or the stories never ran', () => { expect(resolveLink('[qlip] build 20261010-121512: 635 entries … → /local/screenshots\n')).toBe( '' ); expect(resolveLink()).toBe(''); }); - it('is what the tests workflow links', () => { + it('is what the tests workflow links, as the whole link so that no build means no link', () => { const tests = readFileSync(resolve(__dirname, '../.github/workflows/tests.yml'), 'utf8'); expect(tests).toContain('.github/scripts/qlip-build-link.sh qlip-output.log'); - expect(tests).toContain('[Qlip visual tests](${{ steps.qlip.outputs.url }})'); + expect(tests).toContain('${{ steps.qlip.outputs.link }}'); + expect(tests).not.toContain('[Qlip visual tests](${{ steps.qlip.outputs.url }})'); }); }); diff --git a/package.json b/package.json index 8e8dccef..c8c59570 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@qoretechnologies/reqraft", - "version": "0.10.70", + "version": "0.10.71", "description": "ReQraft is a collection of React components and hooks that are used across Qore Technologies' products made using the ReQore component library from Qore.", "main": "dist/index.js", "types": "dist/index.d.ts",