release-bot #15

Closed
ztimson wants to merge 0 commits from release-bot into master
Owner

Description

Created a bot to handle creating release notes when milestones are closed

Checklist

  • Reviewed changes (or use Review/AI label)
  • Updated comments/documentation
## Description <!-- Addition information & context --> Created a bot to handle creating release notes when milestones are closed ## Checklist <!-- Complete after creating PR --> - [x] Reviewed changes (or use `Review/AI` label) - [ ] Updated comments/documentation
ztimson added 2 commits 2026-01-14 15:48:41 -05:00
Added a release bot to create release notes from closed milestones
All checks were successful
Publish Library / Build NPM Project (push) Successful in 3s
Publish Library / Tag Version (push) Successful in 5s
72ffe3dcc7
Removed --no-cache, we are already using latest tag
All checks were successful
Publish Library / Build NPM Project (push) Successful in 3s
Publish Library / Tag Version (push) Successful in 5s
Code review / review (pull_request) Successful in 40s
e625782eec
ztimson added the
Review
AI
label 2026-01-14 15:49:20 -05:00
assistant reviewed 2026-01-14 15:49:55 -05:00
assistant left a comment
First-time contributor

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.

## 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 release
env:
AI_HOST: anthropic
AI_MODEL: claude-sonnet-4-5
First-time contributor

Typo 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.

Typo 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.
ztimson marked this conversation as resolved
@@ -0,0 +6,4 @@
dotenv.config({path: '.env.local', override: true, quiet: true, debug: false});
(async () => {
const git = process.env['GIT_HOST'],
First-time contributor

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.

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.
ztimson marked this conversation as resolved
@@ -0,0 +16,4 @@
token = process.env['AI_TOKEN'];
// Get milestone info
const milestoneData = await fetch(`${git}/api/v1/repos/${owner}/${repo}/milestones/${milestone}`, {
First-time contributor

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.

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.
ztimson marked this conversation as resolved
@@ -0,0 +31,4 @@
}).then(resp => resp.ok ? resp.json() : []);
// Get latest tag
const latestTag = await $`git describe --tags --abbrev=0`.text();
First-time contributor

The git describe command 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.

The `git describe` command 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.
First-time contributor

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.

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.
ztimson marked this conversation as resolved
@@ -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;
First-time contributor

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.

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.
ztimson marked this conversation as resolved
@@ -0,0 +61,4 @@
// Create release
const name = latestTag.trim();
await fetch(`${git}/api/v1/repos/${owner}/${repo}/releases`, {
First-time contributor

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.

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.
ztimson marked this conversation as resolved
src/release.mjs Outdated
@@ -0,0 +62,4 @@
// Create release
const name = latestTag.trim();
await fetch(`${git}/api/v1/repos/${owner}/${repo}/releases`, {
method: 'POST',
First-time contributor

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.

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.
ztimson added 1 commit 2026-01-14 15:56:13 -05:00
Added checks
All checks were successful
Publish Library / Build NPM Project (push) Successful in 4s
Publish Library / Tag Version (push) Successful in 16s
Code review / review (pull_request) Successful in 38s
8cfcb3f95c
assistant reviewed 2026-01-14 15:56:53 -05:00
assistant left a comment
First-time contributor

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.

## 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 release
env:
AI_HOST: anthropic
AI_MODEL: claude-sonnet-4-5
First-time contributor

Typo 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.

Typo 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 () => {
First-time contributor

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); }

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 info
First-time contributor

API 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.

API 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 tag
First-time contributor

The git describe command 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.

The `git describe` command 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;
First-time contributor

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;

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 release
const name = latestTag.trim();
First-time contributor

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.

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) });
First-time contributor

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}`)`

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}\`)`
ztimson closed this pull request 2026-01-14 15:57:05 -05:00
All checks were successful
Publish Library / Build NPM Project (push) Successful in 4s
Publish Library / Tag Version (push) Successful in 16s
Code review / review (pull_request) Successful in 38s

Pull request closed

Sign in to join this conversation.