Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Release and Publish

on:
push:
branches: [release]

permissions:
contents: write
packages: write
issues: write
pull-requests: write
id-token: write # Required for npm provenance via OIDC

# Two releases racing on the same branch would fight over tags and the
# changelog commit.
concurrency:
group: release
cancel-in-progress: false

jobs:
release:
name: semantic-release
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
issues: write
pull-requests: write
id-token: write

steps:
- name: Checkout
uses: actions/checkout@v4
with:
# semantic-release reads the full tag history to work out the next
# version.
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

# The test suite drives real `git` against temporary repositories, and
# runners have no identity configured.
- name: Configure git identity
run: |
git config --global user.email "ci@example.com"
git config --global user.name "CI"
git config --global init.defaultBranch main

- uses: pnpm/action-setup@v4
with:
# Matches the packageManager field in package.json.
version: 8.15.0

- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
cache: pnpm

# Trusted publishing needs npm >= 11.5.1; the runner ships an older one.
# No NPM_TOKEN is used anywhere — auth comes from the OIDC id-token above,
# which requires a trusted publisher configured for this package on
# npmjs.com pointing at this repository and this workflow file.
- name: Upgrade npm for OIDC support
run: npm install -g npm@latest

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Lint
run: pnpm run lint

- name: Build
run: pnpm run build

- name: Test
run: pnpm exec vitest run

- name: Read version before release
id: before
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"

- name: Release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HUSKY: "0" # Git hooks must not run on the automated changelog commit

# semantic-release is a no-op when a push contains only non-releasing
# commit types (chore, docs, ci, test). Comparing the version tells us
# whether anything was actually published, so the mirror below does not
# try to republish an existing version and fail with a 409.
- name: Detect whether a release happened
id: released
run: |
AFTER=$(node -p "require('./package.json').version")
if [ "$AFTER" != "${{ steps.before.outputs.version }}" ]; then
echo "published=true" >> "$GITHUB_OUTPUT"
echo "version=$AFTER" >> "$GITHUB_OUTPUT"
echo "Released $AFTER"
else
echo "published=false" >> "$GITHUB_OUTPUT"
echo "No release for this push"
fi

- name: Setup Node for GitHub Packages
if: steps.released.outputs.published == 'true'
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://npm.pkg.github.com
scope: "@juspay"

