Skip to content

feat: release automation script - #1855

Merged
IronCore864 merged 30 commits into
canonical:mainfrom
IronCore864:release-automation
Jul 28, 2025
Merged

IronCore864 merged 30 commits into
canonical:mainfrom
IronCore864:release-automation

Conversation

@IronCore864

@IronCore864 IronCore864 commented Jun 26, 2025 •

Copy link
Copy Markdown
Contributor

This PR automates the release process according to our discussion in Frankfurt, see here (internal link) for more details.

Dependencies:

  • ENV var GITHUB_TOKEN set
  • The git command is available locally
  • pygithub (managed by tox; if you want to run the script directly for testing purposes, you need to have it).

The script does the following:

  • Runs locally with minimal dependencies (pygithub, installed by tox, and git command)
  • By default, release from the main branch, but other branch is supported.
  • Release: tox -e release. This detects version from the latest tag and suggests a new version for user confirmation. It can be overriden with user-provided value.
  • The script can detect open "update charm pins" PR and asks the user to merge those first.
  • The script asks for a human-written title and a introductory paragraph for the release.
  • Release note and CHANGES.md are formatted (for example, drop the GitHub usernames)
    with categorizations accordingly
  • The script automates version number changes in various files and creates a PR.

@tonyandrewmeyer @james-garner-canonical please have a look because I think according to the order it's going to be you guys doing releases soon.

Done:

  • Test the script by doing a real release.
  • Update docs dependencies as separate process/PR - no need to do anymore since we moved everything to uv with lock.

@IronCore864

Copy link
Copy Markdown
Contributor Author

Test in a mock repo

Existing old release

old-release

Release

$ python release.py
ℹ️ INFO: Latest version in branch "main"": 0.1.0
ℹ️ INFO: Suggested new version: 0.1.1
Input version to release (press enter to use suggested version 0.1.1), or 'c' to cancel:
⚠️ WARNING: Check out the releases page: https://github.com/IronCoreWorks/release-automation/releases before confirming!
Confirm creating release '0.1.1' on branch 'main'? [y/N]: y
ℹ️ INFO: Draft release created: https://github.com/IronCoreWorks/release-automation/releases/tag/untagged-6661b7012148818ad142.
================================================================================
Formatted release notes:
================================================================================
## What's Changed

### Features
* Add changes.md in https://github.com/IronCoreWorks/release-automation/pull/6

### Documentation
* Add version in https://github.com/IronCoreWorks/release-automation/pull/3

### Tests
* Add test in https://github.com/IronCoreWorks/release-automation/pull/4

**Full Changelog**: https://github.com/IronCoreWorks/release-automation/compare/0.1.0...0.1.1
================================================================================
The automatically generated title is: 0.1.1
Enter release title, press Enter to keep the auto-generated title:
> 0.1.1 Test Release

Enter release summary (multi-line supported, type '.' on a new line to finish):
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
.
ℹ️ INFO: Release title and notes updated.
ℹ️ INFO: Updated CHANGES.md with new release notes.
ℹ️ INFO: Updated ops/version.py to release version: 0.1.1
ℹ️ INFO: Updated testing/pyproject.toml to release version: 0.1.1
ℹ️ INFO: Updated tracing/pyproject.toml to release version: 0.1.1
Switched to a new branch 'release-prep-0.1.1'
[release-prep-0.1.1 fd5967f] chore: prepare release 0.1.1
 4 files changed, 17 insertions(+), 3 deletions(-)
            Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Delta compression using up to 10 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 1.80 KiB | 1.80 MiB/s, done.
Total 9 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
        remote:
remote: Create a pull request for 'release-prep-0.1.1' on GitHub by visiting:
remote:      https://github.com/IronCore864/release-automation/pull/new/release-prep-0.1.1
remote:
To github.com:IronCore864/release-automation.git
 * [new branch]      release-prep-0.1.1 -> release-prep-0.1.1
                                                                                
ℹ️ INFO: Created PR: https://github.com/IronCoreWorks/release-automation/pull/10

Automated new release

new-release

Automated release PR

release pr

Post-release

