Skip to content

Commit

Permalink
Merge pull request #29 from uclahs-cds/nwiltsie-attach-tarball
Browse files Browse the repository at this point in the history
Explicitly manage secrets, add capability to attach source tarball
  • Loading branch information
nwiltsie authored Jan 28, 2025
2 parents a452e40 + cc40672 commit e539242
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 24 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/internal-alias.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,3 @@ permissions:
jobs:
update-alias:
uses: ./.github/workflows/wf-alias-release.yaml
# Secrets are only required until tool-create-release is made public
secrets: inherit
3 changes: 2 additions & 1 deletion .github/workflows/internal-finalize.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
finalize-release:
if: ${{ github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'automation-create-release') }}
uses: ./.github/workflows/wf-finalize-release.yaml
secrets: inherit
with:
draft: false
secrets:
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/internal-prepare.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ jobs:
with:
bump_type: ${{ inputs.bump_type }}
prerelease: ${{ inputs.prerelease }}
# Secrets are only required until tool-create-release is made public
secrets: inherit
secrets:
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}
30 changes: 25 additions & 5 deletions .github/workflows/wf-alias-release.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
---
on:
workflow_call:
inputs:
# These inputs are taken directly from stefanzweifel/git-auto-commit-action
commit-user-name:
type: string
description: Name used for the commit user
required: false
default: github-actions[bot]
commit-user-email:
type: string
description: Email address used for the commit user
required: false
default: 41898282+github-actions[bot]@users.noreply.github.com
secrets:
token:
description: >
Personal access token (PAT) used to fetch the repository. Required
if the repository has any private submodules.
required: false

jobs:
alias-release:
Expand All @@ -14,7 +32,7 @@ jobs:
env:
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.token || github.token }}
run: |
ACTION_DATA=$(gh api "repos/$REPO/actions/runs/$RUN_ID")
echo "::debug::$ACTION_DATA"
Expand All @@ -27,14 +45,14 @@ jobs:
repository: uclahs-cds/tool-create-release
path: reusable
ref: ${{ steps.workflow-parsing.outputs.SHA }}
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}

- name: Checkout calling repository
uses: actions/checkout@v4
with:
path: caller
fetch-depth: 0
fetch-tags: true
token: ${{ secrets.token || github.token }}

- name: Set up python
uses: actions/setup-python@v5
Expand All @@ -47,9 +65,11 @@ jobs:
# Update the alias if necessary
- id: alias-release
run: |
git config --file "$REPO_DIR/.git/config" user.name "github-actions[bot]"
git config --file "$REPO_DIR/.git/config" user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --file "$REPO_DIR/.git/config" user.name "$COMMIT_USER"
git config --file "$REPO_DIR/.git/config" user.email "$COMMIT_EMAIL"
alias-release "$REPO_DIR" "$GITHUB_REF"
env:
REPO_DIR: caller
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.token || github.token }}
COMMIT_USER: ${{ inputs.commit-user-name }}
COMMIT_EMAIL: ${{ inputs.commit-user-email }}
39 changes: 35 additions & 4 deletions .github/workflows/wf-finalize-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ on:
description: If true (the default), draft the release for later manual approval.
type: boolean
default: true
attach-tarball:
description: If true, attach a tarball including all submodules to the release.
type: boolean
default: false

secrets:
token:
description: >
Personal access token (PAT) used to fetch the repository and submodules.
Required if `draft` is false (to allow triggering alias workflow) or if
`attach-tarball` is true _and_ one or more of the submodules are private.
required: false

jobs:
finalize-release:
Expand All @@ -19,7 +31,7 @@ jobs:
env:
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.token || github.token }}
run: |
ACTION_DATA=$(gh api "repos/$REPO/actions/runs/$RUN_ID")
echo "::debug::$ACTION_DATA"
Expand All @@ -32,7 +44,6 @@ jobs:
repository: uclahs-cds/tool-create-release
path: reusable
ref: ${{ steps.workflow-parsing.outputs.SHA }}
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}

- name: Set up python
uses: actions/setup-python@v5
Expand All @@ -42,9 +53,29 @@ jobs:
# Install the bundled package
- run: pip install ./reusable

