Skip to content

ci: release-please + publish + contributors automation - #1

Merged
smorin merged 7 commits into
mainfrom
ci-automation
Jun 8, 2026
Merged

smorin merged 7 commits into
mainfrom
ci-automation

Conversation

@smorin

@smorin smorin commented Jun 8, 2026 •

Copy link
Copy Markdown
Contributor

Adds release automation (release-please → tag → OIDC publish to TestPyPI then PyPI), a commitlint Conventional-Commits gate, and contributors-please automation.

Design: docs/superpowers/specs/2026-06-07-ci-release-contributors-design.md
Plan: docs/superpowers/plans/2026-06-07-ci-release-contributors.md

Note: GitHub environments testpypi/pypi created; PyPI/TestPyPI trusted publishers point at publish.yml.

Summary by CodeRabbit

  • Documentation

    • Added contributors list and changelog files.
  • Chores

    • Established automated release and PyPI publishing workflows.
    • Configured commit message validation standards.

Copilot AI review requested due to automatic review settings June 8, 2026 05:24
@coderabbitai

coderabbitai Bot commented Jun 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR establishes the complete CI/CD and release infrastructure for the mockcast project, including conventional commit enforcement, automated release versioning via release-please, multi-stage PyPI publishing with trusted publishing, and contributor list management.

Changes

Release Infrastructure and CI/CD

Layer / File(s) Summary
Conventional Commit Enforcement
commitlint.config.mjs, .github/workflows/commitlint.yml
Defines commit message linting rules requiring lowercase enumerated types, non-empty subject/type, no trailing periods, and header length limits; enforces via GitHub Actions on pull requests to main.
Release Configuration and Versioning
release-please-config.json, .release-please-manifest.json
Configures release-please for Python releases with version mapping from pyproject.toml, PR title patterns, and changelog section taxonomy.
Automated Release Orchestration
.github/workflows/release-please.yml
Implements release-please GitHub App workflow triggered on main pushes; creates releases and conditionally regenerates/commits uv.lock via a secondary sync-uv-lock job when a release is created.
PyPI Publishing Pipeline
.github/workflows/publish.yml
Multi-stage workflow triggered on version tags, validates tag commit is on main, verifies tag version matches pyproject.toml, builds distributions, publishes to TestPyPI for verification, then publishes to production PyPI using trusted publishing.
Contributor Tracking and List Generation
.contributors.yml, .github/workflows/update-contributors.yml
Configures contributor classification by path patterns (docs, quality, code), identity mapping, and GitHub Actions workflow that regenerates CONTRIBUTORS.md when repository content changes.
Release Documentation Scaffolding
CHANGELOG.md, CONTRIBUTORS.md
Initializes changelog and contributors documentation with headers and placeholder markers for automated tooling insertion.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A release pipeline springs to life,
From commit lint to PyPI strife,
Contributors tracked, versions blessed,
Automation puts code to the test!
Trust and convention lead the way,
While mockcast builds a brighter day. 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: CI automation for release-please, publish workflows, and contributors management.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci-automation

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
release-please-config.json (1)

18-27: ⚡ Quick win

Align changelog sections with allowed commit types.

build, style, and revert are allowed by commitlint.config.mjs but not explicitly mapped here. Add them (or explicitly hide them) to keep release notes deterministic.

