---
name: release-process
description: Guide for cutting a new release of the Cloud Foundation Fabric (CFF) repository. Use this skill when asked to create, prepare, or draft a new release.
---

# Cloud Foundation Fabric Release Process

This skill guides maintainers through the process of cutting a new release for the Cloud Foundation Fabric (CFF) repository.

> **CRITICAL:** Release names and tags MUST ALWAYS be prefixed with `v` (e.g., `v55.1.0`, `v56.0.0`).

## Prerequisites

- **Permissions:** You must have write/release permissions on the repository.
- **GitHub Token:** A valid GitHub token (can be easily derived by running `gh auth token`).
- **Environment:** You can run the tools using either `uv` (recommended) or a standard Python virtual environment with `tools/requirements.txt` installed.

## 1. Preparation

Start from the `master` branch and ensure you are up to date:

```bash
git checkout master
git pull
```

Identify the **latest released version** by extracting it from the `default-versions.tf` file:

```bash
LATEST_RELEASE=$(grep -oP '(?<=# Fabric release: ).*' default-versions.tf)
echo "Latest release is: $LATEST_RELEASE"
```

## 2. Generate and Review Changelog

Run the changelog script, specifying the bump type (e.g., `major`, `minor`, `patch`):

```bash
# Set your bump type here (major, minor, or patch)
BUMP_TYPE="minor"

# Option A: Using uv (Recommended)
uv run tools/changelog.py --release-from $LATEST_RELEASE --bump $BUMP_TYPE --write --token $(gh auth token)

# Option B: Using a standard virtual environment
./tools/changelog.py --release-from $LATEST_RELEASE --bump $BUMP_TYPE --write --token $(gh auth token)
```

**Review the changes:**
Run `git diff CHANGELOG.md` and carefully inspect the output. Look for:
- PRs missing labels (they will appear under a "no subsection" or similar area).
- Weird or unclear names in PR titles.

**If you find issues:**
1. Click the PR link in the diff.
2. Manually fix the labels or title on GitHub.
3. Re-run the `changelog.py` command above.
4. Repeat until the changelog is clean.

## 3. Bump Versions

Once the changelog is correct, extract the newly generated release version from the top of the changelog and bump the repository versions:

```bash
NEW_RELEASE=$(grep -oP '(?<=^## \[).*(?=\] - )' CHANGELOG.md | head -n 1)
# Ensure it has the 'v' prefix
if [[ $NEW_RELEASE != v* ]]; then NEW_RELEASE="v$NEW_RELEASE"; fi
echo "New release is: $NEW_RELEASE"

# Option A: Using uv (Recommended)
uv run tools/versions.py --fabric-release $NEW_RELEASE --write-defaults

# Option B: Using a standard virtual environment
./tools/versions.py --fabric-release $NEW_RELEASE --write-defaults
```

## 4. Commit and Push

Commit the prepared release files and push to `master`:

```bash
git add CHANGELOG.md default-versions.tf
git commit -m "prep $NEW_RELEASE"
git push origin master
```

**Important:** Wait for the GitHub Actions workflows on `master` to finish successfully before proceeding to the next step. You can monitor the progress directly from your terminal:

```bash
# Watch the latest workflow run on the master branch
gh run watch $(gh run list --branch master --limit 1 --json databaseId -q '.[0].databaseId')
```

## 5. Create the GitHub Release

You can create the release either automatically via the GitHub CLI or manually via the GitHub UI.

### Option A: Automated via GitHub CLI (Recommended)

This script extracts any "BREAKING CHANGES" from the changelog, converts the heading to Title Case, and prepends them to the automatically generated release notes.

```bash
# 1. Extract the section for the new release from CHANGELOG.md
# We use awk to grab everything from the new release header until the next release header
RELEASE_NOTES=$(awk "/^## \[$NEW_RELEASE\]/{flag=1; next} /^## \[v/{flag=0} flag" CHANGELOG.md)

# 2. Extract just the BREAKING CHANGES section (if any)
BREAKING_CHANGES=$(echo "$RELEASE_NOTES" | awk '/^### BREAKING CHANGES/{flag=1; print; next} /^### /{flag=0} flag')

# 3. Create the release
if [ -n "$(echo "$BREAKING_CHANGES" | tr -d '[:space:]')" ]; then
  # Convert "### BREAKING CHANGES" to "### Breaking Changes"
  FORMATTED_BREAKING_CHANGES=$(echo "$BREAKING_CHANGES" | sed 's/^### BREAKING CHANGES/### Breaking Changes/')

  # Prepend breaking changes to the generated notes
  gh release create "$NEW_RELEASE" --title "$NEW_RELEASE" --generate-notes --notes "$FORMATTED_BREAKING_CHANGES"
else
  # Otherwise, just generate the standard notes
  gh release create "$NEW_RELEASE" --title "$NEW_RELEASE" --generate-notes
fi
```

### Option B: Manual via GitHub UI

Go to the [GitHub Releases UI](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/releases/new) and configure the release:

1. **Tag:** Create a new tag matching the new version (e.g., `v56.0.0`).
2. **Title:** Use the exact same version string as the tag.
3. **Release Notes:** Click the **"Generate release notes"** button.
4. **Breaking Changes:** If the `CHANGELOG.md` contains a "BREAKING CHANGES" section for this release, copy it, paste it at the **top** of the generated release notes, and change the heading to "Breaking Changes".

Click **Publish release**.