- name: Establish variables for tarball attachment
id: set-repo-name
run: |
REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2)
echo "REPO_NAME=$REPO_NAME" >> "$GITHUB_OUTPUT"
mkdir source
echo "CLONE_PATH=source/$REPO_NAME" >> "$GITHUB_OUTPUT"
# Only check out the calling repository if we're going to attach a
# tarball to the release
- name: Clone repository to create tarball
uses: actions/checkout@v4
if: ${{ inputs.attach-tarball }}
with:
path: ${{ steps.set-repo-name.outputs.CLONE_PATH }}
submodules: 'recursive'
token: ${{ secrets.token || github.token }}

- name: Finalize release
run: finalize-release "$DRAFT"
id: finalize-release
run: finalize-release "$DRAFT" --archival-path "$CLONE_PATH"
env:
DRAFT: ${{ inputs.draft }}
# Use the other token to allow the aliasing workflow to run
GH_TOKEN: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}
GH_TOKEN: ${{ secrets.token || github.token }}
CLONE_PATH: ${{ steps.set-repo-name.outputs.CLONE_PATH }}
19 changes: 15 additions & 4 deletions .github/workflows/wf-prepare-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,22 @@ on:
required: false
version_files:
type: string
description: Comma-separated list of relative paths to files with version numbers that should be updated. Every file must have exactly one line that looks like `version = "xxxx"` - some effort is made to handle different quoting styles, leading underscores, etc.
description: >
Comma-separated list of relative paths to files with version numbers
that should be updated. Every file must have exactly one line that
looks like `version = "xxxx"` - some effort is made to handle
different quoting styles, leading underscores, etc.
required: false
default: ""

secrets:
token:
description: >
Personal access token (PAT) used to open the pull request. Must be
provided in order for any actions to run in response to the PR
creation.
required: false

jobs:
prepare-release:
runs-on: ubuntu-latest
Expand All @@ -50,7 +62,7 @@ jobs:
env:
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.token || github.token }}
run: |
ACTION_DATA=$(gh api "repos/$REPO/actions/runs/$RUN_ID")
echo "::debug::$ACTION_DATA"
Expand All @@ -63,7 +75,6 @@ jobs:
repository: uclahs-cds/tool-create-release
path: reusable
ref: ${{ steps.workflow-parsing.outputs.SHA }}
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}

- name: Checkout calling repository
uses: actions/checkout@v4
Expand Down Expand Up @@ -104,7 +115,7 @@ jobs:
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}
token: ${{ secrets.token || github.token }}
path: caller
add-paths: ${{ inputs.changelog }},${{ inputs.version_files }}
commit-message: ${{ steps.bump-changelog.outputs.commit_message }}
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Add `attach-tarball` argument to finalize workflow to attach source tarball with release

### Changed

- Remove hard-coded UCLA secrets, add explicit `secrets` inputs to workflows

## [1.0.3] - 2024-11-01

