Skip to content

PHPC-2381: Allow releasing pre-release versions through the release automation #1590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
33 changes: 9 additions & 24 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
workflow_dispatch:
inputs:
version:
description: "The version to be released. This is checked for consistency with the branch name and configuration"
description: "The version to be released in PECL format (e.g. 1.19.1, 1.20.0beta1)"
required: true
type: "string"
jira-version-number:
Expand Down Expand Up @@ -76,31 +76,12 @@ jobs:
with:
php-version: "${{ matrix.php-version }}"

- name: "Update version information to stable release"
run: ./bin/update-release-version.php to-stable

- name: "Read current package version"
run: echo "PACKAGE_VERSION=$(./bin/update-release-version.php get-version)" >> "$GITHUB_ENV"

# Sanity check - the version from the input and the one determined by phongo_version.h need to be the same
- name: "Check version for consistency"
if: ${{ inputs.version != env.PACKAGE_VERSION }}
# We exit with an error to abort the workflow. This is only run if the versions don't match
run: |
echo '❌ Release failed due to version mismatch: expected ${{ inputs.version }}, got ${{ env.PACKAGE_VERSION }} from code' >> $GITHUB_STEP_SUMMARY
exit 1

#
# Preliminary checks done - commence the release process
#

- name: "Create package commit"
uses: mongodb-labs/drivers-github-tools/bump-version@v2
with:
version: ${{ inputs.version }}
# Use get-version as a dummy as a version_bump_script is required
# We run the bump script manually earlier so we can sanity-check the version number and print nice output
version_bump_script: "./bin/update-release-version.php get-version"
# Note: this script will fail and abort if the requested version can't be released
version_bump_script: "./bin/update-release-version.php release"
commit_template: 'Package ${VERSION}'
# Don't push changes as we're creating a second commit later
push_commit: false
Expand All @@ -117,7 +98,7 @@ jobs:
uses: mongodb-labs/drivers-github-tools/bump-version@v2
with:
version: ${{ inputs.version }}
version_bump_script: "./bin/update-release-version.php to-next-patch-dev"
version_bump_script: "./bin/update-release-version.php to-next-dev"
commit_template: 'Back to -dev'
# Don't push commit, we still need to merge up
push_commit: false
Expand Down Expand Up @@ -155,7 +136,11 @@ jobs:
EOL

- name: "Create draft release"
run: echo "RELEASE_URL=$(gh release create ${{ inputs.version }} --target ${{ github.ref_name }} --title "${{ inputs.version }}" --notes-file release-message --draft)" >> "$GITHUB_ENV"
run: |
if [[ "${{ inputs.version }}" =~ (alpha|beta) ]]; then
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't release candidates also be considered a prerelease? Those historically used "beta" stability in PECL.

Copy link
Member Author

Choose a reason for hiding this comment

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

Note that since PECL doesn't have a stability constant for release candidates, so I haven't yet added support for them. However, it should be easy enough to add in case we want to do so.

I'll take this as a "yes, let's support release candidates". I'll update the tooling accordingly 👍

PRERELEASE="--prerelease --latest=false"
fi
echo "RELEASE_URL=$(gh release create ${{ inputs.version }} ${PRERELEASE} --target ${{ github.ref_name }} --title "${{ inputs.version }}" --notes-file release-message --draft)" >> "$GITHUB_ENV"

