| 71 | const issueTitle = (d: Drift) => `⬆️ Upgrade ${d.slug} to ${d.latest}`; |
| 72 | |
| 73 | function workOrder(d: Drift): string { |
| 74 | const edits = d.edits |
| 75 | .map((e) => `- \`${e.file}\`\n - \`${e.from}\` → \`${e.to}\``) |
| 76 | .join("\n"); |
| 77 | |
| 78 | return `**${d.name}** is on \`${d.current}\`; upstream released [\`${d.latest}\`](${d.releaseNotes})${ |
| 79 | d.releaseDate ? ` on ${d.releaseDate}` : "" |
| 80 | } (${d.severity} bump). |
| 81 | |
| 82 | ### Changes to apply |
| 83 | |
| 84 | ${edits} |
| 85 | |
| 86 | ${ |
| 87 | d.imageTag |
| 88 | ? `Container tag \`${d.imageTag}\` was verified to exist upstream.` |
| 89 | : `> [!WARNING]\n> No published container tag was found for this version. Confirm the image exists before doing anything else — a release without an image is not shippable.` |
| 90 | } |
| 91 | |
| 92 | ${d.warnings.length ? `### Warnings\n\n${d.warnings.map((w) => `- ${w}`).join("\n")}\n` : ""} |
| 93 | ### Required before merging |
| 94 | |
| 95 | A newer release is not evidence that the new version still works with our |
| 96 | compose file, our \`.env\` and our volumes. Establish a baseline first, then |
| 97 | prove the bump did not regress it: |
| 98 | |
| 99 | \`\`\`bash |
| 100 | # 1. baseline: does it pass today, before any change? |
| 101 | ./packages/scripts/maintenance/test-stack.sh ${d.slug} |
| 102 | |
| 103 | # 2. apply the edits above, then: |
| 104 | ./packages/scripts/maintenance/test-stack.sh ${d.slug} |
| 105 | \`\`\` |
| 106 | |
| 107 | The test pulls every image, waits for all services to become healthy, checks |
| 108 | that nothing crash-loops during a settle window, and makes a real HTTP request |
| 109 | to the app's entry point. |
| 110 | |
| 111 | - If the baseline fails too, this app was already broken: fix that first or say |
| 112 | so in the PR — it is not a regression from this bump. |
| 113 | - If the baseline passes and the bump fails, do **not** merge. Read the release |
| 114 | notes: a required new env var or a migration usually needs \`.env\` or |
| 115 | \`compose.yaml\` changes alongside the version. |
| 116 | - ${d.severity === "major" ? "This is a **major** bump: assume breaking changes and read the upgrade guide before touching anything." : "Attach the test output to the PR."} |
| 117 | |
| 118 | <sub>Filed automatically from \`work/version-drift.json\`.</sub>`; |
| 119 | } |
| 120 | |
| 121 | function main() { |
| 122 | const report = JSON.parse(readFileSync(REPORT, "utf-8")); |