- name: Mirror to GitHub Packages
if: steps.released.outputs.published == 'true'
run: pnpm publish --access public --no-git-checks --registry https://npm.pkg.github.com
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57 changes: 57 additions & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"branches": ["release"],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits",
"releaseRules": [
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "revert", "release": "patch" },
{ "type": "docs", "release": false },
{ "type": "style", "release": false },
{ "type": "refactor", "release": "patch" },
{ "type": "test", "release": false },
{ "type": "build", "release": "patch" },
{ "type": "ci", "release": false },
{ "type": "chore", "release": false },
{ "breaking": true, "release": "major" }
],
"parserOpts": {
"headerPattern": "^(?:\\w+-\\d+:\\s*)?(\\w+!?)(\\([\\w\\$\\.\\-\\*\\s]*\\))?\\s*:(.*)$",
"headerCorrespondence": ["type", "scope", "subject"],
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"]
}
}
],
[
"@semantic-release/release-notes-generator",
{
"preset": "conventionalcommits",
"parserOpts": {
"headerPattern": "^(?:\\w+-\\d+:\\s*)?(\\w+!?)(\\([\\w\\$\\.\\-\\*\\s]*\\))?\\s*:(.*)$",
"headerCorrespondence": ["type", "scope", "subject"],
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"]
}
}
],
"@semantic-release/changelog",
[
"@semantic-release/npm",
{
"npmPublish": true,
"provenance": true
}
],
"@semantic-release/github",
[
"@semantic-release/git",
{
"assets": ["CHANGELOG.md", "package.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
]
}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changelog

Released versions are cut automatically by
[semantic-release](https://semantic-release.gitbook.io/) from the commit
messages on `release`. Entries below this line are generated — do not edit them
by hand.
34 changes: 34 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,40 @@ pnpm run dev -- list --json

---

## Releasing

Releases are cut automatically by **semantic-release** — never bump the version
or publish by hand. This mirrors `juspay/neurolink`.

**Flow:** push to `release` → `.github/workflows/release.yml` → `npx
semantic-release` → version derived from the commit messages → published to npm
with provenance → `CHANGELOG.md` and `package.json` committed back with
`[skip ci]` → mirrored to GitHub Packages.

**Auth is token-less.** Publishing uses npm Trusted Publishing (OIDC): the
workflow declares `id-token: write` and upgrades npm (`npm install -g npm@latest`,
since OIDC needs npm >= 11.5.1). There is no `NPM_TOKEN`. This requires a
trusted publisher configured for `@juspay/workforge` on npmjs.com, pointing at
this repository and at `release.yml` by name — rename that file and publishing
breaks.

**Commit types decide the version** (`.releaserc.json`):

| Type | Effect |
|------|--------|
| `feat` | minor |
| `fix`, `perf`, `revert`, `refactor`, `build` | patch |
| `docs`, `style`, `test`, `ci`, `chore` | no release |
| `BREAKING CHANGE:` in the body, or `type!` | major |

A ticket prefix is tolerated — `BZ-123: fix: ...` parses the same as `fix: ...`.

Preview what a push would release, without publishing anything:

```bash
pnpm run release:dry-run
```

## Architecture

### v3.0 - Modular Design
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ A powerful CLI tool for managing Git worktrees with intelligent environment vari

```bash
# Install globally via pnpm
pnpm install -g workforge
pnpm install -g @juspay/workforge

# Use anywhere
workforge --type feat --name user-auth
Expand All @@ -49,7 +49,7 @@ wf --type fix --name memory-leak

```bash
# Install in your project
pnpm install --save-dev workforge
pnpm install --save-dev @juspay/workforge

# Add to package.json scripts
{
Expand Down Expand Up @@ -318,7 +318,7 @@ jobs:
- uses: actions/checkout@v3

- name: Install WorkForge
run: pnpm install -g workforge
run: pnpm install -g @juspay/workforge

- name: Configure WorkForge
run: |
Expand Down Expand Up @@ -652,7 +652,7 @@ jobs:
if [ -n "${{ github.event.inputs.ticket_id }}" ]; then
TICKET_FLAG="--ticket ${{ github.event.inputs.ticket_id }}"
fi
npx workforge -t feat -n ${{ github.event.inputs.feature_name }} $TICKET_FLAG -y
npx @juspay/workforge create -t feat -n ${{ github.event.inputs.feature_name }} $TICKET_FLAG -y
```

### Team Workflows
Expand Down
41 changes: 36 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "workforge",
"version": "1.5.0",
"name": "@juspay/workforge",
"version": "1.0.0",
"type": "module",
"description": "Smart Git workspace manager with automatic environment setup, Jira integration, and intelligent package management",
"main": "dist/index.js",
Expand All @@ -15,7 +15,8 @@
"lint:fix": "eslint src --ext .ts --fix",
"prepublishOnly": "pnpm run lint && pnpm run build && vitest run",
"test": "pnpm run build && vitest run",
"test:watch": "vitest"
"test:watch": "vitest",
"release:dry-run": "semantic-release --dry-run --no-ci"
},
"keywords": [
"git",
Expand All @@ -24,15 +25,34 @@
"development",
"branch-management"
],
"author": "Your Name",
"author": "Sachin Sharma <sachiny09@gmail.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/juspay/workforge.git"
},
"homepage": "https://github.com/juspay/workforge#readme",
"bugs": {
"url": "https://github.com/juspay/workforge/issues"
},
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^11.0.6",
"@semantic-release/npm": "^13.1.2",
"@semantic-release/release-notes-generator": "^14.1.0",
"@types/inquirer": "^9.0.9",
"@types/node": "^20.0.0",
"@types/yargs": "^17.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"conventional-changelog-conventionalcommits": "^9.1.0",
"eslint": "^8.56.0",
"semantic-release": "^24.2.8",
"tsx": "^4.0.0",
"typescript": "^5.0.0",
"vitest": "^4.1.10"
Expand All @@ -51,5 +71,16 @@
"files": [
"dist/",
"README.md"
]
],
"pnpm": {
"overrides": {
"brace-expansion@1": "1.1.16",
"brace-expansion@2": "2.1.2",
"flatted@3": "3.4.2",
"js-yaml@4": "4.3.1",
"minimatch@3": "3.1.3",
"minimatch@9": "9.0.7",
"picomatch@2": "2.3.2"
}
}
}
Loading