$ python release.py --post-release
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (1/1), 907 bytes | 453.00 KiB/s, done.
From github.com:IronCoreWorks/release-automation
   fa80ad9..a4d32b4  main       -> upstream/main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Updating fa80ad9..a4d32b4
Fast-forward
 CHANGES.md             | 14 ++++++++++++++
 ops/version.py         |  2 +-
 testing/pyproject.toml |  2 +-
 tracing/pyproject.toml |  2 +-
 4 files changed, 17 insertions(+), 3 deletions(-)
ℹ️ INFO: Updated ops/version.py to post-release version: 0.1.2.dev0
ℹ️ INFO: Updated testing/pyproject.toml to post-release version: 0.1.2.dev0
ℹ️ INFO: Updated tracing/pyproject.toml to post-release version: 0.1.2.dev0
Switched to a new branch 'post-release'
[post-release 5d204b5] chore: post release
 3 files changed, 3 insertions(+), 3 deletions(-)
Enumerating objects: 14, done.
Counting objects: 100% (14/14), done.
Delta compression using up to 10 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (8/8), 1.75 KiB | 1.75 MiB/s, done.
Total 8 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
remote:
remote: Create a pull request for 'post-release' on GitHub by visiting:
remote:      https://github.com/IronCore864/release-automation/pull/new/post-release
remote:
To github.com:IronCore864/release-automation.git
 * [new branch]      post-release -> post-release
ℹ️ INFO: Created PR: https://github.com/IronCoreWorks/release-automation/pull/11

Post-release PR

post release pr

@dimaqq dimaqq left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Early review

Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread uv.lock Outdated
@IronCore864
IronCore864 marked this pull request as ready for review July 2, 2025 10:50
Comment thread release.py Outdated
Comment thread release.py Outdated

@tonyandrewmeyer tonyandrewmeyer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few comments, but in general I think the primary test is a release, and the last two, which used this, seemed fine, and if we think there should be tweaks as we each use this to do a release, doing it at the time seems fine.

Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated

@benhoyt benhoyt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like a good start!

Comment thread tox.ini Outdated
Comment thread release.py Outdated

@dimaqq dimaqq left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Partial review at this point, sorry I'm multitasking with secondment.

Comment thread release.py
Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py
Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py Outdated
@IronCore864

Copy link
Copy Markdown
Contributor Author

Another test after refactoring according to all comments above:

$ git branch
  main

$ python release.py --owner ironcoreworks --repo release-automation  # testing org and repo
2025-07-10 11:13:14,849 - INFO - Latest tag in branch "main": 0.1.0
2025-07-10 11:13:14,850 - INFO - Suggested new version: 0.2.0
Input the new tag for the release (press enter to use the tag 0.2.0), or 'c' to cancel:
3.2.0
2025-07-10 11:13:17,939 - WARNING - Check out the releases page: https://github.com/ironcoreworks/release-automation/releases before confirming!
Confirm creating tag '3.2.0' on branch 'main'? [y/N]: y
2025-07-10 11:13:19,675 - INFO - Draft release created: https://github.com/IronCoreWorks/release-automation/releases/tag/untagged-5a42876b7b5b428d3b6b.
================================================================================
Formatted release notes:
================================================================================
## What's Changed


### Features
* Add changes.md in https://github.com/IronCoreWorks/release-automation/pull/6
* Update release automation script and versions in https://github.com/IronCoreWorks/release-automation/pull/20
* Update in https://github.com/IronCoreWorks/release-automation/pull/23
* Update release script in https://github.com/IronCoreWorks/release-automation/pull/24

### Documentation
* Add version in https://github.com/IronCoreWorks/release-automation/pull/3

### Tests
* Add test in https://github.com/IronCoreWorks/release-automation/pull/4

**Full Changelog**: https://github.com/IronCoreWorks/release-automation/compare/0.1.0...3.2.0
================================================================================
2025-07-10 11:13:19,676 - INFO - The automatically generated title is: 3.2.0
Enter release title, press Enter to keep the auto-generated title:
> Test release, ops 3.2.0, tracing 3.2.0, testing/scenario 8.2.0

Enter release summary (multi-line supported; type '.' on a new line to finish):
This is a release for testing the automation script.

