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
11 changes: 10 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check PR has a semver release label
if: github.event_name == 'pull_request'
run: |
set -euo pipefail
labels=$(ruby -rjson -e 'puts JSON.parse(File.read(ENV.fetch("GITHUB_EVENT_PATH"))).fetch("pull_request").fetch("labels").map { |label| label.fetch("name") }')
if ! grep -qx 'semver-patch' <<< "$labels" && ! grep -qx 'semver-minor' <<< "$labels"; then
echo "Expected pull request to have either the semver-patch or semver-minor label."
exit 1
fi
- name: Check that the default datadog-ci version is pinned
run: |
set -euo pipefail
Expand All @@ -26,7 +35,7 @@ jobs:
set -euo pipefail
bash -n scripts/bump-datadog-ci-version.sh
bash -n scripts/create-datadog-ci-bump-pr.sh
bash -n scripts/release-datadog-ci-bump.sh
bash -n scripts/release-action.sh

tmpdir=$(mktemp -d)
cp action.yaml README.md "$tmpdir"/
Expand Down
70 changes: 56 additions & 14 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,91 @@

This repository ships a composite GitHub Action. Releases are Git tags: immutable semver tags such as `v3.1.0`, plus a moving major tag such as `v3`.

## Requirements

The release scripts require the [GitHub CLI](https://cli.github.com/manual/) and an authenticated session:

```bash
gh auth login
gh auth status
```

Run release scripts from a clean working tree.

## Release labels

Every PR must have one of these labels:

- `semver-patch`: requests the next patch release
- `semver-minor`: requests the next minor release

If a release includes multiple merged PRs, `semver-minor` wins over `semver-patch`. Major releases are explicit: pass `--tag vX.0.0` to the release script.

## Bump datadog-ci

Run the bump helper from a clean working tree:
This repository provides a helper for the common case of bumping the default `datadog-ci-version`. It is not required for every `junit-upload-github-action` release; any merged PR with a `semver-patch` or `semver-minor` label can be released with `scripts/release-action.sh`.

To create a `datadog-ci-version` bump PR, run the helper from a clean working tree:

```bash
scripts/create-datadog-ci-bump-pr.sh
```

The script uses `gh` to check the latest `DataDog/datadog-ci` release. If that release is newer than the default in `action.yaml`, it creates a branch, updates `action.yaml` and `README.md`, pushes the branch, creates the `datadog-ci-version-bump` label if needed, and opens a PR with that label.
The script uses `gh` to check the latest `DataDog/datadog-ci` release. If that release is newer than the default in `action.yaml`, it creates a branch, updates `action.yaml` and `README.md`, pushes the branch, creates labels if needed, and opens a PR.

Preview the bump PR without creating a branch, commit, labels, push, or PR:

```bash
scripts/create-datadog-ci-bump-pr.sh --dry-run
```

The PR gets:

- `datadog-ci-version-bump`
- `semver-patch` when `datadog-ci` only changed by patch
- `semver-minor` when `datadog-ci` changed by minor, or when moving from a floating default to the first pinned version

To test a specific version instead of the latest release:

```bash
scripts/create-datadog-ci-bump-pr.sh v5.14.0
scripts/create-datadog-ci-bump-pr.sh v5.14.0 --dry-run
```

Review and merge the PR normally.

## Release the action

After a `datadog-ci-version-bump` PR is merged, run:
Preview the release first:

```bash
scripts/release-datadog-ci-bump.sh
scripts/release-action.sh --dry-run
```

The script fetches `main` and tags, finds the latest merged PR with the `datadog-ci-version-bump` label that is on `main` but not included in the latest immutable action tag, and releases that merge commit. The action version follows the `datadog-ci` change:
The script fetches `main` and tags, finds merged PRs since the latest immutable action tag, reads their `semver-patch` and `semver-minor` labels, and chooses the next action tag. It releases `origin/main` by default, updates the moving major tag, and creates a GitHub Release with GitHub-generated release notes.

- floating `v5` to the first pinned `v5.x.y`: action minor bump
- `datadog-ci` minor bump: action minor bump
- `datadog-ci` patch bump: action patch bump
If the dry run looks right, publish the release:

The release creates the next immutable action tag, updates the moving major tag, and creates a GitHub Release with GitHub-generated release notes starting from the previous immutable action tag.
```bash
scripts/release-action.sh
```

To release a specific commit on `main`:

```bash
scripts/release-action.sh --sha abc1234 --dry-run
scripts/release-action.sh --sha abc1234
```

Preview the release without creating tags or a GitHub Release:
To choose the tag manually:

```bash
scripts/release-datadog-ci-bump.sh --dry-run
scripts/release-action.sh --tag v3.2.1 --dry-run
scripts/release-action.sh --tag v3.2.1
```

If multiple bump PRs were merged without releases, the script warns and releases only the latest one. To intentionally release an older merge commit separately, stop and pass a specific PR number or commit SHA before releasing the latest one:
If the requested tag is lower than the merged PR labels imply, for example a patch tag while an unreleased PR has `semver-minor`, the script fails. To publish that tag intentionally:

```bash
scripts/release-datadog-ci-bump.sh --pr 123
scripts/release-datadog-ci-bump.sh --sha abc1234
scripts/release-action.sh --tag v3.2.1 --allow-version-mismatch
```
144 changes: 101 additions & 43 deletions scripts/create-datadog-ci-bump-pr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,45 @@ set -euo pipefail

usage() {
cat <<'EOF'
Usage: scripts/create-datadog-ci-bump-pr.sh [vX.Y.Z]
Usage: scripts/create-datadog-ci-bump-pr.sh [vX.Y.Z] [--dry-run]

Checks the latest DataDog/datadog-ci release with gh, then opens a PR that bumps
the default datadog-ci-version when the release is newer than the current default.

Arguments:
vX.Y.Z Optional exact datadog-ci release tag to use instead of releases/latest.

Environment:
BASE_BRANCH Base branch for the PR. Defaults to main.
BRANCH_NAME Branch to create. Defaults to datadog-ci-bump/<version>.
BUMP_LABEL Label applied to the PR. Defaults to datadog-ci-version-bump.
REMOTE Git remote to push to. Defaults to origin.
REPO GitHub repo for gh commands. Defaults to gh repo view's repo.
Options:
--dry-run Print the bump PR that would be created.
EOF
}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi

if [[ $# -gt 1 ]]; then
usage >&2
exit 1
fi
dry_run=false
requested_version=""
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
--dry-run)
dry_run=true
shift
;;
v[0-9]*.[0-9]*.[0-9]*)
if [[ -n "$requested_version" ]]; then
usage >&2
exit 1
fi
requested_version="$1"
shift
;;
*)
usage >&2
exit 1
;;
esac
done