### Fixed
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Usage of this tool requires adding three workflows to each calling repository (n

1. Create a new release with auto-generated notes and the target tag.
* By default the new release is a draft, so no public release or tag are created without user intervention.
1. Optionally, attach a source tarball including all submodules to the new release.
1. Comment on the release PR with a link to the new release.

```mermaid
Expand Down Expand Up @@ -113,7 +114,14 @@ Parameters can be specified using the [`with`](https://docs.github.com/en/action
| `wf-prepare-release.yaml` | `changelog` | string | no | Relative path to the CHANGELOG file. Defaults to `./CHANGELOG.md`. |
| `wf-prepare-release.yaml` | `timezone` | string | no | IANA timezone to use when calculating the current date for the CHANGELOG. Defaults to `America/Los_Angeles`. |
| `wf-finalize-release.yaml` | `draft` | boolean | no | If true (the default), mark the new release as a draft and require manual intervention to continue. |
| `wf-finalize-release.yaml` | `attach-tarball` | boolean | no | If true (not the default), attach a tarball of the repository source, including all submodules, to the release. |
| `wf-alias-release.yaml` | `commit-user-name` | string | no | User name to use while tagging new commits (defaults to `github-actions[bot]`) |
| `wf-alias-release.yaml` | `commit-user-email` | string | no | User email to use while tagging new commits (defaults to `41898282+github-actions[bot]@users.noreply.github.com`) |

All four workflows also accept a `token` secret which is required for full functionality (e.g. CI/CD checks on the opened pull request). The provided [personal access token](https://github.com/settings/tokens/new) should be stored as a secret in the repository and have the following scopes:

* `repo`
* `workflow`

### Updating hard-coded strings with `version_files`

Expand Down
58 changes: 56 additions & 2 deletions bumpchanges/finalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional


from .logging import setup_logging, NOTICE, LoggingMixin
Expand Down Expand Up @@ -75,7 +76,7 @@ def __post_init__(self):
except ValueError:
pass

def create(self, draft: bool):
def create(self, draft: bool, archival_path: Optional[Path]):
"""Create the release and return the URL."""
args = [
"gh",
Expand Down Expand Up @@ -119,6 +120,45 @@ def create(self, draft: bool):
width=2000,
)

# Create and upload a tarball if the archival path exists
if archival_path:
self.logger.info("Creating tarball")

tarball = Path(
os.environ["GITHUB_WORKSPACE"],
f"{archival_path.name}-{self.tag}.tar.gz",
)

subprocess.run(
["tar", "--exclude-vcs", "-czvf", tarball, archival_path.name],
cwd=archival_path.parent,
check=True,
)

try:
subprocess.run(
[
"gh",
"release",
"upload",
self.tag,
"--repo",
self.owner_repo,
f"{tarball}#Source code with submodules (tar.gz)",
],
check=True,
)
comment_body += (
"\n\nA source tarball including all submodules "
"has been attached to the release."
)

except subprocess.CalledProcessError:
self.logger.error("Failed to attach tarball to release!")
comment_body += (
"\n\n**ERROR:** Failed to attach source tarball to release!"
)

subprocess.run(
[
"gh",
Expand All @@ -140,15 +180,29 @@ def entrypoint():

parser = argparse.ArgumentParser()
parser.add_argument("draft", type=str_to_bool)
parser.add_argument(
"--archival-path", help="Path to a directory to tar and attach to the release"
)

args = parser.parse_args()

try:
# Parse the environment to create the release
new_release = PreparedRelease.from_environment()

archival_path = Path(args.archival_path) if args.archival_path else None
if archival_path and not archival_path.exists():
archival_path = None

if archival_path:
# Sanity-check that the cloned name matches the environment
repo_name = new_release.owner_repo.split("/", maxsplit=1)[-1]
if repo_name != archival_path.name:
raise RuntimeError(f"{repo_name} != {archival_path.name}!")

# Draft or create the release
new_release.create(args.draft)
new_release.create(args.draft, archival_path)

except:
logging.getLogger(__name__).exception("Failed to create new release")
raise
3 changes: 2 additions & 1 deletion templates/alias-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ permissions:
jobs:
update-alias:
uses: uclahs-cds/tool-create-release/.github/workflows/wf-alias-release.yaml@v1
secrets: inherit
secrets:
token: ${{ secrets.YOUR_PAT }}
4 changes: 3 additions & 1 deletion templates/finalize-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:
finalize-release:
if: ${{ github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'automation-create-release') }}
uses: uclahs-cds/tool-create-release/.github/workflows/wf-finalize-release.yaml@v1
secrets: inherit
with:
draft: false
attach-tarball: false
secrets:
token: ${{ secrets.YOUR_PAT }}
3 changes: 2 additions & 1 deletion templates/prepare-release-non-semantic-version.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ jobs:
with:
bump_type: "exact"
exact_version: ${{ inputs.version }}
secrets: inherit
secrets:
token: ${{ secrets.YOUR_PAT }}
3 changes: 2 additions & 1 deletion templates/prepare-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ jobs:
with:
bump_type: ${{ inputs.bump_type }}
prerelease: ${{ inputs.prerelease }}
secrets: inherit
secrets:
token: ${{ secrets.YOUR_PAT }}

0 comments on commit e539242

Please sign in to comment.