Skip to content

CXX-3002 update release instructions to support signed release tags #1388

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 8 commits into from
Apr 21, 2025
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
14 changes: 11 additions & 3 deletions etc/garasign_dist_file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ artifactory_creds=~/.secrets/artifactory-creds.txt
garasign_creds=~/.secrets/garasign-creds.txt

unset ARTIFACTORY_USER ARTIFACTORY_PASSWORD
# shellcheck source=/dev/null
. "${artifactory_creds:?}"
: "${ARTIFACTORY_USER:?"missing ARTIFACTORY_USER in ${artifactory_creds:?}"}"
: "${ARTIFACTORY_PASSWORD:?"missing ARTIFACTORY_PASSWORD in ${artifactory_creds:?}"}"

unset GRS_CONFIG_USER1_USERNAME GRS_CONFIG_USER1_PASSWORD
# shellcheck source=/dev/null
. "${garasign_creds:?}"
: "${GRS_CONFIG_USER1_USERNAME:?"missing GRS_CONFIG_USER1_USERNAME in ${garasign_creds:?}"}"
: "${GRS_CONFIG_USER1_PASSWORD:?"missing GRS_CONFIG_USER1_PASSWORD in ${garasign_creds:?}"}"
Expand All @@ -37,6 +39,9 @@ dist_file_signed="${dist_file:?}.asc"

"${launcher:?}" login --password-stdin --username "${ARTIFACTORY_USER:?}" artifactory.corp.mongodb.com <<<"${ARTIFACTORY_PASSWORD:?}"

# Ensure latest version of Garasign is being used.
"${launcher:?}" pull artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-gpg

plugin_commands=(
gpg --yes -v --armor -o "${dist_file_signed:?}" --detach-sign "${dist_file:?}"
)
Expand All @@ -49,6 +54,9 @@ plugin_commands=(
artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-gpg

# Validate the signature file works as intended.
keyring="$(mktemp)"
curl -sS https://pgp.mongodb.com/cpp-driver.pub | gpg -q --no-default-keyring --keyring "${keyring:?}" --import -
gpgv --keyring "${keyring:?}" "${dist_file_signed:?}" "${dist_file:?}"
(
GNUPGHOME="$(mktemp -d)"
export GNUPGHOME
curl -sS https://pgp.mongodb.com/cpp-driver.pub | gpg -q --no-default-keyring --import -
gpgv "${dist_file_signed:?}" "${dist_file:?}"
)
67 changes: 67 additions & 0 deletions etc/garasign_release_tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env bash

# Used by make_release.py.
# See: https://docs.devprod.prod.corp.mongodb.com/release-tools-container-images/garasign/garasign_signing/

set -o errexit
set -o pipefail

: "${1:?"missing tag name as first argument"}"

release_tag="${1:?}"

# Allow customization point to use docker in place of podman.
launcher="${GARASIGN_LAUNCHER:-"podman"}"

if ! command -v "${launcher:?}" >/dev/null; then
echo "${launcher:?} is required to create a GPG-signed release tag" 1>&2
fi

artifactory_creds=~/.secrets/artifactory-creds.txt
garasign_creds=~/.secrets/garasign-creds.txt

unset ARTIFACTORY_USER ARTIFACTORY_PASSWORD
# shellcheck source=/dev/null
. "${artifactory_creds:?}"
: "${ARTIFACTORY_USER:?"missing ARTIFACTORY_USER in ${artifactory_creds:?}"}"
: "${ARTIFACTORY_PASSWORD:?"missing ARTIFACTORY_PASSWORD in ${artifactory_creds:?}"}"

unset GRS_CONFIG_USER1_USERNAME GRS_CONFIG_USER1_PASSWORD
# shellcheck source=/dev/null
. "${garasign_creds:?}"
: "${GRS_CONFIG_USER1_USERNAME:?"missing GRS_CONFIG_USER1_USERNAME in ${garasign_creds:?}"}"
: "${GRS_CONFIG_USER1_PASSWORD:?"missing GRS_CONFIG_USER1_PASSWORD in ${garasign_creds:?}"}"

"${launcher:?}" login --password-stdin --username "${ARTIFACTORY_USER:?}" artifactory.corp.mongodb.com <<<"${ARTIFACTORY_PASSWORD:?}"

# Ensure latest version of Garasign is being used.
"${launcher:?}" pull artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-git

# Sign using "MongoDB C++ Release Signing Key <[email protected]>" from https://pgp.mongodb.com/ (cpp-driver).
git_tag_command=(
git
-c "user.name=\"MongoDB C++ Release Signing Key\""
-c "user.email=\"[email protected]\""
tag
-u DC7F679B8A34DD606C1E54CAC4FC994D21532195
-m "\"${release_tag:?}\""
"\"${release_tag:?}\""
)
plugin_commands=""
plugin_commands+="gpg --list-key DC7F679B8A34DD606C1E54CAC4FC994D21532195"
plugin_commands+="&& ${git_tag_command[*]:?}"
"${launcher:?}" run \
--env-file="${garasign_creds:?}" \
-e "PLUGIN_COMMANDS=${plugin_commands:?}" \
--rm \
-v "$(pwd):$(pwd)" \
-w "$(pwd)" \
artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-git

# Validate the release tag is signed as intended.
(
GNUPGHOME="$(mktemp -d)"
export GNUPGHOME
curl -sS https://pgp.mongodb.com/cpp-driver.pub | gpg -q --no-default-keyring --import -
git verify-tag "${release_tag:?}"
)
22 changes: 17 additions & 5 deletions etc/make_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import re
from distutils.version import LooseVersion
import os
import glob
import subprocess
import sys
import tempfile
Expand Down Expand Up @@ -68,6 +69,9 @@
}

