artifacts-builder by jasonraimondi
Automates the release process for the ts-oauth2-server project.
Design
299 Stars
53 Forks
Updated Dec 5, 2025, 02:37 AM
Why Use This
This skill provides specialized capabilities for jasonraimondi's codebase.
Use Cases
- Developing new features in the jasonraimondi repository
- Refactoring existing code to follow jasonraimondi standards
- Understanding and working with jasonraimondi's codebase structure
Install Guide
2 steps- 1
Skip this step if Ananke is already installed.
- 2
Skill Snapshot
Auto scan of skill assets. Informational only.
Valid SKILL.md
Checks against SKILL.md specification
Source & Community
Skill Stats
SKILL.md 363 Lines
Total Files 1
Total Size 0 B
License Complete terms in LICENSE
---
name: artifacts-builder
description: Automates the release process for the ts-oauth2-server project.
license: Complete terms in LICENSE
---
# Release Creator Skill
## Purpose
Automates the release process for the ts-oauth2-server project by:
1. Bumping version numbers in both `package.json` and `jsr.json`
2. Generating changelog entries based on git commits since the last tagged version
3. Updating the CHANGELOG.md file with proper formatting
4. Maintaining Keep a Changelog format and Semantic Versioning compliance
## When to Use This Skill
Use this skill when the user requests:
- Creating a new release
- Bumping the version (patch, minor, major, premajor, preminor, prepatch, prerelease)
- Updating the changelog
- Preparing for a release
- Publishing a new version
## Prerequisites
- Git repository with commit history
- Existing tags for version tracking
- `package.json` and `jsr.json` files present
- `CHANGELOG.md` file exists
## Core Functionality
### Version Bump Types
Supported version bump types (following semver):
- **patch**: Bug fixes (1.0.0 → 1.0.1)
- **minor**: New features (1.0.0 → 1.1.0)
- **major**: Breaking changes (1.0.0 → 2.0.0)
- **prepatch**: Pre-release patch (1.0.0 → 1.0.1-0)
- **preminor**: Pre-release minor (1.0.0 → 1.1.0-0)
- **premajor**: Pre-release major (1.0.0 → 2.0.0-0)
- **prerelease**: Increment pre-release (1.0.0-0 → 1.0.0-1)
### Implementation Steps
#### 1. Get Current Version
```typescript
import { readFileSync } from 'fs';
function getCurrentVersion(): string {
const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
return pkg.version;
}
```
#### 2. Calculate New Version
```typescript
function bumpVersion(current: string, bumpType: string): string {
const parts = current.split('-');
const [major, minor, patch] = parts[0].split('.').map(Number);
const prerelease = parts[1];
switch (bumpType) {
case 'major':
return `${major + 1}.0.0`;
case 'minor':
return `${major}.${minor + 1}.0`;
case 'patch':
return `${major}.${minor}.${patch + 1}`;
case 'premajor':
return `${major + 1}.0.0-0`;
case 'preminor':
return `${major}.${minor + 1}.0-0`;
case 'prepatch':
return `${major}.${minor}.${patch + 1}-0`;
case 'prerelease':
if (prerelease) {
const num = parseInt(prerelease) || 0;
return `${parts[0]}-${num + 1}`;
}
return `${major}.${minor}.${patch + 1}-0`;
default:
throw new Error(`Invalid bump type: ${bumpType}`);
}
}
```
#### 3. Get Git Commits Since Last Tag
```bash
# Get the last tag
last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
# Get commits since last tag
if [ -z "$last_tag" ]; then
# No previous tag, get all commits
commits=$(git log --pretty=format:"%s" --no-merges)
else
# Get commits since last tag
commits=$(git log ${last_tag}..HEAD --pretty=format:"%s" --no-merges)
fi
```
#### 4. Categorize Commits
Parse commits and categorize them based on conventional commit format:
- `feat:` or `feature:` → Added section
- `fix:` → Fixed section
- `BREAKING CHANGE:` or `!:` → Changed section (breaking)
- `docs:` → Skip (or note in documentation)
- `chore:`, `refactor:`, `test:` → Skip or group under "Changed"
- `security:` → Security section
#### 5. Generate Changelog Entry
Follow Keep a Changelog format:
```markdown
## [Version] - YYYY-MM-DD
### Added
- New feature A
- New feature B
### Changed
- **BREAKING**: Changed behavior X
- Updated Y
### Fixed
- Fixed bug in Z
- Resolved issue with W
### Security
- Security fix for vulnerability V
```
#### 6. Update Files
Update both `package.json` and `jsr.json` with the new version, and prepend the new changelog entry to CHANGELOG.md under the `## [Unreleased]` section.
## Usage Examples
### Example 1: Patch Release
```typescript
// User request: "Create a patch release"
const currentVersion = "4.1.1";
const newVersion = "4.1.2";
// 1. Get commits since v4.1.1
// 2. Categorize commits
// 3. Generate changelog entry
// 4. Update package.json, jsr.json, CHANGELOG.md
```
### Example 2: Minor Release with Features
```typescript
// User request: "Bump minor version and update changelog"
const currentVersion = "4.1.1";
const newVersion = "4.2.0";
// Changelog generated from commits:
// - feat: Add new grant type support
// - feat: Enhance token validation
// - fix: Resolve refresh token issue
```
### Example 3: Major Release with Breaking Changes
```typescript
// User request: "Create major release for breaking changes"
const currentVersion = "4.1.1";
const newVersion = "5.0.0";
// Identify BREAKING CHANGE commits
// Place them under ### Changed section
```
## Implementation Script
Here's a complete implementation approach:
```typescript
interface ChangelogEntry {
added: string[];
changed: string[];
deprecated: string[];
removed: string[];
fixed: string[];
security: string[];
}
async function createRelease(bumpType: string): Promise<void> {
// 1. Read current version
const currentVersion = getCurrentVersion();
console.log(`Current version: ${currentVersion}`);
// 2. Calculate new version
const newVersion = bumpVersion(currentVersion, bumpType);
console.log(`New version: ${newVersion}`);
// 3. Get last tag and commits
const lastTag = await getLastTag();
const commits = await getCommitsSinceTag(lastTag);
console.log(`Found ${commits.length} commits since ${lastTag || 'beginning'}`);
// 4. Parse and categorize commits
const changelog = categorizeCommits(commits);
// 5. Generate changelog entry
const changelogEntry = generateChangelogEntry(newVersion, changelog);
console.log('Generated changelog entry');
// 6. Update files
await updatePackageJson(newVersion);
await updateJsrJson(newVersion);
await updateChangelog(changelogEntry);
console.log(`✓ Successfully prepared release ${newVersion}`);
console.log('Next steps:');
console.log(' 1. Review the changes');
console.log(' 2. Commit: git add -A && git commit -m "chore: release v' + newVersion + '"');
console.log(' 3. Tag: git tag v' + newVersion);
console.log(' 4. Push: git push && git push --tags');
}
function categorizeCommits(commits: string[]): ChangelogEntry {
const entry: ChangelogEntry = {
added: [],
changed: [],
deprecated: [],
removed: [],
fixed: [],
security: [],
};
for (const commit of commits) {
const lower = commit.toLowerCase();
if (lower.includes('breaking change') || lower.includes('!:')) {
entry.changed.push(commit.replace(/^[^:]+:\s*/, ''));
} else if (lower.startsWith('feat:') || lower.startsWith('feature:')) {
entry.added.push(commit.replace(/^[^:]+:\s*/, ''));
} else if (lower.startsWith('fix:')) {
entry.fixed.push(commit.replace(/^[^:]+:\s*/, ''));
} else if (lower.startsWith('security:')) {
entry.security.push(commit.replace(/^[^:]+:\s*/, ''));
} else if (lower.startsWith('deprecate:')) {
entry.deprecated.push(commit.replace(/^[^:]+:\s*/, ''));
} else if (lower.startsWith('remove:')) {
entry.removed.push(commit.replace(/^[^:]+:\s*/, ''));
}
// Skip chore, docs, test, refactor, style, etc.
}
return entry;
}
function generateChangelogEntry(version: string, changelog: ChangelogEntry): string {
const date = new Date().toISOString().split('T')[0];
let entry = `## [${version}] - ${date}\n\n`;
if (changelog.added.length > 0) {
entry += '### Added\n';
for (const item of changelog.added) {
entry += `- ${item}\n`;
}
entry += '\n';
}
if (changelog.changed.length > 0) {
entry += '### Changed\n';
for (const item of changelog.changed) {
entry += `- ${item}\n`;
}
entry += '\n';
}
if (changelog.deprecated.length > 0) {
entry += '### Deprecated\n';
for (const item of changelog.deprecated) {
entry += `- ${item}\n`;
}
entry += '\n';
}
if (changelog.removed.length > 0) {
entry += '### Removed\n';
for (const item of changelog.removed) {
entry += `- ${item}\n`;
}
entry += '\n';
}
if (changelog.fixed.length > 0) {
entry += '### Fixed\n';
for (const item of changelog.fixed) {
entry += `- ${item}\n`;
}
entry += '\n';
}
if (changelog.security.length > 0) {
entry += '### Security\n';
for (const item of changelog.security) {
entry += `- ${item}\n`;
}
entry += '\n';
}
return entry;
}
```
## Best Practices
1. **Always verify versions match**: Ensure package.json and jsr.json versions are in sync before and after bumping
2. **Review commits carefully**: Not all commits should appear in changelog
3. **Use conventional commits**: Encourage the team to use conventional commit format
4. **Breaking changes**: Always highlight breaking changes prominently
5. **Date format**: Use ISO date format (YYYY-MM-DD) for consistency
6. **Manual review**: Always review generated changelog before committing
## Error Handling
- **No git repository**: Warn user and exit gracefully
- **Uncommitted changes**: Warn user to commit or stash changes first
- **Invalid bump type**: Show available options and exit
- **Version mismatch**: If package.json and jsr.json versions don't match, warn user
- **No commits**: If no commits since last tag, warn user and ask if they want to proceed
## Output Format
The skill should provide clear feedback:
```
📦 Current version: 4.1.1
🔼 Bumping version: patch
📝 New version: 4.1.2
🔍 Found 5 commits since v4.1.1
📋 Categorized commits:
- Added: 2
- Fixed: 3
✍️ Generated changelog entry
✅ Updated package.json
✅ Updated jsr.json
✅ Updated CHANGELOG.md
✓ Successfully prepared release v4.1.2
Next steps:
1. Review the changes
2. Commit: git add -A && git commit -m "chore: release v4.1.2"
3. Tag: git tag v4.1.2
4. Push: git push && git push --tags
```
## Integration with Project
This skill respects the project's:
- Semantic versioning (as stated in CHANGELOG.md)
- Keep a Changelog format (as shown in existing CHANGELOG.md)
- Git workflow and tagging conventions
- Dual package manager support (npm and JSR)
## Notes
- The skill does NOT automatically commit, tag, or push changes
- It prepares all files for review before manual commit
- This allows the developer to review and adjust if needed
- The skill is idempotent - can be run multiple times safely
- ALWAYS Ensure package.json and jsr.json versions are in sync before and after bumping
Name Size