diff --git a/.claude/skills/create-release/SKILL.md b/.claude/skills/create-release/SKILL.md new file mode 100644 index 0000000000..c4d684ee81 --- /dev/null +++ b/.claude/skills/create-release/SKILL.md @@ -0,0 +1,36 @@ +--- +name: create-release +description: Bump the Rust workspace version in root Cargo.toml, regenerate the lockfile, and open a draft PR on GitHub. Use this skill whenever the user says something like "create a release", "bump the version", "release vX.Y.Z", "prepare a release branch", or "bump workspace version". Trigger even if they just say "release X.Y.Z" or mention a semver version in a release context. +--- + +# Create Release + +Automate the mechanical parts of cutting a release. The full flow (branch from `main`, bump `[workspace.package].version` in `Cargo.toml`, regenerate `Cargo.lock`, push, open draft PR) is implemented in `scripts/create-release.sh`. This skill's job is to collect the version, then invoke the script. + +## Steps + +### 1. Get the target version + +If the user didn't supply a version already, ask: "What version should I bump to?" + +The version must be bare semver (e.g. `32.0.0`, `31.1.0`) — no `v` prefix. The script re-validates and will reject bad input. + +### 2. Run the script + +```bash +scripts/create-release.sh +``` + +The script will: + +1. Fail fast if the working tree is dirty. +2. `git fetch origin main` and branch `release/v` from `origin/main`. +3. Update only the `version` field in `[workspace.package]` of `Cargo.toml`. +4. Run `cargo update -w` to refresh workspace entries in `Cargo.lock`. +5. Commit (`chore: bump workspace version to `), push with `-u`, and open a draft PR titled `chore: release v` against `main`. + +Return the PR URL from the `gh pr create` output to the user. + +### 3. On failure + +If the script exits non-zero, surface its error to the user and stop — do not try to finish the steps manually without checking in first. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3f25d41e80..a3d470fe6d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,6 +2,7 @@ # Rules are evaluated in order. Later matches override earlier ones. # More specific patterns at the bottom override general patterns above. +.claude/ @DataDog/apm-common-components-core .clang-format @DataDog/libdatadog .codecov.yml @DataDog/apm-common-components-core .cargo/* @DataDog/libdatadog-core diff --git a/scripts/create-release.sh b/scripts/create-release.sh new file mode 100755 index 0000000000..558047c23e --- /dev/null +++ b/scripts/create-release.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Cut a release: branch from main, bump workspace version, regenerate lockfile, +# push, and open a draft PR. +# +# Usage: scripts/create-release.sh +# bare semver, e.g. 32.0.0 (no leading "v") + +set -euo pipefail + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 " >&2 + exit 2 +fi + +VERSION="$1" + +if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then + echo "Error: '$VERSION' is not a valid bare semver (e.g. 32.0.0). Do not include a 'v' prefix." >&2 + exit 2 +fi + +REPO_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then + echo "Error: working directory has uncommitted tracked changes. Commit or stash them first." >&2 + git status --short --untracked-files=no >&2 + exit 1 +fi + +BRANCH="release/v${VERSION}" + +echo "==> Fetching origin/main" +git fetch origin main + +echo "==> Creating branch ${BRANCH} from origin/main" +git checkout -b "${BRANCH}" origin/main + +echo "==> Bumping [workspace.package] version to ${VERSION} in Cargo.toml" +# Update only the `version = "..."` line inside the [workspace.package] section. +python3 - "$VERSION" <<'PY' +import re, sys, pathlib +version = sys.argv[1] +path = pathlib.Path("Cargo.toml") +text = path.read_text() + +pattern = re.compile( + r'(\[workspace\.package\][^\[]*?\nversion\s*=\s*")[^"]*(")', + re.DOTALL, +) +new_text, n = pattern.subn(rf'\g<1>{version}\g<2>', text, count=1) +if n != 1: + sys.exit("Error: could not locate version field in [workspace.package]") +path.write_text(new_text) +PY + +echo "==> Regenerating lockfile (cargo update -w)" +cargo update -w + +echo "==> Committing" +git add Cargo.toml Cargo.lock +git commit -m "chore: bump workspace version to ${VERSION}" + +echo "==> Pushing ${BRANCH}" +git push -u origin "${BRANCH}" + +echo "==> Creating draft PR" +gh pr create \ + --title "chore: release v${VERSION}" \ + --body "Bump workspace version to \`${VERSION}\` and regenerate lockfile." \ + --base main \ + --draft