release-management
Generates and manages release manifests for release/hotfix branches. Use when creating a release or hotfix branch, selecting which products to include in a release, or preparing for CI validation.
SKILL.md
| Name | release-management |
| Description | Generates and manages release manifests for release/hotfix branches. Use when creating a release or hotfix branch, selecting which products to include in a release, or preparing for CI validation. |
name: release-management description: Orchestrates the complete release preparation process - detects changed products, analyzes commits for version bumps, updates version.json files, generates manifests and changelogs, and creates release branches. Use when preparing a new release. allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Skill, AskUserQuestion
Release Manager
You are the orchestrator for preparing releases in the Umbraco.AI repository.
Task
Guide users through the complete release preparation process:
- Detect changed products since their last release tags
- Analyze commits to recommend version bumps (major/minor/patch)
- Confirm versions with the user
- Update Directory.Packages.props inter-product dependency ranges (with user approval)
- Update peerDependencyVersions in root package.json npm peer dependency ranges (with user approval)
- Create release branch (e.g.,
release/2026.02.1) and switch to it - Dependency validation - Check for cross-product conflicts
- Update version.json files for each product
- Generate release-manifest.json via
/release-manifest-management - Generate CHANGELOG.md files via
/changelog-management - Validate all files are consistent
- Commit all changes to the release branch
Workflow
Phase 1: Change Detection
-
Find all products - Discover Umbraco.AI* directories at repo root
-
For each product, detect changes since last release:
# Find the most recent release tag for this product git tag --list "Umbraco.AI@*" --sort=-version:refname | head -n1 # Get commits affecting this product since that tag git log <tag>..HEAD --oneline -- <ProductFolder>/ # Exclude non-substantive changes (CHANGELOG.md, version.json) git diff <tag>..HEAD --name-only -- <ProductFolder>/ | grep -v 'CHANGELOG.md\|version.json' -
Present changed products to user:
Detected changes since last release: ┌─────────────────────┬──────────┬─────────────────────────────┐ │ Product │ Last Tag │ Changes │ ├─────────────────────┼──────────┼─────────────────────────────┤ │ Umbraco.AI │ 1.0.0 │ 12 commits (3 feat, 2 fix) │ │ Umbraco.AI.OpenAI │ 1.0.0 │ 3 commits (1 fix) │ │ Umbraco.AI.Prompt │ 1.0.0 │ 5 commits (1 BREAKING) │ └─────────────────────┴──────────┴─────────────────────────────┘
Phase 2: Version Bump Analysis
For each changed product:
-
Analyze commit types since last tag:
# Get all commits with their messages git log <tag>..HEAD --pretty=format:"%s" -- <ProductFolder>/ -
Determine bump level based on conventional commits:
- BREAKING CHANGE in body or exclamation mark after scope → Major (1.0.0 → 2.0.0)
- feat: or feat(scope): → Minor (1.0.0 → 1.1.0)
- fix:, perf: → Patch (1.0.0 → 1.0.1)
- Only docs:, chore:, refactor: → No bump (but user can override)
-
Read current version from
<Product>/version.json -
Calculate new version:
- Major: Increment X in X.Y.Z, reset Y and Z to 0
- Minor: Increment Y in X.Y.Z, reset Z to 0
- Patch: Increment Z in X.Y.Z
-
Present recommendations:
Version bump recommendations: ┌─────────────────────┬──────────┬──────────┬─────────────────────────────┐ │ Product │ Current │ Proposed │ Reason │ ├─────────────────────┼──────────┼──────────┼─────────────────────────────┤ │ Umbraco.AI │ 1.0.0 │ 1.1.0 │ 3 feat, 2 fix commits │ │ Umbraco.AI.OpenAI │ 1.0.0 │ 1.0.1 │ 1 fix commit │ │ Umbraco.AI.Prompt │ 1.0.0 │ 2.0.0 │ 1 BREAKING CHANGE │ └─────────────────────┴──────────┴──────────┴─────────────────────────────┘
Phase 3: Version Confirmation
Use AskUserQuestion to confirm or adjust versions:
- Default option: "Use recommended versions (above)"
- Alternative options:
- "Downplay breaking changes to minor" - Treat breaking changes as minor bumps (X.Y.0 → X.Y+1.0 instead of X+1.0.0)
- "Adjust individual versions" - Manually specify version for each product
- "Cancel release preparation"
If user chooses "Downplay breaking changes to minor":
- For all products with major bumps (X.Y.Z → X+1.0.0), change to minor bumps (X.Y.Z → X.Y+1.0)
- Keep all other bumps (minor, patch) as-is
- Show updated version table and confirm
If user chooses "Adjust individual versions":
- For each product, ask for custom version
- Validate version format (X.Y.Z)
- Warn if version doesn't follow semver conventions
Phase 4: Update Inter-Product Dependency Ranges (.NET)
After confirming versions, update the Directory.Packages.props file to reflect new minimum version requirements only for products with breaking changes.
Important: Only update dependency ranges when there's a breaking change that requires dependent packages to update. If dependent packages can continue working with the previous version, keep the existing range.
Workflow:
-
Read current Directory.Packages.props:
# Read the root Directory.Packages.props file cat Directory.Packages.props -
Identify products with breaking changes:
- Look for products with BREAKING CHANGE in commit bodies
- Look for commits with
!after scope (e.g.,feat!:,refactor!:) - Track whether breaking changes were downplayed to minor (still breaking!)
- Only these products need dependency range updates
-
Determine which ranges need updating:
- Look for
<PackageVersion Include="Umbraco.AI.*" Version="[X.Y.Z, X.999.999)" />entries - Only update ranges for products with breaking changes:
- Major bump (X.Y.Z → X+1.0.0): Update both bounds:
[X+1.0.0, X+1.999.999) - Minor bump from downplayed breaking change (X.Y.Z → X.Y+1.0): Update lower bound only:
[X.Y+1.0, X.999.999)
- Major bump (X.Y.Z → X+1.0.0): Update both bounds:
- Do NOT update ranges for products without breaking changes (feat/fix only bumps)
- Look for
-
Present proposed changes to user (if any breaking changes detected):
Directory.Packages.props updates: Breaking changes detected in: - Umbraco.AI.Core (BREAKING CHANGE: DetailLevel removal) The following dependency ranges will be updated: - Umbraco.AI.Core: [1.0.0, 1.999.999) → [1.1.0, 1.999.999) - Umbraco.AI.Web: [1.0.0, 1.999.999) → [1.1.0, 1.999.999) - Umbraco.AI.AGUI: [1.0.0, 1.999.999) → [1.1.0, 1.999.999) - Umbraco.AI.Startup: [1.0.0, 1.999.999) → [1.1.0, 1.999.999) Products without breaking changes (Agent, Prompt) will keep existing ranges. -
Ask for approval using AskUserQuestion (only if breaking changes detected):
- Default option: "Update dependency ranges for breaking changes (recommended)"
- Alternative options:
- "Skip dependency updates" - Continue without updating ranges
- "Adjust manually later" - Skip now, remind user to update manually
-
If no breaking changes detected:
✓ No breaking changes detected - dependency ranges remain unchanged -
If approved, update the file:
# Use Edit tool to update Directory.Packages.props -
Confirm updates:
✓ Updated 4 inter-product dependency ranges in Directory.Packages.props
Important Notes:
- Conservative approach: Only update ranges when there are breaking changes
- Products without breaking changes keep their existing ranges (allowing flexibility)
- Only the lower bound changes for minor bumps from downplayed breaking changes
- Both bounds change for true major bumps (X.0.0 → X+1.0.0)
- These changes will be staged and committed with other release files
- If unsure, err on the side of NOT updating (keeps more flexibility for consumers)
Phase 4.5: Update Inter-Product Peer Dependencies (npm)
After updating Directory.Packages.props, update peerDependencyVersions in root package.json to keep npm peer dependencies in sync with .NET dependency ranges.
Important: This phase uses the same version decisions from Phase 3. No need to re-analyze commits.
Workflow:
-
Read current peerDependencyVersions from root package.json:
cat package.json -
Use confirmed versions from Phase 3:
- Take the list of products being released with their new versions
- Same information used in Phase 4 for
Directory.Packages.props
-
Determine which npm ranges need updating:
- For each product being released, check if it has an npm package (has
Client/package.jsonwithtypesfield) - Map the new version to npm semver range:
- New version 2.0.0 →
^2.0.0 - New version 1.3.0 →
^1.3.0 - New version 1.2.1 →
^1.2.1
- New version 2.0.0 →
- Update ALL products being released (not just breaking changes) to ensure consistency
- For each product being released, check if it has an npm package (has
-
Present proposed changes to user:
peerDependencyVersions updates (in root package.json): Products being released: - Umbraco.AI → 1.3.0 - Umbraco.AI.Agent → 1.2.0 - Umbraco.AI.Prompt → 2.0.0 The following npm peer dependency ranges will be updated: - @umbraco-ai/core: ^1.2.0 → ^1.3.0 - @umbraco-ai/agent: ^1.1.0 → ^1.2.0 - @umbraco-ai/prompt: ^1.0.0 → ^2.0.0 -
Validate consistency with Directory.Packages.props:
- Verify that npm ranges match .NET minimum versions from Phase 4
- Warn if any mismatches detected (shouldn't happen if Phase 4 was done correctly)
-
Ask for approval using AskUserQuestion:
- Default option: "Update npm peer dependency ranges (recommended)"
- Alternative options:
- "Skip npm updates" - Continue without updating ranges
- "Adjust manually later" - Skip now, remind user to update manually
-
If approved, update the file:
# Use Edit tool to update peerDependencyVersions in root package.json -
Confirm updates:
✓ Updated npm peer dependency ranges in root package.json (peerDependencyVersions)
Mapping versions to npm ranges:
| New Version | npm Range | Meaning |
|---|---|---|
| 1.2.0 | ^1.2.0 | ≥1.2.0 and <2.0.0 |
| 1.3.0 | ^1.3.0 | ≥1.3.0 and <2.0.0 |
| 2.0.0 | ^2.0.0 | ≥2.0.0 and <3.0.0 |
| 17.1.0 | ^17.1.0 | ≥17.1.0 and <18.0.0 |
Important Notes:
- Uses the same version decisions from Phase 3 (no re-analysis needed)
- Updates ALL products being released (ensures consistency)
- npm ranges should mirror the new minimum versions
- External dependencies like
@umbraco-cms/backofficeare also managed here - These changes will be staged and committed with other release files
Phase 6: Create Release Branch
IMPORTANT: Create the release branch BEFORE making any file changes.
Branch Naming Convention:
Per CONTRIBUTING.md, the recommended convention is calendar-based with incrementing numbers:
release/YYYY.MM.N- Year, month, and incrementing release number- Example:
release/2026.02.1for the first February 2026 release - Example:
release/2026.02.2for the second February 2026 release
This is independent from product version numbers (which follow semantic versioning). A single release branch like release/2026.02.1 can contain multiple products at different versions (e.g., Core@1.1.0, OpenAI@2.0.0, Prompt@1.0.5).
Workflow:
-
Determine current date - Get current year and month for default branch name:
# Get current year and month date +"%Y.%m" # Example output: 2026.02 -
Find next release number - Check existing date-based release tags on GitHub:
# Fetch all tags from remote to ensure we have the latest git fetch --tags # Find existing release tags for current month (e.g., 2026.02.*) # IMPORTANT: This pattern only matches date-based release tags (YYYY.MM.COUNT), # not product version tags (Product@VERSION) git tag --list "2026.02.*" --sort=-version:refname # Example output (only date-based tags): # 2026.02.3 # 2026.02.2 # 2026.02.1 # # This will NOT match product tags like: # Umbraco.AI@1.1.0 # Umbraco.AI.OpenAI@2.0.0 # Parse the highest number and increment by 1 # If no tags exist for current month, start with 1Tag Parsing Logic:
The repository uses two types of tags:
- Date-based release tags:
YYYY.MM.N(e.g.,2026.02.1) - Represent complete release events - Product version tags:
Product@Version(e.g.,Umbraco.AI@1.1.0) - Track individual product versions
For release branch naming, we only care about date-based tags:
- Date tags follow the format
YYYY.MM.Nwhere N is an incrementing counter - Created by the release pipeline when a release is deployed
- Multiple products can be released together under one date tag (e.g.,
2026.02.1might include Core@1.1.0, OpenAI@2.0.0, Prompt@1.0.5) - The pattern
git tag --list "YYYY.MM.*"only matches date-based tags, not product tags - Find the latest date tag for the current month and increment N
- If no date tags exist for current month, N starts at 1
- Date-based release tags:
-
Ask user for branch name:
Create release branch using recommended calendar naming? Latest release tag for February 2026: 2026.02.2 Suggested branch name: release/2026.02.3 (next release in February 2026) Options: - Use suggested name (release/2026.02.3) - Enter custom name (e.g., release/v1.1.0 for version-based) - CancelIf no tags exist for current month:
Create release branch using recommended calendar naming? No previous releases found for February 2026. Suggested branch name: release/2026.02.1 (first release in February 2026) Options: - Use suggested name (release/2026.02.1) - Enter custom name (e.g., release/v1.1.0 for version-based) - Cancel -
Create and checkout branch:
git checkout -b release/<name> -
Confirm branch creation:
✓ Created and switched to branch: release/2026.02.1 All subsequent changes will be made on this branch. Note: This release will contain: - Umbraco.AI 1.1.0 - Umbraco.AI.OpenAI 1.0.1 - Umbraco.AI.Prompt 2.0.0
Phase 7: Dependency Validation
Check for cross-product dependency issues:
-
Find dependency ranges in
Directory.Packages.propsfiles:grep -r "Umbraco.AI.Core" */Directory.Packages.props -
Warn about breaking changes:
⚠️ Warning: Version conflict detected Umbraco.AI → 2.0.0 (major bump) Umbraco.AI.Prompt requires [1.0.0, 1.999.999) Recommendations: - Include Umbraco.AI.Prompt in this release and update its dependency - Or: Keep Umbraco.AI at 1.x for this release
Phase 8: Update version.json Files
For each product with confirmed version:
-
Read current version.json:
{ "version": "1.0.0", "suffixes": ["-beta", ""] } -
Update version field using Edit tool:
# Edit <Product>/version.json to update version -
Verify update by reading the file back
Phase 9: Generate Release Manifest
Invoke /release-manifest-management skill with product list:
- Build comma-separated list of all products being released
- Pass via
--products="Product1,Product2,..."parameter - Example:
--products="Umbraco.AI,Umbraco.AI.Agent,Umbraco.AI.OpenAI" - Skill will generate manifest automatically without prompting
Phase 10: Generate Changelogs
For each product in the manifest:
-
Invoke
/changelog-managementskill:/changelog-management --product=<ProductName> --version=<Version> -
Verify changelog was generated correctly
Phase 11: Validation
Verify all files are consistent:
- Check version.json matches intended versions
- Check CHANGELOG.md exists and has correct version header
- Check release-manifest.json includes all intended products
- Report any issues to user
Phase 12: Commit Changes
All work has been done on the release branch. Now commit everything:
-
Stage all changes:
git add release-manifest.json git add Directory.Packages.props git add package.json git add */version.json git add */CHANGELOG.md -
Create commit:
git commit -m "chore(release): Prepare release 2026.02.1 Updated products: - Umbraco.AI: 1.0.0 → 1.1.0 - Umbraco.AI.OpenAI: 1.0.0 → 1.0.1 - Umbraco.AI.Prompt: 1.0.0 → 2.0.0 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"Note: Use the release branch name (e.g., 2026.02.1) in the commit message, not product versions.
-
Show summary:
✓ Release branch created: release/2026.02.1 ✓ Updated 3 products: - Umbraco.AI: 1.0.0 → 1.1.0 - Umbraco.AI.OpenAI: 1.0.0 → 1.0.1 - Umbraco.AI.Prompt: 1.0.0 → 2.0.0 ✓ Generated changelogs ✓ All changes committed Next steps: - Review the changes: git show HEAD - Push to remote: git push -u origin release/2026.02.1 - Create PR to merge into main - CI will validate and build packages
Important Notes
- Always run from repository root
- Branch naming: Use calendar-based naming
release/YYYY.MM.N(recommended per CONTRIBUTING.md)- Independent from product versions (multiple products = different versions in one release)
- N is an incrementing number for each release in that month (1, 2, 3, etc.)
- Example:
release/2026.02.1can contain Core@1.1.0, OpenAI@2.0.0, Prompt@1.0.5 - Version-based naming like
release/v1.1.0is valid but not recommended
- Use conventional commit analysis for version recommendations
- Validate cross-product dependencies
- This skill orchestrates
/release-manifest-managementand/changelog-management - Creates commits following conventional commit format
- Release branches trigger CI validation and packaging
Version Bump Decision Logic
Priority (highest first):
1. BREAKING CHANGE in commit body → Major
2. ! after scope (e.g., feat!:) → Major
3. feat: or feat(<scope>): → Minor
4. fix: or perf: → Patch
5. Only docs/chore/refactor → Ask user (default: patch)
Cross-Product Dependency Check
Read Directory.Packages.props files to detect version ranges:
<PackageVersion Include="Umbraco.AI.Core" Version="[1.0.0, 1.999.999)" />
If bumping Core to 2.0.0, warn about all products with [1.x, 1.999.999) ranges.
Example Flow
User invokes: /release-management
Phase 1: Detect changes
You scan git history and show:
- Umbraco.AI: 12 commits since 1.0.0
- Umbraco.AI.OpenAI: 3 commits since 1.0.0
- Umbraco.AI.Prompt: 5 commits since 1.0.0
Phase 2: Analyze versions
You show recommendations:
- Umbraco.AI: 1.0.0 → 1.1.0 (minor - 3 feat commits)
- Umbraco.AI.OpenAI: 1.0.0 → 1.0.1 (patch - 1 fix)
- Umbraco.AI.Prompt: 1.0.0 → 2.0.0 (major - BREAKING CHANGE)
Phase 3: Confirm versions
You ask: Use these versions?
Options:
- Use recommended versions (above)
- Downplay breaking changes to minor (2.0.0 → 1.1.0)
- Adjust individual versions
- Cancel
User confirms with chosen option
Phase 4: Update Directory.Packages.props
You read Directory.Packages.props
You identify products with BREAKING CHANGES (Core only)
You present proposed dependency range updates for Core packages only
User approves updates
You update only the Core-related ranges (Agent, Prompt ranges remain unchanged)
Phase 4.5: Update peerDependencyVersions in root package.json
You read peerDependencyVersions from root package.json
You use the same confirmed versions from Phase 3
You map new versions to npm peer dependency ranges
You present proposed npm range updates for ALL products being released
User approves updates
You update npm peer dependency ranges in root package.json (e.g., 1.3.0 → ^1.3.0)
Phase 6: Create release branch
You fetch tags from remote
You check for existing YYYY.MM.* tags (e.g., 2026.02.*)
You find: 2026.02.1 (latest release tag for February 2026)
You suggest: release/2026.02.2 (next release in February 2026)
You create the branch and switch to it
All subsequent work happens on this branch
Phase 7: Check dependencies
You check Directory.Packages.props
You warn: Prompt requires Core 1.x, but Core is going to 1.1.0 - compatible!
Phase 8: Update version.json
You edit all three version.json files on the release branch
Phase 9: Generate manifest
You invoke /release-manifest-management --products="Umbraco.AI,Umbraco.AI.OpenAI,Umbraco.AI.Prompt"
Manifest created with 3 products (no user prompt needed)
Phase 10: Generate changelogs
You invoke /changelog-management for each product
All changelogs generated
Phase 11: Validate
You verify all files are correct
Phase 12: Commit changes
You commit all changes to the release branch
You show summary and next steps
Error Handling
- No changes detected: Ask user if they want to proceed anyway (manual version bump)
- Git tag not found: Fall back to comparing with main branch
- Invalid version.json: Report error and ask user to fix manually
- Changelog generation fails: Report error but continue with other products
- Dependency conflict: Warn user but allow them to proceed