Suggested alignment diff
   "changelog-sections": [
     { "type": "feat", "section": "Features" },
     { "type": "fix", "section": "Bug Fixes" },
     { "type": "perf", "section": "Performance" },
     { "type": "refactor", "section": "Refactoring" },
     { "type": "docs", "section": "Documentation" },
     { "type": "ci", "section": "CI/CD" },
     { "type": "test", "section": "Testing" },
+    { "type": "build", "section": "Build System", "hidden": true },
+    { "type": "style", "section": "Style", "hidden": true },
+    { "type": "revert", "section": "Reverts" },
     { "type": "chore", "section": "Miscellaneous", "hidden": true }
   ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@release-please-config.json` around lines 18 - 27, The changelog-sections
array is missing mappings for commit types allowed by commitlint (build, style,
revert); update the "changelog-sections" configuration to include entries for {
"type": "build" }, { "type": "style" }, and { "type": "revert" } — either map
them to explicit section names (e.g., "Build", "Style", "Reverts") or add them
with "hidden": true so release-please produces deterministic release notes;
ensure you modify the existing "changelog-sections" array in
release-please-config.json accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.contributors.yml:
- Around line 40-43: The identity_map entry currently contains a personal email
for login "smorin"; remove or replace the plaintext PII by updating the
identity_map mapping (the "login: smorin" and its "emails" list) to use the
GitHub no-reply address (e.g., `@users.noreply.github.com`) or move the mapping
out of the repo into a private/secret config; ensure the commit removes the
personal email from .contributors.yml and preserves the login mapping if needed
with the no-reply address.

In @.github/workflows/commitlint.yml:
- Around line 19-24: The workflow currently references mutable action tags
"actions/checkout@v4" and "wagoid/commitlint-github-action@v6"; replace those
with the corresponding immutable commit SHAs to harden CI supply-chain integrity
(locate the two uses of actions/checkout and wagoid/commitlint-github-action in
the file and substitute the tag suffixes with the full commit SHA values for the
exact versions you intend to pin, keeping the existing with: configFile:
commitlint.config.mjs and fetch-depth: 0 settings intact).

In @.github/workflows/publish.yml:
- Around line 38-46: The workflow step "Verify tag matches pyproject version"
relies on tomllib (Python 3.11+) but doesn't pin Python; update the job to run
actions/setup-python@v5 (or later) and set python-version to "3.11" (or
">=3.11") before the step that defines TAG_VERSION and PKG_VERSION so tomllib is
available; ensure the setup-python action precedes the shell run that computes
PKG_VERSION.

In @.github/workflows/release-please.yml:
- Around line 35-73: The sync-uv-lock job runs after release-please has already
created the release tag, meaning any uv.lock updates happen after the tag points
to a commit with an out-of-sync lockfile. Move the uv.lock synchronization to
occur before the release tag is created by either removing the post-release
sync-uv-lock job and configuring release-please to ensure uv.lock is in sync as
part of its PR validation (using a pre-commit hook or additional CI check), or
by adding a validation step that fails the release if uv.lock is out of sync
rather than fixing it after the fact.

In @.github/workflows/update-contributors.yml:
- Around line 11-15: Remove the unnecessary permissions entry by deleting the
"issues: write" permission under the permissions block so the workflow token
only has the required "contents: write" and "pull-requests: write" entries;
update the permissions block (permissions, contents, pull-requests) accordingly
and verify the workflow still operates when creating/updating PRs.

---

Nitpick comments:
In `@release-please-config.json`:
- Around line 18-27: The changelog-sections array is missing mappings for commit
types allowed by commitlint (build, style, revert); update the
"changelog-sections" configuration to include entries for { "type": "build" }, {
"type": "style" }, and { "type": "revert" } — either map them to explicit
section names (e.g., "Build", "Style", "Reverts") or add them with "hidden":
true so release-please produces deterministic release notes; ensure you modify
the existing "changelog-sections" array in release-please-config.json
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b50d3fc6-0a54-4599-a366-4cf7217fbd24

📥 Commits

Reviewing files that changed from the base of the PR and between 5aac267 and 995bcb2.

📒 Files selected for processing (10)
  • .contributors.yml
  • .github/workflows/commitlint.yml
  • .github/workflows/publish.yml
  • .github/workflows/release-please.yml
  • .github/workflows/update-contributors.yml
  • .release-please-manifest.json
  • CHANGELOG.md
  • CONTRIBUTORS.md
  • commitlint.config.mjs
  • release-please-config.json

Comment thread .contributors.yml
Comment on lines +40 to +43
identity_map:
- login: smorin
emails:
- steve.morin@gmail.com

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid committing personal email addresses in repo config.

identity_map currently contains a personal email in plaintext. Prefer GitHub @users.noreply.github.com (or move mapping to a secret/private config) to avoid unnecessary PII exposure in-repo.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.contributors.yml around lines 40 - 43, The identity_map entry currently
contains a personal email for login "smorin"; remove or replace the plaintext
PII by updating the identity_map mapping (the "login: smorin" and its "emails"
list) to use the GitHub no-reply address (e.g., `@users.noreply.github.com`) or
move the mapping out of the repo into a private/secret config; ensure the commit
removes the personal email from .contributors.yml and preserves the login
mapping if needed with the no-reply address.

Comment on lines +19 to +24
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v6
with:
configFile: commitlint.config.mjs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin GitHub Actions to immutable SHAs.

Line 19 and Line 22 use mutable tags (@v4, @v6), which weakens CI supply-chain integrity. Pin to full commit SHAs.

Suggested hardening diff
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<full-length-commit-sha>
         with:
           fetch-depth: 0
-      - uses: wagoid/commitlint-github-action@v6
+      - uses: wagoid/commitlint-github-action@<full-length-commit-sha>
         with:
           configFile: commitlint.config.mjs
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/commitlint.yml around lines 19 - 24, The workflow
currently references mutable action tags "actions/checkout@v4" and
"wagoid/commitlint-github-action@v6"; replace those with the corresponding
immutable commit SHAs to harden CI supply-chain integrity (locate the two uses
of actions/checkout and wagoid/commitlint-github-action in the file and
substitute the tag suffixes with the full commit SHA values for the exact
versions you intend to pin, keeping the existing with: configFile:
commitlint.config.mjs and fetch-depth: 0 settings intact).

Comment on lines +38 to +46
- name: Verify tag matches pyproject version
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION="$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")"
if [ "${TAG_VERSION}" != "${PKG_VERSION}" ]; then
echo "::error::tag ${TAG_VERSION} != pyproject ${PKG_VERSION}"
exit 1
fi
echo "Tag matches pyproject version (${TAG_VERSION})."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check the default Python version on ubuntu-latest runner

# Query GitHub Actions documentation or test in the runner
echo "Checking ubuntu-latest default Python version..."
echo "Note: As of June 2026, ubuntu-latest is Ubuntu 24.04 with Python 3.12"
echo "Verify at: https://github.com/actions/runner-images"

Repository: smorinlabs/mockcast

Length of output: 1941


🌐 Web query:

GitHub Actions runner-images ubuntu-latest default Python version 3.11 3.12

💡 Result:

On GitHub Actions, the ubuntu-latest runner image (currently Ubuntu 24.04) does not have a single fixed "default" Python version that remains static; instead, it includes multiple pre-cached versions of Python [1][2]. As of June 2026, the Ubuntu 24.04 image includes various versions such as 3.10, 3.11, 3.12, and 3.13 [1]. It is important to note that relying on the pre-installed default Python version found in the system PATH is discouraged, as this version can change unexpectedly when GitHub updates the runner images [3][4][5]. GitHub officially recommends explicitly specifying the desired Python version in your workflow using the actions/setup-python action to ensure consistency and reliability [3][4][5]. For example, you can set the Python version as follows: - uses: actions/setup-python@v6 with: python-version: '3.12' By using actions/setup-python, the action will check the local tool cache for the specified version or download it on-the-fly if it is not already available, ensuring your workflow uses the exact version you require regardless of the underlying runner image's default [3][5].

Citations:


🌐 Web query:

tomllib available Python 3.11 documentation github actions setup-python recommended

💡 Result:

The tomllib module is included in the Python standard library starting with Python 3.11 [1][2]. It provides functionality for parsing TOML files [1][3]. Regarding GitHub Actions, it is recommended to use the actions/setup-python action to explicitly define the Python version in your workflows [4][5]. This ensures consistency across different runners, as the default version of Python available on runners can vary and change unexpectedly [4][5][6]. To set up your environment, you can use the following configuration in your workflow file: steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: '3.11' - run: python -c "import tomllib; print('tomllib is available')" By explicitly specifying python-version: '3.11' (or later), you ensure that the environment has access to the tomllib module [4][5][7]. The setup-python action is the official and recommended method for configuring Python versions in GitHub Actions [5][6].

Citations:


Pin Python for tomllib to avoid runner-image drift

The workflow uses tomllib, which is available only in Python 3.11+. Since ubuntu-latest ships multiple Python versions and the “default” Python on PATH can change when runner images update, the step should not rely on an implicit Python version. GitHub recommends explicitly selecting the Python version with actions/setup-python.

Recommendation: Use actions/setup-python@v5 (or later) to install Python >= 3.11 before running the tag/version check.

Option 2: Explicit Python setup
+      - uses: actions/setup-python@v5
+        with:
+          python-version: '3.11'
+
       - name: Verify tag matches pyproject version
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml around lines 38 - 46, The workflow step
"Verify tag matches pyproject version" relies on tomllib (Python 3.11+) but
doesn't pin Python; update the job to run actions/setup-python@v5 (or later) and
set python-version to "3.11" (or ">=3.11") before the step that defines
TAG_VERSION and PKG_VERSION so tomllib is available; ensure the setup-python
action precedes the shell run that computes PKG_VERSION.

Comment on lines +35 to +73
sync-uv-lock:
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/create-github-app-token@v3
id: app-token
with:
app-id: ${{ secrets.RELEASE_PLEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_PLEASE_PRIVATE_KEY }}

- uses: actions/checkout@v4
with:
token: ${{ steps.app-token.outputs.token }}
ref: main

- uses: astral-sh/setup-uv@v6
with:
enable-cache: true

- name: Regenerate uv.lock from pyproject
run: uv lock

- name: Commit uv.lock if changed
env:
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
run: |
if git diff --quiet uv.lock; then
echo "uv.lock already in sync; nothing to commit."
exit 0
fi
git config user.email "${APP_SLUG}[bot]@users.noreply.github.com"
git config user.name "${APP_SLUG}[bot]"
git add uv.lock
git commit -m "chore(release): sync uv.lock for ${TAG_NAME}"
git push origin main

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Race condition: sync-uv-lock runs after the release tag is created.

The sync-uv-lock job runs when release_created == 'true', which means release-please has already created the git tag. If uv.lock needs updating, this workflow will:

  1. Create release tag pointing to commit A (with out-of-sync uv.lock)
  2. Commit updated uv.lock as commit B on main
  3. Leave the release tag pointing to the old state

Impact: Users checking out the release tag will get an inconsistent lockfile. The tagged release doesn't include the synchronized uv.lock.

Recommended fix: Ensure uv.lock is synchronized in the release-please PR itself (e.g., via a pre-commit hook or CI check on the PR) rather than fixing it post-release. Alternatively, consider failing the release if uv.lock is out of sync, rather than silently fixing it afterward.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-please.yml around lines 35 - 73, The sync-uv-lock
job runs after release-please has already created the release tag, meaning any
uv.lock updates happen after the tag points to a commit with an out-of-sync
lockfile. Move the uv.lock synchronization to occur before the release tag is
created by either removing the post-release sync-uv-lock job and configuring
release-please to ensure uv.lock is in sync as part of its PR validation (using
a pre-commit hook or additional CI check), or by adding a validation step that
fails the release if uv.lock is out of sync rather than fixing it after the
fact.

Comment on lines +11 to +15
permissions:
contents: write
pull-requests: write
issues: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Drop unnecessary issues: write permission from the workflow token.

This job appears to only open/update PR content. Keeping issues: write broadens token capabilities without clear need; remove it unless the action explicitly requires issue mutations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/update-contributors.yml around lines 11 - 15, Remove the
unnecessary permissions entry by deleting the "issues: write" permission under
the permissions block so the workflow token only has the required "contents:
write" and "pull-requests: write" entries; update the permissions block
(permissions, contents, pull-requests) accordingly and verify the workflow still
operates when creating/updating PRs.

@smorin
smorin merged commit d5d29a6 into main Jun 8, 2026
4 checks passed
@smorin
smorin deleted the ci-automation branch June 8, 2026 05:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds CI automation to standardize releases and maintenance tasks for the Python package: release PR/tag creation via release-please, OIDC-based publishing to TestPyPI then PyPI, Conventional Commits enforcement, and automated contributor list updates.

Changes:

  • Introduces release-please configuration + manifest, and seeds CHANGELOG.md.
  • Adds GitHub Actions workflows for release-please tagging, publishing to TestPyPI→PyPI, and commitlint gating on PRs.
  • Adds contributors-please automation configuration and a seeded CONTRIBUTORS.md.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
release-please-config.json Configures release-please (python strategy, changelog sections, extra files).
.release-please-manifest.json Seeds manifest-mode version tracking for release-please.
CHANGELOG.md Seeds a release-please-managed changelog.
.github/workflows/release-please.yml Runs release-please on main and optionally syncs uv.lock post-release.
.github/workflows/publish.yml Builds and publishes tagged releases to TestPyPI then PyPI via OIDC.
.github/workflows/commitlint.yml Enforces Conventional Commits on PRs using commitlint.
commitlint.config.mjs Self-contained commitlint rule set (no external extends).
.github/workflows/update-contributors.yml Automates contributor list updates via PRs on pushes to main.
.contributors.yml Configures contributors-please behavior (classification, ignore list, identity map).
CONTRIBUTORS.md Seeds contributors file with markers for automation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +13 to +15
"extra-files": [
{ "type": "toml", "path": "pyproject.toml", "jsonpath": "$.project.version" }
]
Comment on lines +25 to +27
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
Comment on lines +40 to +42
TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION="$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")"
if [ "${TAG_VERSION}" != "${PKG_VERSION}" ]; then
Comment on lines +53 to +56
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants