-
Notifications
You must be signed in to change notification settings - Fork 9
Release Process Update #101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,263 @@ | ||||||||||||||||||||||||||||
| # Prepare Release Workflow | ||||||||||||||||||||||||||||
| # This workflow automates the release preparation process: | ||||||||||||||||||||||||||||
| # 1. Updates package versions in all package.json files | ||||||||||||||||||||||||||||
| # 2. Generates changelog from git diff between main and last release tag | ||||||||||||||||||||||||||||
| # 3. Creates a release branch and tag | ||||||||||||||||||||||||||||
| # 4. Opens a pull request for review | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| name: Prepare Release | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||
| version: | ||||||||||||||||||||||||||||
| description: 'Release version (e.g., 0.2.0-beta.1). Leave empty to auto-increment patch version.' | ||||||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||
| pull-requests: write | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||
| prepare-release: | ||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||
| - name: Checkout repository | ||||||||||||||||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||
| fetch-depth: 0 # Full history needed for git diff and tags | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - name: Setup Node.js | ||||||||||||||||||||||||||||
| uses: actions/setup-node@v4 | ||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||
| node-version: '22' | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - name: Get latest release tag | ||||||||||||||||||||||||||||
| id: get-latest-tag | ||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||
| # Get the latest tag that looks like a version (v*) | ||||||||||||||||||||||||||||
| LATEST_TAG=$(git tag -l 'v*' --sort=-v:refname | head -n 1) | ||||||||||||||||||||||||||||
| if [ -z "$LATEST_TAG" ]; then | ||||||||||||||||||||||||||||
| echo "No previous release tag found, using initial commit" | ||||||||||||||||||||||||||||
| LATEST_TAG=$(git rev-list --max-parents=0 HEAD) | ||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||
| echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||
| echo "Latest tag: $LATEST_TAG" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - name: Get current version | ||||||||||||||||||||||||||||
| id: get-current-version | ||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||
| CURRENT_VERSION=$(node -p "require('./packages/durabletask-js/package.json').version") | ||||||||||||||||||||||||||||
| echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||
| echo "Current version: $CURRENT_VERSION" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - name: Calculate next version | ||||||||||||||||||||||||||||
| id: calc-version | ||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||
| INPUT_VERSION="${{ github.event.inputs.version }}" | ||||||||||||||||||||||||||||
| CURRENT_VERSION="${{ steps.get-current-version.outputs.current_version }}" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if [ -n "$INPUT_VERSION" ]; then | ||||||||||||||||||||||||||||
| # Use the specified version | ||||||||||||||||||||||||||||
| NEW_VERSION="$INPUT_VERSION" | ||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||
| # Auto-increment: parse current version and bump appropriately | ||||||||||||||||||||||||||||
| # Handle pre-release versions like 0.1.0-alpha.2 -> 0.1.0-alpha.3 | ||||||||||||||||||||||||||||
| # Handle stable versions like 0.1.0 -> 0.1.1 | ||||||||||||||||||||||||||||
| NEW_VERSION=$(node -e " | ||||||||||||||||||||||||||||
| const v = '$CURRENT_VERSION'; | ||||||||||||||||||||||||||||
| const match = v.match(/^(\d+)\.(\d+)\.(\d+)(?:-([a-z]+)\.(\d+))?$/); | ||||||||||||||||||||||||||||
| if (!match) { | ||||||||||||||||||||||||||||
| console.log(v); | ||||||||||||||||||||||||||||
| process.exit(0); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| const [, major, minor, patch, preType, preNum] = match; | ||||||||||||||||||||||||||||
| if (preType && preNum) { | ||||||||||||||||||||||||||||
| // Increment pre-release number | ||||||||||||||||||||||||||||
| console.log(\`\${major}.\${minor}.\${patch}-\${preType}.\${parseInt(preNum) + 1}\`); | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| // Increment patch version | ||||||||||||||||||||||||||||
| console.log(\`\${major}.\${minor}.\${parseInt(patch) + 1}\`); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| ") | ||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||
| echo "New version: $NEW_VERSION" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - name: Generate changelog diff | ||||||||||||||||||||||||||||
| id: changelog-diff | ||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||
| LATEST_TAG="${{ steps.get-latest-tag.outputs.latest_tag }}" | ||||||||||||||||||||||||||||
| NEW_VERSION="${{ steps.calc-version.outputs.new_version }}" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| echo "Generating changelog for changes between $LATEST_TAG and HEAD..." | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Get merge commits (PRs) between last tag and HEAD | ||||||||||||||||||||||||||||
| CHANGELOG_CONTENT=$(git log "$LATEST_TAG"..HEAD --merges --pretty=format:"- %s" | \ | ||||||||||||||||||||||||||||
| sed 's/Merge pull request #\([0-9]*\) from [^:]*:/\[#\1\](https:\/\/github.com\/microsoft\/durabletask-js\/pull\/\1):/' | \ | ||||||||||||||||||||||||||||
|
Comment on lines
+98
to
+99
|
||||||||||||||||||||||||||||
| CHANGELOG_CONTENT=$(git log "$LATEST_TAG"..HEAD --merges --pretty=format:"- %s" | \ | |
| sed 's/Merge pull request #\([0-9]*\) from [^:]*:/\[#\1\](https:\/\/github.com\/microsoft\/durabletask-js\/pull\/\1):/' | \ | |
| CHANGELOG_CONTENT=$(git log "$LATEST_TAG"..HEAD --merges --pretty=format:"- %s %b" | \ | |
| sed 's/Merge pull request #\([0-9]*\) from [^ ]* \(.*\)/\[#\1\](https:\/\/github.com\/microsoft\/durabletask-js\/pull\/\1): \2/' | \ |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sed 's/Merge branch .*//' can turn a line like - Merge branch 'x' into - (not an empty line), so grep -v '^$' won't remove it and the changelog can contain blank bullet points. Consider filtering these merges before prefixing with - , or drop lines that become -/- after transformations.
| grep -v '^$' || echo "") | |
| grep -Ev '^- *$' || echo "") |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow adds changelog sections as ### Changes, but the existing CHANGELOG.md structure uses ### New / ### Fixes headings. Consider keeping the same headings (and optionally splitting entries) so the changelog remains consistent across releases and any downstream tooling/expectations don’t break.
| ### Changes | |
| ${CHANGELOG_CONTENT} | |
| ### New | |
| ${CHANGELOG_CONTENT} | |
| ### Fixes |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const newSection = $NEW_SECTION; in a node -e "..." block is fragile because $NEW_SECTION includes commit messages; backticks, ${...}, or other special characters in commit subjects can break the JS template literal and/or the shell quoting. Consider writing NEW_SECTION to a temp file and reading it from Node, or pass it via base64/JSON-escaped string to avoid injection/quoting failures.
| node -e " | |
| const fs = require('fs'); | |
| let content = fs.readFileSync('CHANGELOG.md', 'utf8'); | |
| const newSection = \`$NEW_SECTION\`; | |
| NEW_SECTION_FILE=$(mktemp) | |
| printf '%s\n' "$NEW_SECTION" > "$NEW_SECTION_FILE" | |
| NEW_SECTION_FILE="$NEW_SECTION_FILE" node -e " | |
| const fs = require('fs'); | |
| let content = fs.readFileSync('CHANGELOG.md', 'utf8'); | |
| const newSection = fs.readFileSync(process.env.NEW_SECTION_FILE, 'utf8'); |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This workflow creates and pushes the release tag before the release PR is reviewed/merged, so the tag will point to a release-branch commit rather than the eventual merge commit on main. That can make vX.Y.Z not correspond to the released commit on the default branch and can confuse consumers/tooling. Consider deferring tag creation until after the PR is merged (e.g., a separate workflow triggered on merge), or tagging the merge commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the current version doesn’t match the regex, the script prints the current version and exits successfully, which will cause the workflow to try creating a branch/tag that likely already exists (and then fail later). It would be safer to
exit 1with a clear error when parsing fails, or fall back tonpm version patch --no-git-tag-versionfor semver-aware bumping.