Skip to content
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

Add prepare-release action #236

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
876e827
Add prepare-release action
kenodegard Dec 10, 2024
379990b
Create release branch if missing
kenodegard Dec 10, 2024
7972292
Correct inputs
kenodegard Dec 10, 2024
eddae7f
Add requirements file
kenodegard Dec 10, 2024
6421c56
Use token for cloning
kenodegard Dec 10, 2024
35bc53c
Fix variable
kenodegard Dec 10, 2024
660a02b
Use specialized tokens
kenodegard Dec 11, 2024
62f5f50
Update README.md
kenodegard Dec 11, 2024
efec99d
Remove branch-token
kenodegard Dec 12, 2024
66f5954
Add back fork-token to cloning
kenodegard Dec 12, 2024
2edc990
Rename tokens
kenodegard Dec 12, 2024
598af2a
Use GH API to create branch remotely
kenodegard Dec 12, 2024
030bc7d
Correct tokens
kenodegard Dec 12, 2024
42bf103
Remove pip caching
kenodegard Dec 13, 2024
2ac25e4
Use =
kenodegard Dec 13, 2024
9690c5e
Correct forking
kenodegard Dec 13, 2024
8637354
Add branch-sha input
kenodegard Dec 13, 2024
df5bad0
Workaround for `gh repo fork`
kenodegard Dec 13, 2024
2319569
Remove fork-token default
kenodegard Dec 13, 2024
65d3a14
Debugging
kenodegard Dec 13, 2024
3d3c224
Add cache for pip packages
kenodegard Dec 17, 2024
315b336
Use create-fork action
kenodegard Dec 18, 2024
40a3d03
Improve descriptions
kenodegard Dec 18, 2024
8ac5901
Fix token
kenodegard Dec 18, 2024
fe72127
Merge remote-tracking branch 'upstream/main' into prepare-release
kenodegard Jan 24, 2025
f3e6fbe
Add prepare-release to tests.yml
kenodegard Jan 24, 2025
2e15e0c
Update PR body
kenodegard Jan 24, 2025
57aecd7
Checkout conda/actions before testing prepare-release
kenodegard Jan 24, 2025
8871c9b
Limit tests to only when there are prepare-release changes
kenodegard Jan 24, 2025
5f954cb
Use correct path
kenodegard Jan 24, 2025
9a868f6
Update token
kenodegard Jan 24, 2025
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
38 changes: 38 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ jobs:
filters: |
code:
- 'template-files/**'

- name: Comment on PR
if: github.event_name == 'pull_request' && steps.filter.outputs.code == 'true'
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0
Expand All @@ -130,6 +131,43 @@ jobs:
${{ steps.templates-error.outputs.summary }}
GITHUB_TOKEN: ${{ secrets.SANDBOX_TEMPLATE_TOKEN }}

prepare-release:
runs-on: ubuntu-latest
steps:
- name: Filter Changes
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: filter
with:
filters: |
code:
- 'prepare-release/**'

- name: Checkout Source
if: steps.filter.outputs.code == 'true'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Prepare Major Release
if: steps.filter.outputs.code == 'true'
uses: ./prepare-release
with:
repository: conda-sandbox/releases
version: ${{ github.event.pull_request.number }}.0.0
branch: ${{ github.event.pull_request.number }}.0.x
branch-sha: main
token: ${{ secrets.SANDBOX_RELEASES_TOKEN }}
fork-token: ${{ secrets.FORK_TOKEN }}

- name: Prepare Patch Release
if: steps.filter.outputs.code == 'true'
uses: ./prepare-release
with:
repository: conda-sandbox/releases
version: 0.0.${{ github.event.pull_request.number }}
branch: 0.0.x
branch-sha: main
token: ${{ secrets.SANDBOX_RELEASES_TOKEN }}
fork-token: ${{ secrets.FORK_TOKEN }}

# required check
analyze:
needs: [pytest, read-file, template-files]
Expand Down
79 changes: 79 additions & 0 deletions prepare-release/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Prepare Release

This action prepares a release on GitHub:
1. Running `towncrier` to update the changelog.

## Action Inputs

| Name | Description | Default |
| ---- | ----------- | ------- |
| `version` | Version to release. | **Required** |
| `branch` | Target branch to use for the release. | `${{ github.even.repository.default_branch` |
| `changelog-author` | Git-format author to use for the changelog commits. | @conda-bot |
| `token` | GitHub token to create release branch if missing and the pull request.<br>Fine-grained PAT: `pull-request: write; contents: write` | `${{ github.token }}` |
| `fork-token` | GitHub token to create and push to the fork/branch.<br>Fine-grained PAT: `administration: write; contents: write` | `${{ github.token }}` |

## Sample Workflows

### Basic Workflow

```yaml
name: Prepare Release

on:
workflow_dispatch:
inputs:
version:
description: The version to release.
required: true

permissions:
contents: write
pull-requests: write

jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Prepare Release
uses: conda/actions/prepare-release
with:
version: ${{ inputs.version }}
```