- name: "Set summary"
run: |
Expand Down
23 changes: 11 additions & 12 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,17 @@ enter the version number and the corresponding JIRA version ID for the release.
This version ID can be obtained from a link in the "Version" column on the
[PHPC releases page](https://jira.mongodb.org/projects/PHPC?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page&status=unreleased).

The automation will then create and push the necessary commits and tag, create a
draft release, and trigger the packaging builds for the newly created tag. The
release is created in a draft state and can be published once the release notes
have been updated.
The automation will create and push the necessary commits and tag, create a
draft release, trigger the packaging builds for the newly created tag, and
publish all required SSDLC assets. The release is created in a draft state and
can be published once the release notes have been updated.

Pre-releases (e.g. alpha and beta stability) can be released using the
automation as well. When entering a pre-release version number, make sure to not
include a dash before the stability, e.g. `1.20.0beta1` not `1.20.0-beta1`. PECL
versions do not include a dash before the stability. GitHub Releases for
pre-release versions will be marked as such and will not be marked as "latest"
release.

Alternatively, you may follow the [manual release process](#manual-release-process)
before continuing with the next section.
Expand All @@ -75,14 +82,6 @@ in the MongoDB documentation must be updated to account for new releases. Make
sure to update both MongoDB and Language compatibility tables, as shown in
[this pull request](https://github.com/mongodb/docs-ecosystem/pull/642).

## Handle merge-up pull request

After the release automation pushes changes to the stable branch the release was
created from, the merge automation will create a new pull request to merge these
changes into the next versioned branch. Since version changes always create a
conflict, follow the "Ignoring Changes" section in the pull request to resolve
the conflicts and merge the pull request once the build completes.

## Announce release

Significant release announcements should also be posted in the
Expand Down
74 changes: 73 additions & 1 deletion bin/update-release-version.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ function usage()

echo <<<EOT
Usage:
{$argv[0]} <command>
{$argv[0]} <command> [<version>]

Commands:
release: Release the given version (requires second argument)
to-next-dev: Update to the next version following the current version
to-stable: Mark the current version as stable
to-next-patch-dev: Update to the next patch development version
to-next-minor-dev: Update to the next minor development version
Expand Down Expand Up @@ -50,6 +52,25 @@ function read_release_version(string $filename): array
return $versions;
}

function parse_release_version(string $version): array
{
// Regex copied from https://github.com/pear/pear-core/blob/6f4c3a0b134626d238d75a44af01a2f7c4e688d9/PEAR/Common.php#L32
if (! preg_match('#^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:(?<stability>(?:alpha|beta))(?<prereleasenum>\d+))?$#', $version, $matches)) {
throw new Exception(sprintf('Given version "%s" is not in the PEAR version format'));
}

return [
'version' => $version,
'stability' => $matches['stability'] ?? 'stable',
'versionComponents' => [
$matches['major'],
$matches['minor'],
$matches['patch'],
0,
],
];
}

function write_release_version(string $filename, array $version): void
{
if (! is_file($filename)) {
Expand Down Expand Up @@ -140,6 +161,45 @@ function get_next_minor_version(array $versions): array
];
}

function get_next_release_version(array $versions, string $releaseVersion): array
{
$releaseVersion = parse_release_version($releaseVersion);

// When bumping to the specified release version, check if the major, minor, and patch versions match what's currently in the file
if (array_slice($versions['versionComponents'], 0, 3) !== array_slice($releaseVersion['versionComponents'], 0, 3)) {
throw new Exception(sprintf('Cannot bump version "%s" to version "%s".', $versions['version'], $releaseVersion['version']));
}

// Now, re-use the existing version components to copy over the previous build number used for DLLs
$releaseVersion['versionComponents'] = $versions['versionComponents'];

return $releaseVersion;
}

function get_next_dev_version(array $versions): array
{
$versionComponents = $versions['versionComponents'];

// We're dealing with a pre-release. The next version is a devel version of the corresponding stable release
// Examples:
// 1.19.1snapshot => 1.19.1dev
// 1.20.0alpha1 => 1.20.0dev
// 1.20.0beta1 => 1.20.0dev
if ($versions['stability'] != 'stable') {
// Increase the build number for unique DLL versions
$versionComponents[3]++;

return [
'version' => get_version_string_from_components($versionComponents) . 'dev',
'stability' => 'devel',
'versionComponents' => $versionComponents,
];
}

// For all other releases, return the next patch version
return get_next_patch_version($versions);
}

// Allow 2 arguments as the bump-version action always passes a version number, even when not needed
if (! in_array($argc, [2, 3])) {
usage();
Expand All @@ -153,6 +213,18 @@ function get_next_minor_version(array $versions): array

exit(0);

case 'release':
if ($argc !== 3) {
usage();
}

$newVersion = get_next_release_version($currentVersion, $argv[2]);
break;

case 'to-next-dev':
$newVersion = get_next_dev_version($currentVersion);
break;

case 'to-stable':
$newVersion = get_stable_version($currentVersion);
break;
Expand Down
Loading