Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/cut-patch-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,23 @@ jobs:
--color 0E8A16 \
--description "Backport this fix to release/v$VERSION" \
--force

# Post an immediate "branch cut" card so the team is notified the moment the
# patch branch exists, without waiting ~20-40 min for notify-release-feishu to
# finish the prerelease build. The download card still follows from that build.
# feishu-notice.ts only imports node:crypto, so the setup-node above suffices.
- name: Notify Feishu that the branch was cut
if: steps.guard.outputs.published == 'true'
env:
FEISHU_WEBHOOK: ${{ secrets.FEISHU_RELEASE_WEBHOOK }}
FEISHU_SIGN_SECRET: ${{ secrets.FEISHU_RELEASE_SIGN_SECRET }}
NOTICE_TITLE: "🌿 已切出 release 分支 v${{ steps.ver.outputs.version }}(小版本 patch)"
NOTICE_TEMPLATE: "green"
NOTICE_BODY: |
**分支**:[`release/v${{ steps.ver.outputs.version }}`](${{ github.server_url }}/${{ github.repository }}/tree/release/v${{ steps.ver.outputs.version }})(从 main 切出,小版本 / patch)

**Backport label**:`backport release/v${{ steps.ver.outputs.version }}` —— 要回灌到这个版本的修复,给 PR 打这个 label。

Prerelease 打包已开始(约 20–40 分钟);完成后会再发一张带各平台下载链接的卡片。
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: node --experimental-strip-types tools/release/src/notifications/feishu-notice.ts
20 changes: 20 additions & 0 deletions .github/workflows/cut-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,23 @@ jobs:
--color 0E8A16 \
--description "Backport this fix to release/v$VERSION" \
--force

# Post an immediate "branch cut" card so the team is notified the moment the
# release branch exists, without waiting ~20-40 min for notify-release-feishu
# to finish the prerelease build. The download card still follows from that
# build. feishu-notice.ts only imports node:crypto, so the setup-node above
# is all it needs.
- name: Notify Feishu that the branch was cut
env:
FEISHU_WEBHOOK: ${{ secrets.FEISHU_RELEASE_WEBHOOK }}
FEISHU_SIGN_SECRET: ${{ secrets.FEISHU_RELEASE_SIGN_SECRET }}
NOTICE_TITLE: "🌿 已切出 release 分支 v${{ steps.ver.outputs.version }}(大版本 minor)"
NOTICE_TEMPLATE: "green"
NOTICE_BODY: |
**分支**:[`release/v${{ steps.ver.outputs.version }}`](${{ github.server_url }}/${{ github.repository }}/tree/release/v${{ steps.ver.outputs.version }})(从 main 切出,大版本 / minor)

**Backport label**:`backport release/v${{ steps.ver.outputs.version }}` —— 要回灌到这个版本的修复,给 PR 打这个 label。

Prerelease 打包已开始(约 20–40 分钟);完成后会再发一张带各平台下载链接的卡片。
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: node --experimental-strip-types tools/release/src/notifications/feishu-notice.ts
33 changes: 33 additions & 0 deletions e2e/tests/packaged-smoke-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const packagedPackageJsonPath = join(workspaceRoot, "apps", "packaged", "package
const scopesScriptPath = join(workspaceRoot, "scripts", "scopes.ts");
const runnersScriptPath = join(workspaceRoot, ".github", "scripts", "runners.py");
const notifyDailyFeishuWorkflowPath = join(workspaceRoot, ".github", "workflows", "notify-daily-feishu.yml");
const cutReleaseWorkflowPath = join(workspaceRoot, ".github", "workflows", "cut-release.yml");
const cutPatchReleaseWorkflowPath = join(workspaceRoot, ".github", "workflows", "cut-patch-release.yml");
const feishuNoticeScriptPath = join(workspaceRoot, "tools", "release", "src", "notifications", "feishu-notice.ts");
const landingPageDailyFeishuWorkflowPath = join(workspaceRoot, ".github", "workflows", "landing-page-daily-feishu.yml");
Expand Down Expand Up @@ -1401,6 +1402,38 @@ process.stdin.on("end", () => {
expect(notice).toContain('required("NOTICE_BODY")');
});

it("[P2] posts an immediate branch-cut Feishu card naming the backport label on both cut workflows", async () => {
// Cutting a release branch triggers a ~20-40 min prerelease build before the
// download card lands, so both cut workflows post an eager "branch cut" notice
// the moment the branch exists. Each must: reuse feishu-notice.ts, run AFTER the
// branch push + label creation, and name the exact backport label so the team
// knows which label to apply for backports.
const [minorCut, patchCut] = await Promise.all([
readFile(cutReleaseWorkflowPath, "utf8"),
readFile(cutPatchReleaseWorkflowPath, "utf8"),
]);

for (const [label, workflow, kind] of [
["cut-release (minor)", minorCut, "大版本 minor"],
["cut-patch-release (patch)", patchCut, "小版本 patch"],
] as const) {
const step = sectionBetween(workflow, "- name: Notify Feishu that the branch was cut", "\n run:");
// Same standalone notifier + the shared release webhook/secret.
expect(workflow, label).toContain("run: node --experimental-strip-types tools/release/src/notifications/feishu-notice.ts");
expect(step, label).toContain("FEISHU_WEBHOOK: ${{ secrets.FEISHU_RELEASE_WEBHOOK }}");
// Names the version's backport label in the card body.
expect(step, label).toContain("backport release/v${{ steps.ver.outputs.version }}");
// Distinguishes major vs minor cut.
expect(step, label).toContain(kind);
// The eager card must come AFTER the branch is actually cut + pushed.
expect(workflow.indexOf("- name: Notify Feishu that the branch was cut"), label)
.toBeGreaterThan(workflow.indexOf('git push origin "$BRANCH"'));
}
// The patch workflow's eager card only fires on the happy (published) path.
const patchNotice = sectionBetween(patchCut, "- name: Notify Feishu that the branch was cut", "\n run:");
expect(patchNotice).toContain("if: steps.guard.outputs.published == 'true'");
});

it("[P2] sends the daily landing PR summary to Feishu with staging deployment status", async () => {
const [workflow, productionWorkflow, script] = await Promise.all([
readFile(landingPageDailyFeishuWorkflowPath, "utf8"),
Expand Down
Loading