generated from ztimson/template
release-bot #15
Reference in New Issue
Block a user
Delete Branch "release-bot"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Created a bot to handle creating release notes when milestones are closed
Checklist
Review/AIlabel)Summary
Found 8 critical issues in the release-bot implementation. Main concerns: missing environment variable validation, silent API error handling, unhandled git command failures, missing import for
$template function, and inadequate error handling for release creation failures. The workflow also has a potential model name typo. The logic for using existing tags as release names may cause conflicts. These issues could result in silent failures or cryptic errors during execution.@@ -0,0 +18,4 @@run: npx -y @ztimson/ai-agents@latest releaseenv:AI_HOST: anthropicAI_MODEL: claude-sonnet-4-5Typo in AI_MODEL value: 'claude-sonnet-4-5' should likely be 'claude-sonnet-4' or 'claude-3-5-sonnet-20241022'. The current value may not be a valid model identifier.
@@ -0,0 +6,4 @@dotenv.config({path: '.env.local', override: true, quiet: true, debug: false});(async () => {const git = process.env['GIT_HOST'],Missing validation for required environment variables. The script will fail with cryptic errors if GIT_HOST, GIT_OWNER, GIT_REPO, GIT_TOKEN, or MILESTONE are not set. Add validation to provide clear error messages.
@@ -0,0 +16,4 @@token = process.env['AI_TOKEN'];// Get milestone infoconst milestoneData = await fetch(`${git}/api/v1/repos/${owner}/${repo}/milestones/${milestone}`, {API errors are silently swallowed by returning empty objects/arrays. If the fetch fails or returns an error, the script continues with empty data. Consider checking resp.status and throwing meaningful errors.
@@ -0,0 +31,4 @@}).then(resp => resp.ok ? resp.json() : []);// Get latest tagconst latestTag = await $`git describe --tags --abbrev=0`.text();The
git describecommand will fail if there are no tags in the repository. This should be wrapped in a try-catch or check if tags exist first to avoid unhandled errors.Missing import for the
$template literal function (appears to be from zx or similar). Add the necessary import statement at the top of the file.@@ -0,0 +57,4 @@system: `You are a release notes writer. Format the provided milestone info, PRs, and issues into clean, organized release notes. Use markdown with sections like "Features", "Bug Fixes", "Breaking Changes", etc. Be concise but informative. Include issue/PR numbers in format #123.`});const body = (await ai.chat(context)).pop().content;Using
pop()on the AI chat response assumes there's at least one element. If the AI returns an empty array, this will fail. Add a check or default value.@@ -0,0 +61,4 @@// Create releaseconst name = latestTag.trim();await fetch(`${git}/api/v1/repos/${owner}/${repo}/releases`, {Creating a release with the latest tag name will fail if that tag/release already exists. Consider using the milestone title or generating a new version number instead.
@@ -0,0 +62,4 @@// Create releaseconst name = latestTag.trim();await fetch(`${git}/api/v1/repos/${owner}/${repo}/releases`, {method: 'POST',The release creation failure only logs to console but doesn't exit with an error code. This means the workflow will show as successful even if the release wasn't created. Consider throwing an error or calling process.exit(1) on failure.
Sitrep
New release bot implementation looks functional but has several robustness issues. Main concerns: missing environment variable validation, silent API error handling, potential failure when reusing existing tag names, and likely typo in the Claude model identifier. The script needs better error handling and validation to prevent cryptic failures in production. The workflow integration and AI prompt design are solid.
@@ -0,0 +18,4 @@run: npx -y @ztimson/ai-agents@latest releaseenv:AI_HOST: anthropicAI_MODEL: claude-sonnet-4-5Typo in AI_MODEL value: 'claude-sonnet-4-5' should likely be 'claude-3-5-sonnet-20241022' or similar valid Anthropic model identifier. The current value may not be recognized by the API.
@@ -0,0 +6,4 @@dotenv.config({quiet: true, debug: false});dotenv.config({path: '.env.local', override: true, quiet: true, debug: false});(async () => {Add validation for required environment variables. The script will fail with cryptic errors if GIT_HOST, GIT_OWNER, GIT_REPO, GIT_TOKEN, or MILESTONE are not set. Consider adding checks like:
if (!git || !owner || !repo || !auth || !milestone) { console.error('Missing required environment variables'); process.exit(1); }@@ -0,0 +16,4 @@model = process.env['AI_MODEL'] || 'llama3',token = process.env['AI_TOKEN'];// Get milestone infoAPI errors are silently swallowed by returning empty objects/arrays. If the fetch fails or returns an error, the script continues with empty/invalid data. Consider checking resp.status and throwing meaningful errors instead of defaulting to empty values.
@@ -0,0 +31,4 @@headers: {'Authorization': `token ${auth}`}}).then(resp => resp.ok ? resp.json() : []);// Get latest tagThe
git describecommand will fail if there are no tags in the repository. While there's error handling below, the error message will be cryptic. Consider wrapping in try-catch specifically for this command to provide a clearer error message.@@ -0,0 +62,4 @@system: `You are a release notes writer. Format the provided milestone info, PRs, and issues into clean, organized release notes. Use markdown with sections like "Features", "Bug Fixes", "Breaking Changes", etc. Be concise but informative. Include issue/PR numbers in format #123.`});const body = (await ai.chat(context)).pop()?.content;Using
pop()on the AI chat response assumes there's at least one element. If the AI returns an empty array, this will return undefined and the check below will catch it, but consider using optional chaining or a more explicit check for clarity:const body = (await ai.chat(context))[0]?.content;@@ -0,0 +69,4 @@}// Create releaseconst name = latestTag.trim();Creating a release with the latest tag name will fail if that tag/release already exists. Consider checking if the release exists first, or use the milestone title to generate a new version number instead of reusing an existing tag.
@@ -0,0 +81,4 @@tag_name: name,body})}).then(resp => { if(!resp.ok) throw new Error(resp.status + ' ' + resp.statusText) });The release creation error is thrown but could provide more context. Consider including the response body in the error message to help debug API failures:
const errorBody = await resp.text(); throw new Error(\${resp.status} ${resp.statusText}: ${errorBody}`)`Pull request closed