### Dynamic Branch Workflow

```yaml
name: Prepare Release

on:
workflow_dispatch:
inputs:
version:
description: The version to release.
required: true

permissions:
contents: write
pull-requests: write

jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Get Branch
shell: python
run: |
from os import environ
from pathlib import Path

# derive the branch from the version by dropping the `PATCH` and using `.x`
branch = "${{ inputs.version }}".rsplit(".", 1)[0]
Path(environ["GITHUB_ENV"]).write_text(f"BRANCH={branch}.x")

- name: Prepare Release
uses: conda/actions/prepare-release
with:
version: ${{ inputs.version }}
branch: ${{ env.BRANCH }}
```
129 changes: 129 additions & 0 deletions prepare-release/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
name: Prepare Release
description: Prepares a release by running towncrier and creating a PR with the changes.
inputs:
version:
description: The version to release.
required: true
branch:
description: The target branch to use for the release.
default: ${{ github.event.repository.default_branch }}
branch-sha:
description: The SHA from which to create the target branch if missing.
default: ${{ github.event.repository.default_branch }}
changelog-author:
description: Git-format author to use for the changelog commits.
default: Conda Bot <[email protected]>
token:
description: |
GitHub token to create release branch if missing and the pull request.
Fine-grained PAT: `pull-request: write; contents: write`
default: ${{ github.token }}
fork-token:
description: |
GitHub token to create and push to the fork.
Fine-grained PAT: `administration: write; contents: write`
# default: ${{ inputs.token }}
comment-blurb:
description: Comment to add to the PR.
default: ✂️ snip snip ✂️ the making of a new release.
repository:
description: The repository to use for the release.
default: ${{ github.repository }}

runs:
using: composite
steps:
- name: Checkout Source
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
path: .github_cache/actions/prepare-release/${{ inputs.repository }}
repository: ${{ inputs.repository }}
token: ${{ inputs.token }}

- name: Create Branch
shell: bash
run: |
if ! git -C ${SOURCE} fetch origin "${{ inputs.branch }}"; then
# if branch doesn't exist, create it from the default branch
gh api \
-X POST \
-H "Accept: application/vnd.github+json" \
"/repos/${{ inputs.repository }}/git/refs" \
-f ref="refs/heads/${{ inputs.branch }}" \
-f sha="$(git -C ${SOURCE} rev-parse ${{ inputs.branch-sha }})"
fi
git -C ${SOURCE} fetch origin
git -C ${SOURCE} checkout "${{ inputs.branch }}"
git -C ${SOURCE} pull origin "${{ inputs.branch }}"
env:
GH_TOKEN: ${{ inputs.token }}
SOURCE: .github_cache/actions/prepare-release/${{ inputs.repository }}

# `hashFiles` only works on files within the working directory, since `requirements.txt`
# is not in the working directory we need to manually compute the SHA256 hash
- name: Compute Hash
id: hash
shell: bash
run: echo hash=$(sha256sum ${{ github.action_path }}/requirements.txt | awk '{print $1}') >> $GITHUB_OUTPUT

- name: Pip Cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ~/.cache/pip
key: ${{ github.workflow }}-prepare-release-${{ steps.hash.outputs.hash }}

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '>=3.9'

- name: Pip Install
shell: bash
run: pip install --quiet -r ${{ github.action_path }}/requirements.txt

- name: Pip List
shell: bash
run: pip list

- name: Run Towncrier
shell: bash
run: >-
towncrier build
--version=${{ inputs.version }}
--dir=.github_cache/actions/prepare-release/${{ inputs.repository }}

# - name: Detect Contributors

# - name: Detect First-Time Contributors

- name: Create Fork
id: create-fork
uses: conda/actions/create-fork@7873f9d7c90877290866eb893b8f6eff2e88429a # v25.1.2
with:
token: ${{ inputs.fork-token || inputs.token }}

- name: Create PR
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
with:
# push to the fork
branch-token: ${{ inputs.fork-token || inputs.token }}
push-to-fork: ${{ steps.create-fork.outputs.fork }}
branch: changelog-${{ inputs.version }}
commit-message: Changelog ${{ inputs.version }}
author: ${{ inputs.changelog-author }}
committer: ${{ inputs.changelog-author }}
# create PR
token: ${{ inputs.token }}
base: ${{ inputs.branch }}
delete-branch: true
title: Changelog ${{ inputs.version }}
# GitHub flavored markdown reinvents how paragraphs work, adjoined lines of text are not
# concatenated so instead we rely on YAML multi-line + extra newlines
body: >-
${{ inputs.comment-blurb }}


<sub>PR generated by ${{ github.html_url }}/actions/runs/${{ github.run_id }},
triggered by ${{ github.event_name == 'schedule' && 'cron' || format('@{0}', github.triggering_actor) }}
via ${{ github.event_name }}.</sub>
1 change: 1 addition & 0 deletions prepare-release/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
towncrier
Loading