Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e347eeb
feat: automate release steps as requested in #7500
ADITYATIWARI342005 Sep 23, 2025
16698e0
fix: Implemented: wrapper for naming consistency; documented and wire…
ADITYATIWARI342005 Sep 23, 2025
85f2c94
feat(release): add prepare-release wrapper, tighten dry-run, implemen…
ADITYATIWARI342005 Sep 23, 2025
5407cad
fix : simplify start.sh and prepare.sh per review; remove tagging an…
ADITYATIWARI342005 Sep 23, 2025
28cbb07
Update Makefile
ADITYATIWARI342005 Sep 24, 2025
72eac69
Update scripts/release/prepare.sh
ADITYATIWARI342005 Sep 24, 2025
f56aebc
add prepare-release to makefile
ADITYATIWARI342005 Sep 24, 2025
c418a08
update the prepare.sh to removed --auto-tag feature
ADITYATIWARI342005 Sep 24, 2025
1125028
fix: restructure RELEASE.md properly; And update start.sh with the cu…
ADITYATIWARI342005 Sep 24, 2025
a10c5c0
Update scripts/release/prepare.sh
ADITYATIWARI342005 Sep 24, 2025
6670c0a
Update scripts/release/prepare.sh
ADITYATIWARI342005 Sep 24, 2025
bf85654
Update prepare.sh
ADITYATIWARI342005 Sep 24, 2025
dd35bf8
Merge branch 'main' into feature/automate-release-steps-7500
ADITYATIWARI342005 Sep 24, 2025
936cc39
Update RELEASE.md, add the bash script from start.sh to release.md
ADITYATIWARI342005 Sep 28, 2025
28b09de
Update start.sh, remove bash script
ADITYATIWARI342005 Sep 28, 2025
e6f6f2a
Merge branch 'main' into feature/automate-release-steps-7500
ADITYATIWARI342005 Sep 28, 2025
17708d1
Update scripts/release/prepare.sh
ADITYATIWARI342005 Sep 28, 2025
949ae12
feat: automate release steps with changelog, UI upgrade, and tag crea…
ADITYATIWARI342005 Sep 28, 2025
b424cd6
fix logic in prepare.sh
ADITYATIWARI342005 Sep 28, 2025
7eb57a8
Delete scripts/release/utils.sh
ADITYATIWARI342005 Sep 28, 2025
8512f26
Update Makefile, remove makefile target for prepare-release as instru…
ADITYATIWARI342005 Sep 28, 2025
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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ changelog:
draft-release:
./scripts/release/draft.py

.PHONY: prepare-release
prepare-release:
bash ./scripts/release/prepare.sh

.PHONY: test-ci
test-ci: GOTEST := $(GOTEST_QUIET)
test-ci: build-examples cover
Expand Down
72 changes: 43 additions & 29 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,11 @@ Create an issue with the checklist for the release by running `bash scripts/rele

<!-- BEGIN_CHECKLIST -->

1. Create a PR "Prepare release 1.x.x / 2.x.x" against main or maintenance branch ([example](https://github.com/jaegertracing/jaeger/pull/6826)) by updating CHANGELOG.md to include:
* A new section with the header `1.x.x / 2.x.x (YYYY-MM-DD)` (copy the template at the top)
* A curated list of notable changes and links to PRs. Do not simply dump git log, select the changes that affect the users.
To obtain the list of all changes run `make changelog`.
* The section can be split into sub-section if necessary, e.g. UI Changes, Backend Changes, Bug Fixes, etc.
* Then upgrade the submodule versions and finally commit. For example:
```
git submodule init
git submodule update
pushd jaeger-ui
git checkout main
git pull
git checkout {new_ui_version} # e.g. v1.5.0
popd
```
* If there are only dependency bumps, indicate this with "Dependencies upgrades only" ([example](https://github.com/jaegertracing/jaeger-ui/pull/2431/files)).
* If there are no changes, indicate this with "No changes" ([example](https://github.com/jaegertracing/jaeger/pull/4131/files)).
* Rotate the below release managers table placing yourself at the bottom. The date should be the first Wednesday of the month.
* Add label `changelog:skip` to the pull request.
1. Create a PR "Prepare release 1.x.x / 2.x.x" against main or maintenance branch ([example](https://github.com/jaegertracing/jaeger/pull/6826)):
* **Automated option**:
- First, create a tracking issue: `bash scripts/release/start.sh`
- Then, create the PR: `bash ./scripts/release/prepare.sh v1.x.x v2.x.x --tracking-issue #ISSUE_NUMBER`
* **Manual option**: Follow the [manual release preparation steps](#manual-release-preparation-steps) below
2. After the PR is merged, create new release tags:
```
git checkout main
Expand All @@ -54,15 +40,14 @@ Create an issue with the checklist for the release by running `bash scripts/rele

## Manual release

* Manual:
* Title "Release 1.x.x / 2.x.x"
* Tag `v1.x.x` (note the `v` prefix) and choose appropriate branch (usually `main`)
* Copy the new CHANGELOG.md section into the release notes
* Extra: GitHub has a button "generate release notes". Those are not formatted as we want,
but it has a nice feature of explicitly listing first-time contributors.
Before doing the previous step, you can click that button and then remove everything
except the New Contributors section. Change the header to `### 👏 New Contributors`,
then copy the main changelog above it. [Example](https://github.com/jaegertracing/jaeger/releases/tag/v1.55.0).
* Title "Release 1.x.x / 2.x.x"
* Tag `v1.x.x` (note the `v` prefix) and choose appropriate branch (usually `main`)
* Copy the new CHANGELOG.md section into the release notes
* Extra: GitHub has a button "generate release notes". Those are not formatted as we want,
but it has a nice feature of explicitly listing first-time contributors.
Before doing the previous step, you can click that button and then remove everything
except the New Contributors section. Change the header to `### 👏 New Contributors`,
then copy the main changelog above it. [Example](https://github.com/jaegertracing/jaeger/releases/tag/v1.55.0).

## Patch Release

Expand All @@ -78,6 +63,35 @@ Maintenance branches should follow naming convention: `release-major.minor` (e.g
* Once the release tag is created, the `ci-release` workflow will kick in and deploy the artifacts for the patch release.
5. Do not perform a new release of the documentation since the major.minor is not changing. The one change that may be useful is bumping the `binariesLatest` variable in the `config.toml` file ([example](https://github.com/jaegertracing/documentation/commit/eacb52f332a7e069c254e652a6b4a58ea5a07b32)).

## Manual Release Preparation Steps

If you prefer to manually create the release PR instead of using the automated script, follow these steps:

1. Update CHANGELOG.md to include:
* A new section with the header `1.x.x / 2.x.x (YYYY-MM-DD)` (copy the template at the top)
* A curated list of notable changes and links to PRs. Do not simply dump git log, select the changes that affect the users.
To obtain the list of all changes run `make changelog`.
* The section can be split into sub-section if necessary, e.g. UI Changes, Backend Changes, Bug Fixes, etc.

2. Update the UI submodule to the latest version:
```bash
git submodule init
git submodule update
pushd jaeger-ui
git checkout main
git pull
git checkout {new_ui_version} # e.g. v1.5.0
popd
```
* If there are only dependency bumps, indicate this with "Dependencies upgrades only" ([example](https://github.com/jaegertracing/jaeger-ui/pull/2431/files)).
* If there are no changes, indicate this with "No changes" ([example](https://github.com/jaegertracing/jaeger/pull/4131/files)).

3. Rotate the release managers table placing yourself at the bottom. The date should be the first Wednesday of the month.

4. Commit your changes and create a pull request.

5. Add label `changelog:skip` to the pull request.

## Release managers

A Release Manager is the person responsible for ensuring that a new version of Jaeger is released. This person will coordinate the required changes, including to the related components such as UI, IDL, and jaeger-lib and will address any problems that might happen during the release, making sure that the documentation above is correct.
Expand All @@ -93,4 +107,4 @@ Here are the release managers for future versions with the tentative release dat
| 2.13.0 | @joe-elliott | 3 December 2025 |
| 2.14.0 | @mahadzaryab1 | 7 January 2026 |
| 2.15.0 | @jkowall | 4 February 2026 |
| 2.16.0 | @yurishkuro | 5 March 2026 |
| 2.16.0 | @yurishkuro | 5 March 2026 |
289 changes: 289 additions & 0 deletions scripts/release/prepare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
#!/usr/bin/env bash

# Copyright (c) 2025 The Jaeger Authors.
# SPDX-License-Identifier: Apache-2.0

# Automated release preparation script (argument-driven)

set -euo pipefail

# Source utility functions
source "$(dirname "$0")/utils.sh"

# Configuration
REPO="jaegertracing/jaeger"
DRY_RUN=false
TRACKING_ISSUE=""

usage() {
cat << EOF
Usage: $0 [OPTIONS] <v1_version> <v2_version>
Automated release script for Jaeger
OPTIONS:
-d, --dry-run Run in dry-run mode (no actual changes)
--tracking-issue Link to the main tracking issue (e.g., #1234)
-h, --help Show this help message
EOF
}

# Parse command line arguments
POSITIONAL=()
while [[ $# -gt 0 ]]; do
case $1 in
-d|--dry-run)
DRY_RUN=true
shift
;;
--tracking-issue)
TRACKING_ISSUE="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
POSITIONAL+=("$1")
shift
;;
esac
done
set -- "${POSITIONAL[@]}"

# Expect explicit versions as positional args (provided by start.sh substitutions)
if [[ $# -ne 2 ]]; then
log_error "Expected two arguments: <v1_version> <v2_version>"
usage
exit 1
fi
new_version_v1="$1"
new_version_v2="$2"

initialize_and_update_main() {
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping repository validation and git sync"
return 0
fi
validate_repository
git fetch upstream
git checkout main
git pull --ff-only upstream main
}

validate_environment() {
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping GitHub CLI validation"
return 0
fi
validate_gh_cli
}


determine_current_versions() {
read -r current_v1 current_v2 <<< "$(get_current_versions)"
log_info "Current versions: $current_v1 / $current_v2"
if [[ -z "${current_v1:-}" || -z "${current_v2:-}" ]]; then
log_error "Failed to determine current versions (v1='${current_v1:-}', v2='${current_v2:-}')."
log_error "Ensure 'get_current_versions' returns both versions in 'vX.Y.Z vA.B.C' format."
exit 1
fi
}


validate_semver_increment() {
local new_version="$1"
local current_version="$2"
# Expect format vX.Y.Z
if ! [[ "$new_version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
log_error "Version $new_version does not follow semantic versioning format (vX.Y.Z)"
return 1
fi
# No monotonicity check; start.sh is the source of truth
return 0
}

normalize_and_validate_versions() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start.sh is expected to provide the right versions. We can double-check them against regex, but I don't se why we need the other logic here

new_version_v1=$(echo "$new_version_v1" | sed 's/^v//')
new_version_v1="v$new_version_v1"
new_version_v2=$(echo "$new_version_v2" | sed 's/^v//')
new_version_v2="v$new_version_v2"
validate_semver_increment "$new_version_v1" "$current_v1" || exit 1
validate_semver_increment "$new_version_v2" "$current_v2" || exit 1
}

generate_changelog() {
log_info "Generating changelog..."
temp_changelog=$(mktemp)
trap "rm -f \"$temp_changelog\"" EXIT
if make changelog > "$temp_changelog" 2>/dev/null; then
log_success "Changelog generated successfully"
else
log_warning "make changelog failed, using fallback template"
cat > "$temp_changelog" << EOF
## Changes since last release
### ✨ New Features
- Automated release process implementation
### 🛠️ Bug Fixes
- Various bug fixes and improvements
### 📚 Documentation
- Updated release documentation
EOF
fi
}

update_ui_submodule() {
log_info "Updating UI submodule to latest version..."
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping UI submodule update"
else
git submodule init
git submodule update
if [[ ! -d "jaeger-ui" ]]; then
log_error "jaeger-ui submodule not found"
exit 1
fi
pushd jaeger-ui || { log_error "Failed to enter jaeger-ui directory"; exit 1; }
git checkout main || { log_error "Failed to checkout main branch in UI submodule"; popd; exit 1; }
git pull || { log_error "Failed to pull latest changes in UI submodule"; popd; exit 1; }
popd
log_success "UI submodule updated to latest"
fi
}

create_release_branch() {
branch_name="release-prep-${new_version_v1}-${new_version_v2}"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping branch creation: $branch_name"
else
git checkout -b "$branch_name"
log_success "Created and switched to branch: $branch_name"
fi
}

update_changelog_and_commit() {
log_info "Updating CHANGELOG.md..."
current_date=$(date +"%Y-%m-%d")
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Would update CHANGELOG.md with new version section"
else
if [[ -f "CHANGELOG.md" ]]; then
temp_full_changelog=$(mktemp)
trap "rm -f \"$temp_full_changelog\"" EXIT
echo "# ${new_version_v1} / ${new_version_v2} (${current_date})" > "$temp_full_changelog"
echo "" >> "$temp_full_changelog"
cat "$temp_changelog" >> "$temp_full_changelog"
echo "" >> "$temp_full_changelog"
cat "CHANGELOG.md" >> "$temp_full_changelog"
mv "$temp_full_changelog" "CHANGELOG.md"
git add "CHANGELOG.md"
git add "jaeger-ui"
git commit -m "Prepare release ${new_version_v1} / ${new_version_v2}
- Updated CHANGELOG.md with new version section
- Updated UI submodule to latest version
- Generated changelog content using make changelog"
log_success "CHANGELOG.md and UI submodule updated and committed"
else
log_error "CHANGELOG.md not found"
exit 1
fi
fi
}

push_branch() {
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping push of branch to origin"
else
git push -u origin "$branch_name"
log_success "Pushed branch to origin"
fi
}

open_pr_with_body() {
pr_title="Prepare release ${new_version_v1} / ${new_version_v2}"
pr_body="Prepare release ${new_version_v1} / ${new_version_v2}.
This PR updates CHANGELOG.md with a new version section and bumps UI submodule."
if [[ -n "$TRACKING_ISSUE" ]]; then
pr_body+=$'\n\nPart of release tracking issue #'"$TRACKING_ISSUE"''
fi
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping PR creation. Preview below:"
echo "Title: $pr_title"
echo "$pr_body"
else
pr_output=$(gh pr create \
--repo "$REPO" \
--title "$pr_title" \
--body "$pr_body" \
--base main \
--head "$branch_name")
pr_exit_code=$?
pr_url=$(echo "$pr_output" | tail -n 1)
if [[ $pr_exit_code -eq 0 ]]; then
log_success "Release PR created: $pr_url"
gh pr edit "$pr_url" --add-label "changelog:skip"
log_success "Added changelog:skip label"
else
log_error "Failed to create PR"
exit 1
fi
fi
}

print_tag_commands() {
cat << EOF
git checkout main
git pull
git tag ${new_version_v1} -s # sign the v1 tag
git tag ${new_version_v2} -s # sign the v2 tag
git push upstream ${new_version_v1} ${new_version_v2}
EOF
}

create_release_tags() {
if [[ "$DRY_RUN" == "true" ]]; then
log_info "DRY RUN: Skipping tag creation and push for ${new_version_v1} ${new_version_v2}"
return 0
fi
git checkout main
git pull --ff-only upstream main || git pull
git tag "${new_version_v1}" -s -m "${new_version_v1}"
git tag "${new_version_v2}" -s -m "${new_version_v2}"
git push upstream "${new_version_v1}" "${new_version_v2}"
}

# Main function
main() {
log_info "Starting automated release process..."
if [[ "$DRY_RUN" != "true" ]]; then
initialize_and_update_main
validate_environment
else
log_info "DRY RUN: Skipping environment and repository setup"
fi
determine_current_versions
normalize_and_validate_versions
generate_changelog
update_ui_submodule
create_release_branch
update_changelog_and_commit
push_branch
open_pr_with_body
log_success "Release PR creation completed!"
log_info "Next: Review and merge the created PR, then follow the steps in the release issue to complete the release."

log_info "Tag creation is documented in the tracking issue; no tagging performed here."
}

# Run main function
main "$@"


Loading