@click.command()
@click.option('--skip-release-tag',
is_flag=True,
help='Use an existing release tag instead of creating a new one')
@click.option('--jira-creds-file',
'-j',
default='jira_creds.txt',
Expand Down Expand Up @@ -111,7 +115,8 @@
help='Produce fewer progress messages')
@click.argument('git-revision', required=True)
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements
def release(jira_creds_file,
def release(skip_release_tag,
jira_creds_file,
github_token_file,
allow_open_issues,
remote,
Expand Down Expand Up @@ -148,6 +153,13 @@ def release(jira_creds_file,
if not quiet:
print_banner(git_revision)

if skip_release_tag:
click.echo(f'Skipping creation of a new release tag')
else:
click.echo('Creating GPG-signed release tag...')
run_shell_script(f'./etc/garasign_release_tag.sh {git_revision}')
click.echo('Creating GPG-signed release tag... done.')

release_tag, release_version = get_release_tag(git_revision)

if not release_tag:
Expand Down Expand Up @@ -384,9 +396,9 @@ def ensure_c_driver(c_driver_build_ref, with_c_driver, quiet):
"""

if with_c_driver:
bson_h = os.path.join(with_c_driver, 'include/bson2/bson/bson.h')
mongoc_h = os.path.join(with_c_driver, 'include/mongoc2/mongoc/mongoc.h')
if os.path.exists(bson_h) and os.path.exists(mongoc_h):
bson_h = glob.glob('include/bson-2.*/bson/bson.h', root_dir=with_c_driver)
mongoc_h = glob.glob('include/mongoc-2.*/mongoc/mongoc.h', root_dir=with_c_driver)
if bson_h and mongoc_h:
return with_c_driver
if not quiet:
click.echo('A required component of the C driver is missing!', err=True)
Expand Down Expand Up @@ -452,7 +464,7 @@ def build_distribution(release_tag, release_version, c_driver_dir, quiet, skip_d

if not skip_distcheck:
click.echo('Building C++ driver from tarball and running tests.')
click.echo('This may take several minutes. This may be skipped with --skip_distcheck')
click.echo('This may take several minutes. This may be skipped with --skip-distcheck')
run_shell_script('cmake --build build --target distcheck')
return dist_file

Expand Down
33 changes: 8 additions & 25 deletions etc/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ git clone -o upstream [email protected]:mongodb/mongo-cxx-driver.git mongo-cxx-driv
cd mongo-cxx-driver-release
```

> [!WARNING]
> The upcoming steps may modify the state of the current repository!
> Cloning the updated repository in a new directory is highly recommended.

Create and activate a fresh Python 3 virtual environment with required packages installed using [uv](https://docs.astral.sh/uv/getting-started/installation/):

```bash
Expand All @@ -300,36 +304,14 @@ uv sync --frozen --group apidocs --group make_release
source "$UV_PROJECT_ENVIRONMENT/bin/activate"
```

### Create a Release Tag...

> [!IMPORTANT]
> Do NOT push the release tag immediately after its creation!

#### ... for a Patch Release

Checkout the release branch (containing the changes from earlier steps) and create a tag for the release.

```bash
git checkout releases/vX.Y
git tag rX.Y.Z
```

#### ... for a Non-Patch Release

Checkout the `master` branch (containing the changes from earlier steps) and create a tag for the release:

```bash
git checkout master
git tag rX.Y.0
```

> [!NOTE]
> A new release branch `releases/vX.Y` will be created later as part of post-release steps.

### Run etc/make_release.py

This script performs the following steps:

- create a GPG-signed release tag,
- create the distribution tarball (e.g. `mongo-cxx-driver-r1.2.3.tar.gz`),
- creates a signature file for the distribution tarball (e.g. `mongo-cxx-driver-r1.2.3.tar.gz.asc`),
- query Jira for release and ticket statuses, and
Expand All @@ -348,7 +330,7 @@ The following secrets are required by this script:
- Artifactory credentials.
- Garasign credentials.

Run the release script with the git tag created above as an argument and
Run the release script with the name of the tag to be created as an argument and
`--dry-run` to test for unexpected errors.

```bash
Expand All @@ -367,6 +349,7 @@ If an error occurs, inspect logs the script produces, and troubleshoot as
follows:

- Use `--dry-run` to prevent unrecoverable effects.
- Use `--skip-release-tag` to skip creating the release tag when it already exists.
- If building the C driver fails, use an existing C driver build (ensure it is
the right version) with `--with-c-driver /path/to/c-driver/install`.
- Use `--skip-distcheck` to bypass time consuming checks when building the
Expand All @@ -380,7 +363,7 @@ Verify the successful creation of the release draft on GitHub.

### Push the Release Tag

Push the release tag (created earlier) to the remote repository:
Push the newly-created GPG-signed release tag to the remote repository:

```bash
git push upstream rX.Y.Z
Expand Down