Skip to content

Add script to perform release #9174

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

Merged
merged 2 commits into from
Jul 17, 2025
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
4 changes: 4 additions & 0 deletions repository.datadog.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
schema-version: v1
kind: mergequeue
enable: false
Copy link
Contributor

@bric3 bric3 Jul 17, 2025

Choose a reason for hiding this comment

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

suggestion: Might be worth adding the reason why it's disabled. As it might be obvious why.

Suggested change
enable: false
# Disabled because it messes with our existing CI ...to be completed
enable: false

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Damned, this was merged with auto-merge. We will add it in the next commit that fixes the unknown (yet) script issue 😬

92 changes: 92 additions & 0 deletions tooling/perform-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env bash
set -euo pipefail

# Ask for confirmation before continuing the release
function confirmOrAbort() {
read -p "Do you want to continue? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborting."
exit 1
fi
}

# Check if current branch is either 'master' or 'release/v*'
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$CURRENT_BRANCH" == "master" ]]; then
MINOR_RELEASE=true
elif [[ "$CURRENT_BRANCH" =~ ^release/v[0-9]+\.[0-9]+\.x$ ]]; then
MINOR_RELEASE=false
else
echo "❌ Please check out either 'master' branch or a 'release/v*' branch to perform a release first."
exit 1
fi
echo -n "✅ Current branch is '$CURRENT_BRANCH'. Performing a "
if [ "$MINOR_RELEASE" = true ]; then
echo "minor release."
else
echo "patch release."
fi

# Check upstream branch is set
if ! git rev-parse --abbrev-ref --symbolic-full-name "@{u}" >/dev/null 2>&1; then
echo "❌ No upstream branch set. Please set the upstream branch for the current branch."
exit 1
fi

# Get the remote name
REMOTE=$(git config --get "branch.$CURRENT_BRANCH.remote")
if [ -z "$REMOTE" ]; then
echo "❌ Unable to determine the remote name. Please ensure you have a remote set."
exit 1
fi

# Check if working copy is clean
if ! git diff-index --quiet HEAD; then
Copy link
Contributor

Choose a reason for hiding this comment

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

note: This could be detected by the --dirty option in git describe

Copy link
Contributor Author

Choose a reason for hiding this comment

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

git describe --dirty will report untracked file.
Do we want to check them as well? 🤷 (I usually have some scripts related to repo management on the side that I never commit 😅 )

Copy link
Contributor

@bric3 bric3 Jul 17, 2025

Choose a reason for hiding this comment

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

I don't believe so, for example

❯ git status --short --branch
## master...origin/master
❯ touch a
❯ git describe --abbrev=8 --tags --first-parent --match="v[0-9].[0-9]*.[0-9]" --dirty
v1.51.0-42-g847275bc
❯ git status --short --branch
## master...origin/master
?? a

while

❯ echo "// ..." >> build.gradle
❯ git status --short --branch
## master...origin/master
 M build.gradle
❯ git describe --abbrev=8 --tags --first-parent --match="v[0-9].[0-9]*.[0-9]" --dirty
v1.51.0-42-g847275bc-dirty

The --dirty identifies local modifications, so untracked files are not accounted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. --dirty is not impacted by untracked changed.
But I still struggle to find out why git describe: Give an object a human readable name based on an available ref is more suited that git diff-index: _ Compare a tree to the working tree or index_
Especially since there is no easy way to interact with the human readable name 🤔

Copy link
Contributor

@bric3 bric3 Jul 17, 2025

Choose a reason for hiding this comment

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

Sorry for not being clear, my purpose in writing this note is see if it was useful to to perform a single command from to get the dirtiness ad the latest tag (i.e combine L45 and L62). The current code is not problematic, and the ROI there is ... vague. Feel free to dismiss this comment.

echo "❌ Working copy is not clean. Please commit or stash your changes before performing a release."
exit 1
fi

# Check if clone is up to date
if ! git fetch "$REMOTE" --quiet ; then
echo "❌ Unable to fetch the latest changes from $REMOTE. Please check your network connection."
exit 1
fi
if ! git diff-index --quiet "$REMOTE/$CURRENT_BRANCH"; then
echo "❌ Working copy is not up to date with $REMOTE/$CURRENT_BRANCH. Please pull the latest changes before performing a release."
exit 1
fi
echo "✅ Working copy is clean and up-to-date."

# Check the git log history
LAST_RELEASE_TAG=$(git describe --tags --abbrev=0 --match='v[0-9]*.[0-9]*.[0-9]*')
echo "ℹ️ Last release version: $LAST_RELEASE_TAG"
SUSPICIOUS_COMMITS=$(git log --oneline --first-parent "$LAST_RELEASE_TAG"..HEAD | grep -E -v "Merge pull request #" | grep -E -v "\(#")
Copy link
Contributor

Choose a reason for hiding this comment

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

note: I just noticed that PR merged with the merge queue (e.g. via the /merge comment in a PR) are not suffixed with the PR number ((#XXXX)). So this command grep -E -v "\(#") will output merge commits like:

Making members static final to avoid repeated work & allocation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

/merge is related to merge-queue right?
If so, it should not be an issue as we don't use it on this repo as it messes with our CI build (our build is a already based merge build)

And yes, it happens sometimes, that's why it is not blocking but requires manual confirmation to continue.

Copy link
Contributor

@bric3 bric3 Jul 17, 2025

Choose a reason for hiding this comment

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

Actually, it has been used already. E.g. here #9179, possibly but unsure here #9166 (as doggo can add a button in the UI, it might not be necessary to write the /merge comment). And that's since 1.51.0, maybe it was used before.

Copy link
Contributor

Choose a reason for hiding this comment

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

But after looking it up, it might be possible to disable it, by adding this repository.datadog.yml file at the repo root.

---
schema-version: v1
kind: mergequeue
enable: false

https://datadoghq.atlassian.net/wiki/spaces/DEVX/pages/3121612126/MergeQueue#Configuration-Specification

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh interesting! I will disable it then 👍

if [ -n "$SUSPICIOUS_COMMITS" ]; then
echo "❌ The following commits are not merge commits and may not be suitable for a release:"
echo "$SUSPICIOUS_COMMITS"
echo "Please review these commits before proceeding with the release."
confirmOrAbort
else
echo "✅ All commits since the last release are merge commits."
fi

# Get the next release version
VERSION=$(echo "$LAST_RELEASE_TAG" | grep -E '^v[0-9]+\.[0-9]+\.0$' | sed 's/^v//')
if [ -z "$VERSION" ]; then
echo "❌ Unable to determine the next release version from the last release tag: $LAST_RELEASE_TAG"
exit 1
fi
if [ "$MINOR_RELEASE" = true ]; then
NEXT_RELEASE_VERSION=$(echo "$VERSION" | awk -F. '{printf "v%d.%d.0", $1, $2 + 1}')
else
NEXT_RELEASE_VERSION=$(echo "$VERSION" | awk -F. '{printf "v%d.%d.%d", $1, $2, $3 + 1}')
fi
echo "ℹ️ Next release version: $NEXT_RELEASE_VERSION"

# Create and push the release tag
echo "ℹ️ The release tag will be created and pushed. No abort is possible after this point."
confirmOrAbort
git tag -a -s -m "Release $NEXT_RELEASE_VERSION" "$NEXT_RELEASE_VERSION"
git push "$REMOTE" "$NEXT_RELEASE_VERSION" --no-verify
echo "✅ Release tag $NEXT_RELEASE_VERSION created and pushed to $REMOTE."