The previous tag from my repo is 0.1.0, hence the suggested version is 0.2.0, which is overriden by values provided by the user.

A quick brown fox jumps over something that I forgot.

Put a single dot at the final line to finish drafting the introduction paragraph.
.
2025-07-10 11:13:38,740 - INFO - Release updated: https://github.com/IronCoreWorks/release-automation/releases/tag/untagged-01c17942f2ee6832d913.
2025-07-10 11:13:38,742 - INFO - Updated CHANGES.md with new release notes.
2025-07-10 11:13:38,742 - INFO - Suggested new scenario version: 8.2.0
Input new scenario version (press enter to use the suggested version 8.2.0), or 'c' to cancel:
Confirm using scenario version '8.2.0'? [y/N]: y
2025-07-10 11:13:47,429 - INFO - Updated ops/version.py to version 3.2.0
2025-07-10 11:13:47,430 - INFO - Updated pyproject.toml to version 8.2.0
2025-07-10 11:13:47,430 - INFO - Updated testing/pyproject.toml to version 8.2.0
2025-07-10 11:13:47,431 - INFO - Updated tracing/pyproject.toml to version 3.2.0
Using CPython 3.12.9
Resolved 149 packages in 304ms
Updated ops-scenario v8.2.0.dev0 -> v8.2.0
Updated ops-tracing v3.2.0.dev0 -> v3.2.0
Switched to a new branch 'release-prep-3.2.0'
[release-prep-3.2.0 0a8f4d0] chore: prepare release 3.2.0
 6 files changed, 26 insertions(+), 9 deletions(-)
Enumerating objects: 20, done.
Counting objects: 100% (20/20), done.
Delta compression using up to 10 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (11/11), 2.03 KiB | 2.03 MiB/s, done.
Total 11 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (6/6), completed with 6 local objects.
remote:
remote: Create a pull request for 'release-prep-3.2.0' on GitHub by visiting:
remote:      https://github.com/IronCore864/release-automation/pull/new/release-prep-3.2.0
remote:
To github.com:IronCore864/release-automation.git
 * [new branch]      release-prep-3.2.0 -> release-prep-3.2.0
2025-07-10 11:13:53,908 - INFO - Created PR: https://github.com/IronCoreWorks/release-automation/pull/26
2025-07-10 11:13:53,908 - INFO - Draft release created. Please merge the version bump PR, publish the draft release, thenrun this script with --post-release to perform post-release actions.

@tonyandrewmeyer tonyandrewmeyer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm happy with this as-is. I'm sure we'll want to tweak things in the future, but this seems a good starting point. It's only for our use, so we have more flexibility than with most changes.

The one change I'd like is for HACKING.md to be updated to include instructions for running this script and remove instructions for all the things this script does.

Comment thread release.py

@james-garner-canonical james-garner-canonical left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm happy with merging this as is. I still kind of like iterating over tags rather than releases for suggesting versions, but I don't think that's a blocker. +1 on Tony's comment to ensure HACKING.md is up-to-date.

@benhoyt benhoyt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking close. A few changes requested (and I agree about updating HACKING.md). Let's try to get this merged by the end of this week.

Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
@IronCore864
IronCore864 requested a review from benhoyt July 24, 2025 11:45

@benhoyt benhoyt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good, thanks for the updates. Approving optimistically, but a few minor changes to HACKING.md suggested.

Comment thread HACKING.md Outdated
Comment thread HACKING.md
Comment thread HACKING.md Outdated
Comment thread HACKING.md Outdated
Comment thread HACKING.md Outdated
Comment thread HACKING.md Outdated

@tonyandrewmeyer tonyandrewmeyer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A couple of small notes, but looks great, thanks!

Comment thread HACKING.md Outdated
Comment thread HACKING.md Outdated
@IronCore864

Copy link
Copy Markdown
Contributor Author

Merged main into this branch, resolved the conflicts in HACKING.md, also tweaked the description in HACKING.md a little bit. Merging now.

Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py Outdated
Comment thread release.py
Comment thread release.py
@IronCore864
IronCore864 requested a review from dimaqq July 28, 2025 03:16
Comment thread release.py Outdated
Comment thread release.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants