Skip to content

PHPC-1584: Sign releases #1544

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 16 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
51 changes: 51 additions & 0 deletions .github/actions/garasign/git-sign/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: "Sign artifact using garasign"
description: "Signs a release artifact"
inputs:
command:
description: "Command to run inside the container"
required: true
garasign_username:
description: "Garasign username"
required: true
garasign_password:
description: "Garasign password"
required: true
artifactory_username:
description: "Artifactory user"
required: true
artifactory_password:
description: "Artifactory password"
required: true
artifactory_image:
description: "Image to use for artifactory"
default: release-tools-container-registry-local/garasign-git
artifactory_registry:
description: "Artifactory registry to be used"
default: artifactory.corp.mongodb.com
skip_setup:
description: "Whether to skip setup"
default: "false"

runs:
using: composite
steps:
- name: Prepare garasign container
if: ${{ inputs.skip_setup == 'false' }}
uses: ./.github/actions/garasign/setup
with:
garasign_username: ${{ inputs.garasign_username }}
garasign_password: ${{ inputs.garasign_password }}
artifactory_username: ${{ inputs.artifactory_username }}
artifactory_password: ${{ inputs.artifactory_password }}
artifactory_registry: ${{ inputs.artifactory_registry }}

- name: "Run git command"
run: |
podman run \
--env-file=envfile \
--rm \
-v $(pwd):$(pwd) \
-w $(pwd) \
${{ inputs.artifactory_registry }}/${{ inputs.artifactory_image }} \
/bin/bash -c "gpgloader && ${{ inputs.command }}"
shell: bash
47 changes: 47 additions & 0 deletions .github/actions/garasign/gpg-sign/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: "Sign artifact using garasign"
description: "Signs a release artifact"
inputs:
filename:
description: "File name to sign"
required: true
garasign_username:
description: "Garasign username"
required: true
garasign_password:
description: "Garasign password"
required: true
artifactory_username:
description: "Artifactory user"
required: true
artifactory_password:
description: "Artifactory password"
required: true
artifactory_image:
description: "Image to use for artifactory"
default: release-tools-container-registry-local/garasign-gpg
artifactory_registry:
description: "Artifactory registry to be used"
default: artifactory.corp.mongodb.com

runs:
using: composite
steps:
- name: Prepare garasign container
uses: ./.github/actions/garasign/setup
with:
garasign_username: ${{ inputs.garasign_username }}
garasign_password: ${{ inputs.garasign_password }}
artifactory_username: ${{ inputs.artifactory_username }}
artifactory_password: ${{ inputs.artifactory_password }}
artifactory_registry: ${{ inputs.artifactory_registry }}

- name: "Create detached signature"
run: |
podman run \
--env-file=envfile \
--rm \
-v $(pwd):$(pwd) \
-w $(pwd) \
${{ inputs.artifactory_registry }}/${{ inputs.artifactory_image }} \
/bin/bash -c "gpgloader && gpg --detach-sign --armor --output ${{ inputs.filename }}.sig ${{ inputs.filename }}"
shell: bash
36 changes: 36 additions & 0 deletions .github/actions/garasign/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: "Prepare garasign container"
description: "Prepares the garasign container used to sign artifacts"
inputs:
garasign_username:
description: "Garasign username"
required: true
garasign_password:
description: "Garasign password"
required: true
artifactory_username:
description: "Artifactory user"
required: true
artifactory_password:
description: "Artifactory password"
required: true
artifactory_registry:
description: "Artifactory registry to be used"
default: artifactory.corp.mongodb.com

runs:
using: composite
steps:
- name: Create the envfile
run: |
cat << EOF > envfile
GRS_CONFIG_USER1_USERNAME=${{ inputs.garasign_username }}
GRS_CONFIG_USER1_PASSWORD=${{ inputs.garasign_password }}
EOF
shell: bash

- name: Log in to artifactory
uses: redhat-actions/podman-login@v1
with:
username: ${{ inputs.artifactory_username }}
password: ${{ inputs.artifactory_password }}
registry: ${{ inputs.artifactory_registry }}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ runs:
steps:
- name: Prepare build environment
id: prepare-build-env
uses: ./.github/workflows/windows/prepare-build
uses: ./.github/actions/windows/prepare-build
with:
version: ${{ inputs.version }}
arch: ${{ inputs.arch }}
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/commit-and-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -e

PACKAGE_VERSION=$1
GPG_KEY_ID=$2

gpgloader

# Create signed "Package x.y.z" commit
echo "Create package commit"
git commit -m "Package ${PACKAGE_VERSION}" -s --gpg-sign=${GPG_KEY_ID} phongo_version.h

