From e1718f03f681d293774e2894ba9b13d13e080fd7 Mon Sep 17 00:00:00 2001 From: Jack Misner Date: Wed, 21 Jan 2026 17:57:14 +0000 Subject: [PATCH 1/4] chore: prepare for v0.1.1 release --- package.json | 5 +- scripts/release.js | 115 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 scripts/release.js diff --git a/package.json b/package.json index cc2af0b..c4c7c95 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,10 @@ "lint:fix": "oxlint --fix", "format": "prettier --write \"src/**/*.{ts,tsx}\" \"__tests__/**/*.{ts,tsx}\"", "format:check": "prettier --check \"src/**/*.{ts,tsx}\" \"__tests__/**/*.{ts,tsx}\"", - "prepublishOnly": "npm run clean && npm run build && npm run test" + "prepublishOnly": "npm run clean && npm run build && npm run test", + "release:patch": "node scripts/release.js patch", + "release:minor": "node scripts/release.js minor", + "release:major": "node scripts/release.js major" }, "peerDependencies": { "react": ">=16.8.0" diff --git a/scripts/release.js b/scripts/release.js new file mode 100644 index 0000000..5fd9f50 --- /dev/null +++ b/scripts/release.js @@ -0,0 +1,115 @@ +#!/usr/bin/env node + +/** + * Release script that creates a release branch, bumps version, and pushes. + * + * Usage: node scripts/release.js + */ + +import { execSync } from 'child_process' +import { readFileSync } from 'fs' +import { fileURLToPath } from 'url' +import { dirname, join } from 'path' + +const __dirname = dirname(fileURLToPath(import.meta.url)) + +function run(cmd, options = {}) { + console.log(`$ ${cmd}`) + return execSync(cmd, { stdio: 'inherit', ...options }) +} + +function runCapture(cmd) { + return execSync(cmd, { encoding: 'utf-8' }).trim() +} + +function calculateNewVersion(current, type) { + const [major, minor, patch] = current.split('.').map(Number) + + switch (type) { + case 'major': + return `${major + 1}.0.0` + case 'minor': + return `${major}.${minor + 1}.0` + case 'patch': + return `${major}.${minor}.${patch + 1}` + default: + throw new Error(`Invalid version type: ${type}`) + } +} + +function getRemoteName() { + const remotes = runCapture('git remote').split('\n').filter(Boolean) + if (remotes.length === 0) { + console.error('āŒ No git remotes configured.') + process.exit(1) + } + // Prefer 'origin', otherwise use the first remote + return remotes.includes('origin') ? 'origin' : remotes[0] +} + +function main() { + const type = process.argv[2] + + if (!['patch', 'minor', 'major'].includes(type)) { + console.error('Usage: node scripts/release.js ') + process.exit(1) + } + + const remote = getRemoteName() + console.log(`šŸ“” Using remote: ${remote}`) + + // Read current version + const packagePath = join(__dirname, '..', 'package.json') + const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8')) + const currentVersion = packageJson.version + + // Calculate new version + const newVersion = calculateNewVersion(currentVersion, type) + const branchName = `release/${newVersion}` + + console.log(`\nšŸ“¦ Release: ${currentVersion} → ${newVersion}\n`) + + // Check we're on main + const currentBranch = runCapture('git branch --show-current') + if (currentBranch !== 'main') { + console.error(`āŒ Must be on main branch to create a release. Currently on: ${currentBranch}`) + process.exit(1) + } + + // Pull latest + console.log('šŸ“„ Pulling latest from main...') + run(`git pull ${remote} main`) + + // Stage and commit any uncommitted changes + const status = runCapture('git status --porcelain') + if (status) { + console.log('\nšŸ“ Staging and committing uncommitted changes...') + run('git add .') + run(`git commit -m "chore: prepare for v${newVersion} release"`) + } + + // Create release branch + console.log(`\n🌿 Creating branch: ${branchName}`) + run(`git checkout -b ${branchName}`) + + // Bump version + console.log(`\nšŸ“ Bumping version to ${newVersion}...`) + run(`npm version ${type}`) + + // Push branch and tags + console.log(`\nšŸš€ Pushing ${branchName} with tags...`) + run(`git push -u ${remote} ${branchName} --follow-tags`) + + console.log(` +āœ… Release branch created and pushed! + +Next steps: +1. Create a PR: https://github.com/jackmisner/utm-toolkit/compare/main...${branchName} +2. Merge the PR to main +3. The tag (v${newVersion}) will trigger the publish workflow + +Note: The npm publish will happen automatically when the tag is pushed. +`) +} + +main() From 37359a9d8fe57513489c279b998dfa2c278414fc Mon Sep 17 00:00:00 2001 From: Jack Misner Date: Wed, 21 Jan 2026 17:57:14 +0000 Subject: [PATCH 2/4] 0.1.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8be57d5..f256356 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@jackmisner/utm-toolkit", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@jackmisner/utm-toolkit", - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "devDependencies": { "@testing-library/react": "^16.0.0", diff --git a/package.json b/package.json index c4c7c95..ab8ed0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jackmisner/utm-toolkit", - "version": "0.1.0", + "version": "0.1.1", "description": "Capture, store, and append UTM tracking parameters", "type": "module", "main": "./dist/cjs/index.js", From 5df9faff18c326bd7deae36cc36f79eb7d90dae0 Mon Sep 17 00:00:00 2001 From: Jack Misner Date: Wed, 21 Jan 2026 18:09:50 +0000 Subject: [PATCH 3/4] fix node-version in publish.yml --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index aa72f59..b0e6c13 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -55,7 +55,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 24 registry-url: 'https://registry.npmjs.org' cache: 'npm' From ce8f39a54e1ea4ae687afc0335282fcdace24f1a Mon Sep 17 00:00:00 2001 From: Jack Misner Date: Wed, 21 Jan 2026 18:13:41 +0000 Subject: [PATCH 4/4] Release script now aborts if there are uncommitted changes, requiring you to manually review and commit first. --- scripts/release.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/release.js b/scripts/release.js index 5fd9f50..09eccdc 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -80,12 +80,15 @@ function main() { console.log('šŸ“„ Pulling latest from main...') run(`git pull ${remote} main`) - // Stage and commit any uncommitted changes + // Check for uncommitted changes const status = runCapture('git status --porcelain') if (status) { - console.log('\nšŸ“ Staging and committing uncommitted changes...') - run('git add .') - run(`git commit -m "chore: prepare for v${newVersion} release"`) + console.error(`āŒ Working directory has uncommitted changes. + +Please review and commit your changes before releasing v${newVersion}: +Then run the release command again. +`) + process.exit(1) } // Create release branch