for command in gh git ruby; do
if ! command -v "$command" >/dev/null 2>&1; then
Expand All @@ -37,18 +50,14 @@ for command in gh git ruby; do
fi
done

if [[ -n "$(git status --porcelain)" ]]; then
echo "Working tree must be clean before creating a bump PR." >&2
exit 1
fi

gh auth status >/dev/null

base_branch="${BASE_BRANCH:-main}"
bump_label="${BUMP_LABEL:-datadog-ci-version-bump}"
remote="${REMOTE:-origin}"
repo="${REPO:-$(gh repo view --json nameWithOwner --jq '.nameWithOwner')}"
requested_version="${1:-}"
base_branch="main"
bump_label="datadog-ci-version-bump"
remote="origin"
repo="DataDog/junit-upload-github-action"
semver_minor_label="semver-minor"
semver_patch_label="semver-patch"

current_version=$(ruby -ryaml -e 'puts YAML.load_file("action.yaml").fetch("inputs").fetch("datadog-ci-version").fetch("default")')
if [[ -n "$requested_version" ]]; then
Expand All @@ -62,27 +71,69 @@ if [[ ! "$latest_version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
exit 1
fi

version_gt() {
local left="${1#v}"
local right="${2#v}"
local left_major left_minor left_patch right_major right_minor right_patch
is_exact_version() {
[[ "$1" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
}

semver_parts() {
local version="${1#v}"
IFS=. read -r semver_major semver_minor semver_patch <<< "$version"
echo "$semver_major $semver_minor $semver_patch"
}

bump_kind_for_datadog_ci_change() {
local current="$1"
local next="$2"

if ! is_exact_version "$current"; then
echo "minor"
return 0
fi

local current_major current_minor current_patch next_major next_minor next_patch
read -r current_major current_minor current_patch <<< "$(semver_parts "$current")"
read -r next_major next_minor next_patch <<< "$(semver_parts "$next")"

IFS=. read -r left_major left_minor left_patch <<< "$left"
IFS=. read -r right_major right_minor right_patch <<< "$right"
if (( next_major == current_major && next_minor == current_minor && next_patch > current_patch )); then
echo "patch"
return 0
fi

(( left_major > right_major )) && return 0
(( left_major < right_major )) && return 1
(( left_minor > right_minor )) && return 0
(( left_minor < right_minor )) && return 1
(( left_patch > right_patch ))
if (( next_major > current_major || (next_major == current_major && next_minor > current_minor) )); then
echo "minor"
return 0
fi

return 1
}

if ! version_gt "$latest_version" "$current_version"; then
if ! release_bump_kind=$(bump_kind_for_datadog_ci_change "$current_version" "$latest_version"); then
echo "No datadog-ci bump needed. Current default is $current_version; latest is $latest_version."
exit 0
fi
if [[ "$release_bump_kind" == "minor" ]]; then
release_label="$semver_minor_label"
else
release_label="$semver_patch_label"
fi

branch_name="datadog-ci-bump/${latest_version#v}"

branch_name="${BRANCH_NAME:-datadog-ci-bump/${latest_version#v}}"
if [[ "$dry_run" == "true" ]]; then
echo "Current datadog-ci version: $current_version"
echo "Target datadog-ci version: $latest_version"
echo "Release bump kind: $release_bump_kind"
echo "Branch to create: $branch_name"
echo "Files to update: action.yaml README.md"
echo "Labels to apply: $bump_label $release_label"
echo "Dry run only. No branch, commit, labels, push, or PR were created."
exit 0
fi

if [[ -n "$(git status --porcelain)" ]]; then
echo "Working tree must be clean before creating a bump PR." >&2
exit 1
fi

existing_pr_url=$(gh pr list \
--repo "$repo" \
Expand All @@ -96,7 +147,7 @@ if [[ -n "$existing_pr_url" ]]; then
fi

if git show-ref --verify --quiet "refs/heads/$branch_name"; then
echo "Local branch '$branch_name' already exists. Delete it or set BRANCH_NAME to another value." >&2
echo "Local branch '$branch_name' already exists. Delete it before rerunning the script." >&2
exit 1
fi

Expand All @@ -111,10 +162,16 @@ git push -u "$remote" "$branch_name"

gh label create "$bump_label" \
--repo "$repo" \
--description "Triggers a junit-upload-github-action release after merge" \
--description "Marks PRs that bump the default datadog-ci version" \
--color "1D76DB" \
--force

gh label create "$release_label" \
--repo "$repo" \
--description "Requests a $release_bump_kind junit-upload-github-action release after merge" \
--color "0E8A16" \
--force

body_file=$(mktemp)
trap 'rm -f "$body_file"' EXIT
cat > "$body_file" <<EOF
Expand All @@ -124,7 +181,7 @@ Bumps the default \`datadog-ci-version\` from \`$current_version\` to \`$latest_

## Release behavior

Merging this PR with the \`$bump_label\` label will trigger the release workflow. That workflow creates the next immutable action tag, moves the major action tag, and creates a GitHub Release.
This PR is labeled \`$release_label\`, so the release helper will create a $release_bump_kind action release after merge.
EOF

gh pr create \
Expand All @@ -133,4 +190,5 @@ gh pr create \
--head "$branch_name" \
--title "Bump datadog-ci to $latest_version" \
--body-file "$body_file" \
--label "$bump_label"
--label "$bump_label" \
--label "$release_label"
Loading
Loading