From 919dca3fae63aea1e9ad0c82ee5b9e26c445395a Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 11:21:23 +0100 Subject: [PATCH 1/8] add command to compose discord report message --- package.json | 1 + scripts/get-report-message.ts | 69 +++++++++++++++++++++++++++++++++++ scripts/package.json | 1 + 3 files changed, 71 insertions(+) create mode 100644 scripts/get-report-message.ts diff --git a/package.json b/package.json index bba2585efc35..f2bce525133b 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "start": "yarn task --task dev --template react-vite/default-ts --start-from=install", "task": "echo 'Installing Script Dependencies...'; cd scripts; yarn install >/dev/null; yarn task", "get-template": "cd scripts; yarn get-template", + "get-report-message": "cd scripts; yarn get-report-message", "test": "cd code; yarn test", "lint": "cd code; yarn lint", "nx": "cd code; yarn nx", diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts new file mode 100644 index 000000000000..7c0fdbc87fc7 --- /dev/null +++ b/scripts/get-report-message.ts @@ -0,0 +1,69 @@ +/* eslint-disable no-console */ +import { command } from 'execa'; +import { readJson } from 'fs-extra'; +import { join } from 'path'; + +type Branch = 'main' | 'next' | 'alpha'; +type Workflow = 'merged' | 'daily'; + +const getFooter = async (branch: Branch, workflow: Workflow, job: string) => { + if (job === 'chromatic-sandboxes') { + return `\n\nThis might not necessarily be a bug, it could be a visual diff that you have to review and approve. Please check it!`; + } + + if (branch === 'alpha') { + const packageJson = await readJson(join(__dirname, '..', 'code', 'package.json')); + + // running in alpha branch we should just show the version which failed + return `\n**Version: ${packageJson.version}**`; + } + + const mergeCommits = + workflow === 'merged' + ? // show single merge for merged workflow + `git log -1 --pretty=format:"\`%h\` %<(12)%ar %s [%an]"` + : // show last 24h merges for daily workflow + `git log --merges --since="24 hours ago" --pretty=format:"\`%h\` %<(12)%ar %s [%an]"`; + + const result = await command(mergeCommits, { shell: true }); + const formattedResult = result.stdout + // discord needs escaped line breaks + .replace(/\n/g, '\\n') + // make links out of pull request ids + .replace('Merge pull request #', 'https://github.com/storybookjs/storybook/pull/'); + + return `\n\n**Relevant PRs:**\n${formattedResult}`; +}; + +// This command is run in Circle CI on failures, to get a rich message to report to Discord +// Usage: yarn get-report-message type workflow branch +async function run() { + const [, , workflow = '', template = ''] = process.argv; + + if (!workflow || !template) { + throw new Error('[get-report-message] Missing workflow or template arguments.'); + } + + const { CIRCLE_BRANCH: currentBranch = '', CIRCLE_JOB: currentJob = '' } = process.env; + + if (!currentBranch || !currentJob) { + throw new Error( + '[get-report-message] Missing CIRCLE_BRANCH or CIRCLE_JOB environment variables.' + ); + } + + const title = `Oh no! The **${currentJob}** job has failed${ + template ? ` for **${template}**.` : '.' + }`; + const body = `\n\n**Branch**: ${currentBranch}\n**Workflow:** ${workflow}`; + const footer = await getFooter(currentBranch as Branch, workflow as Workflow, currentJob); + + console.log(`${title}${body}${footer}`); +} + +if (require.main === module) { + run().catch((err) => { + console.error(err); + process.exit(1); + }); +} diff --git a/scripts/package.json b/scripts/package.json index e7190c1c757e..335de76f9028 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -3,6 +3,7 @@ "version": "7.0.0-alpha.16", "private": true, "scripts": { + "get-report-message": "ts-node ./get-report-message.ts", "get-template": "ts-node ./get-template.ts", "lint": "yarn lint:js && yarn lint:md", "lint:js": "yarn lint:js:cmd . --quiet", From d1ea48068a88c9ca054f27214ff875eb0a893861 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 11:22:04 +0100 Subject: [PATCH 2/8] use report-workflow-on-failure on every CI job --- .circleci/config.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index beb44dd4dbff..31b91319ad56 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -176,30 +176,21 @@ commands: echo "Canceling workflow as previous step resulted in failure." echo "To execute all checks locally, please run yarn ci-tests" curl -X POST --header "Content-Type: application/json" "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}/cancel?circle-token=${WORKFLOW_CANCELER}" - list-recent-merges: - description: 'Lists the merge commits from the past 24 hours' - steps: - - run: - name: Listing merge commits from the past 24 hours - when: on_fail - command: | - git log --merges --since="24 hours ago" --pretty=format:"\`%h\` %<(12)%ar | %s [%an]" | grep "Merge pull request" | sed "s/Merge pull request #/https:\/\/github.com\/storybookjs\/storybook\/pull\//g" report-workflow-on-failure: description: 'Reports failures to discord' parameters: template: description: | - Which template to report in discord + Which template to report in discord. Applicable for parallel sandbox jobs type: string steps: - run: when: on_fail command: git fetch --unshallow - - list-recent-merges - discord/status: - only_for_branches: next,alpha + only_for_branches: main,next,alpha fail_only: true - failure_message: 'Oh no! The **$CIRCLE_JOB** job has failed for **<< parameters.template >>**.\n\n**Relevant PRs of the last 24h:**\n$(git log --merges --since="24 hours ago" --pretty=format:"\`%h\` %<(12)%ar %s [%an]" | grep "Merge pull request" | sed "s/Merge pull request #/https:\/\/github.com\/storybookjs\/storybook\/pull\//g" | tr "\\n" "\\\\n" | sed "s/\\\\/\\\\n/g")' + failure_message: $(yarn get-report-message << pipeline.parameters.workflow >> << parameters.template >>) jobs: build: executor: @@ -222,6 +213,7 @@ jobs: command: | cd code yarn local-registry --publish + - report-workflow-on-failure - save_cache: name: Save Yarn cache key: build-yarn-2-cache-v4--{{ checksum "code/yarn.lock" }}--{{ checksum "scripts/yarn.lock" }} @@ -274,6 +266,7 @@ jobs: rm -rf node_modules mkdir node_modules npx -p @storybook/bench@next sb-bench 'yarn install' --label cra + - report-workflow-on-failure - run: name: prep artifacts when: always @@ -314,6 +307,7 @@ jobs: rm -rf node_modules mkdir node_modules npx -p @storybook/bench@next sb-bench 'yarn install' --label react-vite + - report-workflow-on-failure - run: name: prep artifacts when: always @@ -335,6 +329,7 @@ jobs: command: | cd code yarn lint + - report-workflow-on-failure - cancel-workflow-on-failure check: executor: @@ -350,6 +345,7 @@ jobs: command: | yarn task --task check --start-from=auto --no-link --debug git diff --exit-code + - report-workflow-on-failure - cancel-workflow-on-failure script-unit-tests: executor: sb_node_16_browsers @@ -365,6 +361,7 @@ jobs: yarn test --coverage --ci - store_test_results: path: scripts/junit.xml + - report-workflow-on-failure - cancel-workflow-on-failure unit-tests: executor: @@ -386,6 +383,7 @@ jobs: root: . paths: - code/coverage + - report-workflow-on-failure - cancel-workflow-on-failure coverage: executor: @@ -401,6 +399,7 @@ jobs: command: | cd code yarn coverage + - report-workflow-on-failure chromatic-internal-storybooks: executor: class: medium @@ -416,6 +415,7 @@ jobs: cd code yarn storybook:ui:chromatic yarn storybook:blocks:chromatic + - report-workflow-on-failure - store_test_results: path: test-results ## new workflow @@ -527,6 +527,8 @@ jobs: - run: name: Running Chromatic command: yarn task --task chromatic --template $(yarn get-template << pipeline.parameters.workflow >> chromatic) --no-link --start-from=never --junit + - report-workflow-on-failure: + template: $(yarn get-template << pipeline.parameters.workflow >> chromatic) - store_test_results: path: test-results e2e-sandboxes: From 9435df0fe5aeb54cda300c2a46ed198bdab8fdc8 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 11:23:10 +0100 Subject: [PATCH 3/8] add artificial failure --- .circleci/config.yml | 2 +- code/lib/node-logger/src/index.test.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 31b91319ad56..31eee6e82009 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -188,7 +188,7 @@ commands: when: on_fail command: git fetch --unshallow - discord/status: - only_for_branches: main,next,alpha + only_for_branches: main,next,alpha,yann/improve-reporting-mechanism fail_only: true failure_message: $(yarn get-report-message << pipeline.parameters.workflow >> << parameters.template >>) jobs: diff --git a/code/lib/node-logger/src/index.test.ts b/code/lib/node-logger/src/index.test.ts index 40188dbc8ceb..9e6ff8c21357 100644 --- a/code/lib/node-logger/src/index.test.ts +++ b/code/lib/node-logger/src/index.test.ts @@ -8,6 +8,9 @@ jest.mock('npmlog', () => ({ })); describe('node-logger', () => { + it('should fail', () => { + expect(1).toBe(2); + }); it('should have an info method', () => { const message = 'information'; logger.info(message); From ebb64aa0bcf991e7cd90a89719b55390d3f2831f Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 11:31:23 +0100 Subject: [PATCH 4/8] add default value for template --- .circleci/config.yml | 1 + scripts/get-report-message.ts | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 31eee6e82009..aa77db2fde06 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -183,6 +183,7 @@ commands: description: | Which template to report in discord. Applicable for parallel sandbox jobs type: string + default: 'none' steps: - run: when: on_fail diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts index 7c0fdbc87fc7..de2dd05ea4f9 100644 --- a/scripts/get-report-message.ts +++ b/scripts/get-report-message.ts @@ -38,10 +38,10 @@ const getFooter = async (branch: Branch, workflow: Workflow, job: string) => { // This command is run in Circle CI on failures, to get a rich message to report to Discord // Usage: yarn get-report-message type workflow branch async function run() { - const [, , workflow = '', template = ''] = process.argv; + const [, , workflow = '', template = 'none'] = process.argv; - if (!workflow || !template) { - throw new Error('[get-report-message] Missing workflow or template arguments.'); + if (!workflow) { + throw new Error('[get-report-message] Missing workflow argument.'); } const { CIRCLE_BRANCH: currentBranch = '', CIRCLE_JOB: currentJob = '' } = process.env; @@ -53,7 +53,7 @@ async function run() { } const title = `Oh no! The **${currentJob}** job has failed${ - template ? ` for **${template}**.` : '.' + template !== 'none' ? ` for **${template}**.` : '.' }`; const body = `\n\n**Branch**: ${currentBranch}\n**Workflow:** ${workflow}`; const footer = await getFooter(currentBranch as Branch, workflow as Workflow, currentJob); From d120c2f3f71873a186c35ebbf5fb9e77dd67bd1d Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 11:45:14 +0100 Subject: [PATCH 5/8] format line breaks for discord message --- scripts/get-report-message.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts index de2dd05ea4f9..f46a0e9a2b4f 100644 --- a/scripts/get-report-message.ts +++ b/scripts/get-report-message.ts @@ -58,7 +58,7 @@ async function run() { const body = `\n\n**Branch**: ${currentBranch}\n**Workflow:** ${workflow}`; const footer = await getFooter(currentBranch as Branch, workflow as Workflow, currentJob); - console.log(`${title}${body}${footer}`); + console.log(`${title}${body}${footer}`.replace(/\n/g, '\\n')); } if (require.main === module) { From 9af77c935269e28d25d9f72a0007b14d3a022ae9 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 11:55:54 +0100 Subject: [PATCH 6/8] improve format --- scripts/get-report-message.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts index f46a0e9a2b4f..4a6c9f209e14 100644 --- a/scripts/get-report-message.ts +++ b/scripts/get-report-message.ts @@ -30,7 +30,7 @@ const getFooter = async (branch: Branch, workflow: Workflow, job: string) => { // discord needs escaped line breaks .replace(/\n/g, '\\n') // make links out of pull request ids - .replace('Merge pull request #', 'https://github.com/storybookjs/storybook/pull/'); + .replace(/Merge pull request #/g, 'https://github.com/storybookjs/storybook/pull/'); return `\n\n**Relevant PRs:**\n${formattedResult}`; }; @@ -55,7 +55,7 @@ async function run() { const title = `Oh no! The **${currentJob}** job has failed${ template !== 'none' ? ` for **${template}**.` : '.' }`; - const body = `\n\n**Branch**: ${currentBranch}\n**Workflow:** ${workflow}`; + const body = `\n\n**Branch**: \`${currentBranch}\`\n**Workflow:** ${workflow}`; const footer = await getFooter(currentBranch as Branch, workflow as Workflow, currentJob); console.log(`${title}${body}${footer}`.replace(/\n/g, '\\n')); From f707d71c90e25447f682276d4bfa24fe6d228752 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 15 Nov 2022 12:19:20 +0100 Subject: [PATCH 7/8] remove artificial failure --- .circleci/config.yml | 2 +- code/lib/node-logger/src/index.test.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index aa77db2fde06..7d0864c6dce3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -189,7 +189,7 @@ commands: when: on_fail command: git fetch --unshallow - discord/status: - only_for_branches: main,next,alpha,yann/improve-reporting-mechanism + only_for_branches: main,next,alpha fail_only: true failure_message: $(yarn get-report-message << pipeline.parameters.workflow >> << parameters.template >>) jobs: diff --git a/code/lib/node-logger/src/index.test.ts b/code/lib/node-logger/src/index.test.ts index 9e6ff8c21357..40188dbc8ceb 100644 --- a/code/lib/node-logger/src/index.test.ts +++ b/code/lib/node-logger/src/index.test.ts @@ -8,9 +8,6 @@ jest.mock('npmlog', () => ({ })); describe('node-logger', () => { - it('should fail', () => { - expect(1).toBe(2); - }); it('should have an info method', () => { const message = 'information'; logger.info(message); From fd15defb0dc0849be794015f8b598bc8bf2660d1 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 16 Nov 2022 12:51:24 +0100 Subject: [PATCH 8/8] update branch names for reporting checks --- .circleci/config.yml | 2 +- scripts/get-report-message.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7d0864c6dce3..2a79ad8a516e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -189,7 +189,7 @@ commands: when: on_fail command: git fetch --unshallow - discord/status: - only_for_branches: main,next,alpha + only_for_branches: main,next,next-release,latest-release fail_only: true failure_message: $(yarn get-report-message << pipeline.parameters.workflow >> << parameters.template >>) jobs: diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts index 4a6c9f209e14..28edcf1fe5a8 100644 --- a/scripts/get-report-message.ts +++ b/scripts/get-report-message.ts @@ -3,7 +3,7 @@ import { command } from 'execa'; import { readJson } from 'fs-extra'; import { join } from 'path'; -type Branch = 'main' | 'next' | 'alpha'; +type Branch = 'main' | 'next' | 'alpha' | 'next-release' | 'latest-release'; type Workflow = 'merged' | 'daily'; const getFooter = async (branch: Branch, workflow: Workflow, job: string) => { @@ -11,7 +11,8 @@ const getFooter = async (branch: Branch, workflow: Workflow, job: string) => { return `\n\nThis might not necessarily be a bug, it could be a visual diff that you have to review and approve. Please check it!`; } - if (branch === 'alpha') { + // The CI workflows can run on release branches and we should display the version number + if (branch === 'next-release' || branch === 'latest-release') { const packageJson = await readJson(join(__dirname, '..', 'code', 'package.json')); // running in alpha branch we should just show the version which failed