# Create signed "Release x.y.z" tag
echo "Create release tag"
git tag -F changelog -s --local-user=${GPG_KEY_ID} ${PACKAGE_VERSION}
90 changes: 76 additions & 14 deletions .github/workflows/package-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
submodules: true

- name: "Build Driver"
uses: ./.github/workflows/linux/build
uses: ./.github/actions/linux/build
with:
version: "8.3"

Expand All @@ -38,27 +38,41 @@ jobs:
# PECL always uses the version for the package name.
# Read it from the version file and store in env to use when uploading artifacts
- name: "Read current package version"
run: echo "PACKAGE_VERSION=$(./bin/update-release-version.php get-version)" >> "$GITHUB_ENV"
run: |
PACKAGE_VERSION=$(./bin/update-release-version.php get-version)
echo "PACKAGE_VERSION=${PACKAGE_VERSION}" >> "$GITHUB_ENV"
echo "PACKAGE_FILE=mongodb-${PACKAGE_VERSION}.tgz" >> "$GITHUB_ENV"

- name: "Create detached signature for PECL package"
uses: ./.github/actions/garasign/gpg-sign
with:
filename: ${{ env.PACKAGE_FILE }}
garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }}
garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }}
artifactory_username: ${{ secrets.ARTIFACTORY_USER }}
artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }}

- name: "Install release archive to verify correctness"
run: sudo pecl install mongodb-${{ env.PACKAGE_VERSION }}.tgz
run: sudo pecl install ${{ env.PACKAGE_FILE }}

- name: "Upload artifact"
- name: "Upload artifacts"
Copy link
Member

Choose a reason for hiding this comment

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

I realize these steps predate the PR, but can you remind me why we use both actions/upload-artifact and gh release upload? The former attaches the package and signature files to the action, while the latter attaches them to a GitHub release. Are both needed?

The only prior art that comes to mind was how we handle Windows DLLs by temporarily storing them on an action (from the build step) and having the release action transfer them to the GitHub release.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since this workflow is enabled for every tag, I wanted to upload the artifacts to the build as well in case we push a tag manually (e.g. for a pre-release) where there is no draft release yet. In that case, we'd still be able to download the artifacts manually and upload them to the release manually. I'm happy to remove this once we've covered every possible angle of the release process.

uses: actions/upload-artifact@v4
with:
name: mongodb-${{ env.PACKAGE_VERSION }}.tgz
path: mongodb-${{ env.PACKAGE_VERSION }}.tgz
name: ${{ env.PACKAGE_FILE }}
path: |
${{ env.PACKAGE_FILE }}
${{ env.PACKAGE_FILE }}.sig
retention-days: 3

- name: "Upload release artifact"
run: gh release upload ${{ github.ref_name }} mongodb-${{ env.PACKAGE_VERSION }}.tgz
- name: "Upload release artifacts"
run: gh release upload ${{ github.ref_name }} ${{ env.PACKAGE_FILE }} ${{ env.PACKAGE_FILE }}.sig
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build-windows:
name: "Create Windows package"
runs-on: windows-2022
runs-on: windows-latest
Copy link
Member Author

Choose a reason for hiding this comment

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

Using windows-latest is necessary to be able to share the cached build artifacts.

defaults:
run:
shell: cmd
Expand All @@ -78,7 +92,7 @@ jobs:

- name: "Build Driver"
id: build-driver
uses: ./.github/workflows/windows/build
uses: ./.github/actions/windows/build
with:
version: ${{ matrix.php }}
arch: ${{ matrix.arch }}
Expand All @@ -91,20 +105,68 @@ jobs:
env:
BUILD_DIR: ${{ steps.build-driver.outputs.build-dir }}

- name: "Cache build artifacts for subsequent builds"
uses: actions/cache/save@v4
with:
key: ${{ github.sha }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}
enableCrossOsArchive: true
path: |
php_mongodb.dll
php_mongodb.pdb

sign-and-publish-windows:
name: "Sign and Publish Windows package"
needs: [build-windows]
runs-on: "ubuntu-latest"

strategy:
fail-fast: false
matrix:
# Note: keep this in sync with the Windows matrix in windows-tests.yml
php: [ "7.4", "8.0", "8.1", "8.2", "8.3" ]
arch: [ x64, x86 ]
ts: [ ts, nts ]

steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Restore cached build artifacts
id: cache-build-artifacts
uses: actions/cache/restore@v4
with:
fail-on-cache-miss: true
key: ${{ github.sha }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}
enableCrossOsArchive: true
path: |
php_mongodb.dll
php_mongodb.pdb

- name: "Create detached DLL signature"
uses: ./.github/actions/garasign/gpg-sign
with:
filename: php_mongodb.dll
garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }}
garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }}
artifactory_username: ${{ secrets.ARTIFACTORY_USER }}
artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }}

- name: "Upload DLL and PDB files as build artifacts"
uses: actions/upload-artifact@v4
with:
name: php_mongodb-${{ github.ref_name }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}
name: php_mongodb-${{ github.sha }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}
path: |
php_mongodb.dll
php_mongodb.dll.sig
php_mongodb.pdb
retention-days: 3

- name: "Create and upload release artifact"
run: |
set ARCHIVE=php_mongodb-${{ github.ref_name }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}.zip
zip %ARCHIVE% php_mongodb.dll php_mongodb.pdb CREDITS CONTRIBUTING.md LICENSE README.md THIRD_PARTY_NOTICES
gh release upload ${{ github.ref_name }} %ARCHIVE%
ARCHIVE=php_mongodb-${{ github.ref_name }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.arch }}.zip
zip ${ARCHIVE} php_mongodb.dll php_mongodb.dll.sig php_mongodb.pdb CREDITS CONTRIBUTING.md LICENSE README.md THIRD_PARTY_NOTICES
gh release upload ${{ github.ref_name }} ${ARCHIVE}
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44 changes: 31 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ jobs:
git config user.name "${GIT_AUTHOR_NAME}"
git config user.email "${GIT_AUTHOR_EMAIL}"

# Create the "Package x.y.z" commit that will be the base of our tag
- name: "Create release commit"
run: git commit -m "Package ${{ env.PACKAGE_VERSION }}" phongo_version.h

# Create a draft release with a changelog
# TODO: Consider using the API to generate changelog
- name: "Create draft release with generated changelog"
Expand All @@ -101,14 +97,34 @@ jobs:
- name: "Read changelog from draft release"
run: gh release view ${{ env.PACKAGE_VERSION }} --json body --template '{{ .body }}' >> changelog

# TODO: Sign tag
- name: "Create release tag"
run: git tag -a -F changelog ${{ env.PACKAGE_VERSION }}

- name: "Update version information to next patch development release"
run: |
./bin/update-release-version.php to-next-patch-dev
git commit -m "Back to -dev" phongo_version.h
# This step creates the "Package x.y.z" commit that will be the base of
# our tag and creates the release tag. This is run inside the container in
# order to create signed git artifacts
- name: "Create package commit and release tag"
uses: ./.github/actions/garasign/git-sign
with:
command: "$(pwd)/.github/workflows/commit-and-tag.sh ${{ env.PACKAGE_VERSION }} ${{ vars.GPG_KEY_ID }}"
garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }}
garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }}
artifactory_username: ${{ secrets.ARTIFACTORY_USER }}
artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }}

# This step needs to happen outside of the container, as PHP is not
# available within.
- name: "Bump to next development release"
run: ./bin/update-release-version.php to-next-patch-dev

# Create a signed "back to -dev" commit, again inside the container
- name: "Create dev commit"
uses: ./.github/actions/garasign/git-sign
with:
# Setup can be skipped as it was already done before
skip_setup: true
command: "git commit -m 'Back to -dev' -s --gpg-sign=${{ vars.GPG_KEY_ID }} phongo_version.h"
garasign_username: ${{ secrets.GRS_CONFIG_USER1_USERNAME }}
garasign_password: ${{ secrets.GRS_CONFIG_USER1_PASSWORD }}
artifactory_username: ${{ secrets.ARTIFACTORY_USER }}
artifactory_password: ${{ secrets.ARTIFACTORY_PASSWORD }}

# TODO: Manually merge using ours strategy. This avoids merge-up pull requests being created
# Process is:
Expand All @@ -122,7 +138,9 @@ jobs:

- name: "Prepare release message"
run: |
echo "${{ format(env.default-release-message, env.PACKAGE_VERSION, inputs.jira-version-number) }}" > release-message
cat > release-message <<'EOL'
${{ format(env.default-release-message, env.PACKAGE_VERSION, inputs.jira-version-number) }}
EOL
cat changelog >> release-message

# Update release with correct release information
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:

- name: "Build Driver"
id: build-driver
uses: ./.github/workflows/linux/build
uses: ./.github/actions/linux/build
with:
version: ${{ matrix.php-version }}

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/windows-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:

- name: "Build Driver"
id: build-driver
uses: ./.github/workflows/windows/build
uses: ./.github/actions/windows/build
with:
version: ${{ matrix.php }}
arch: ${{ matrix.arch }}
Expand Down Expand Up @@ -74,7 +74,7 @@ jobs:

- name: Prepare build environment
id: prepare-build
uses: ./.github/workflows/windows/prepare-build
uses: ./.github/actions/windows/prepare-build
with:
version: ${{ matrix.php }}
arch: ${{ matrix.arch }}
Expand Down
Loading