Skip to content
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
15 changes: 15 additions & 0 deletions .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Lint Commit Messages
on:
pull_request:
branches: [ main ]

permissions:
contents: read
pull-requests: read

jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: wagoid/commitlint-github-action@v6
130 changes: 130 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Based on https://python-semantic-release.readthedocs.io/en/latest/configuration/automatic-releases/github-actions.html#examples

name: Continuous Delivery

on:
push:
branches:
- main

# default: least privileged permissions across all jobs
permissions:
contents: read

jobs:
release:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-release-${{ github.ref_name }}
cancel-in-progress: false

permissions:
contents: write

steps:
# Note: We checkout the repository at the branch that triggered the workflow
# with the entire history to ensure to match PSR's release branch detection
# and history evaluation.
# However, we forcefully reset the branch to the workflow sha because it is
# possible that the branch was updated while the workflow was running. This
# prevents accidentally releasing un-evaluated changes.
- name: Setup | Checkout Repository on Release Branch
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
fetch-depth: 0

- name: Setup | Force release branch to be at workflow sha
run: |
git reset --hard ${{ github.sha }}

- name: Evaluate | Verify upstream has NOT changed
# Last chance to abort before causing an error as another PR/push was applied to
# the upstream branch while this workflow was running. This is important
# because we are committing a version change (--commit). You may omit this step
# if you have 'commit: false' in your configuration.
#
# You may consider moving this to a repo script and call it from this step instead
# of writing it in-line.
shell: bash
run: |
set +o pipefail

UPSTREAM_BRANCH_NAME="$(git status -sb | head -n 1 | cut -d' ' -f2 | grep -E '\.{3}' | cut -d'.' -f4)"
printf '%s\n' "Upstream branch name: $UPSTREAM_BRANCH_NAME"

set -o pipefail

if [ -z "$UPSTREAM_BRANCH_NAME" ]; then
printf >&2 '%s\n' "::error::Unable to determine upstream branch name!"
exit 1
fi

git fetch "${UPSTREAM_BRANCH_NAME%%/*}"

if ! UPSTREAM_SHA="$(git rev-parse "$UPSTREAM_BRANCH_NAME")"; then
printf >&2 '%s\n' "::error::Unable to determine upstream branch sha!"
exit 1
fi

HEAD_SHA="$(git rev-parse HEAD)"

if [ "$HEAD_SHA" != "$UPSTREAM_SHA" ]; then
printf >&2 '%s\n' "[HEAD SHA] $HEAD_SHA != $UPSTREAM_SHA [UPSTREAM SHA]"
printf >&2 '%s\n' "::error::Upstream has changed, aborting release..."
exit 1
fi

printf '%s\n' "Verified upstream branch has not changed, continuing with release..."

- name: Action | Semantic Version Release
id: release
# Adjust tag with desired version if applicable.
uses: python-semantic-release/python-semantic-release@v10.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
git_committer_name: "github-actions"
git_committer_email: "actions@users.noreply.github.com"

- name: Publish | Upload to GitHub Release Assets
uses: python-semantic-release/publish-action@v10.1.0
if: steps.release.outputs.released == 'true'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.release.outputs.tag }}

- name: Upload | Distribution Artifacts
uses: actions/upload-artifact@v4
with:
name: distribution-artifacts
path: dist
if-no-files-found: error

deploy:
# 1. Separate out the deploy step from the publish step to run each step at
# the least amount of token privilege
# 2. Also, deployments can fail, and its better to have a separate job if you need to retry
# and it won't require reversing the release.
runs-on: ubuntu-latest
needs: release
if: ${{ needs.release.outputs.released == 'true' }}

permissions:
contents: read
id-token: write

steps:
- name: Setup | Download Build Artifacts
uses: actions/download-artifact@v4
id: artifact-download
with:
name: distribution-artifacts
path: dist

# see https://docs.pypi.org/trusted-publishers/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
print-hash: true
verbose: true
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# CHANGELOG

<!-- version list -->

## v1.0.0 (2025-06-16)

- Initial Release
128 changes: 128 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Contributing to workers-py

Thank you for your interest in contributing to workers-py! This document provides guidelines and information to help you contribute effectively.

## Table of Contents

- [Getting Started](#getting-started)
- [Development Setup](#development-setup)
- [Making Changes](#making-changes)
- [Commit Message Guidelines](#commit-message-guidelines)
- [Release Process](#release-process)
- [Submitting Changes](#submitting-changes)

## Getting Started

1. Fork the repository on GitHub
2. Clone your fork locally:
```bash
git clone https://github.com/YOUR_USERNAME/workers-py.git
cd workers-py
```
3. Set up the development environment (see [Development Setup](#development-setup))

## Development Setup

Follow the [Development section](https://github.com/cloudflare/workers-py#development) of the README for setting up your development environment.

### Development Dependencies

The project includes these development tools:
- **pytest**: Testing framework
- **ruff**: Fast Python linter
- **mypy**: Static type checking

## Making Changes

1. Create a new branch for your feature or bugfix:
```bash
git checkout -b your-username/your-change-name
```

2. Run our code formatter via `uvx ruff format` and linter via `uvx ruff fix .`

3. Add or update tests as needed

4. Run the test suite: `uv clean cache && uv run pytest`

## Commit Message Guidelines

This project uses automated semantic versioning via `python-semantic-release` which relies on
tags in the commit message to determine whether a release should be made.

### Commit Format

The format parsed by python-semantic-release is https://www.conventionalcommits.org/en/v1.0.0/#summary.
It looks something like this:

```
<tag>(<optional scope>): <subject>

<body>

<footer>
```

### Commit Tags

Including "BREAKING CHANGE" in the commit message (either in the body or footer) will trigger a release.

The following tags will trigger a release:

- **feat**: A new feature (triggers minor version bump)
- **fix**: A bug fix (triggers patch version bump)

The following tags will not trigger a release:

- **docs**: Documentation changes
- **style**: Code style changes (formatting, etc.)
- **refactor**: Code refactoring without feature changes
- **test**: Adding or updating tests
- **chore**: Maintenance tasks, dependency updates
- **ci**: CI/CD configuration changes

## Release Process

This project uses **python-semantic-release** for automated versioning and releases. Here's how it works:

### Automated Releases

1. **Version Calculation**: Based on conventional commit messages since the last release:
- `fix:` commits → patch version bump (1.0.0 → 1.0.1)
- `feat:` commits → minor version bump (1.0.0 → 1.1.0)
- `BREAKING CHANGE:` → major version bump (1.0.0 → 2.0.0)

2. **Release Trigger**: Releases are created automatically when changes are pushed to the `main` branch

3. **Release Artifacts**:
- Git tag (format: `v{version}`)
- Updated `pyproject.toml` version
- Changelog generation
- PyPI package publication (via GitHub Actions)

## Submitting Changes

1. **Push your branch** to your fork:
```bash
git push origin your-username/your-change-name
```

2. **Create a Pull Request** on GitHub with:
- Clear title following conventional commit format
- Description of changes made
- Any breaking changes clearly documented
- Explanation of how you tested your changes under a "Test Plan" section

3. **Review Process**:
- All CI checks must pass
- Code review from maintainers
- Tests must pass
- Documentation updates if needed

## Questions or Issues?

- Open an issue on GitHub for bugs or feature requests
- Check existing issues before creating new ones
- For questions, use GitHub Discussions or open an issue

Thank you for contributing to workers-py! 🚀
84 changes: 83 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "workers-py"
version = "1.0.0"
description = "A set of libraries and tools for Python Workers"
readme = "README.md"
requires-python = ">=3.10"
Expand All @@ -18,7 +19,6 @@ dependencies = [
"commentjson>=0.9.0",
"pyodide-cli",
]
dynamic = ["version"]

[dependency-groups]
dev = [
Expand All @@ -29,6 +29,9 @@ dev = [
"mypy>=1.0.0"
]

[project.optional-dependencies]
build = ["uv ~= 0.5.23"]

[project.scripts]
pywrangler = "pywrangler.cli:app"

Expand Down Expand Up @@ -63,3 +66,82 @@ source = "vcs"

[tool.hatch.build.targets.wheel]
packages = ["src/pywrangler"]

[tool.semantic_release]
assets = []
build_command_env = []
commit_message = "{version}\n\nAutomatically generated by python-semantic-release"
commit_parser = "conventional"
logging_use_named_masks = false
major_on_zero = true
allow_zero_version = false
no_git_verify = false
tag_format = "v{version}"
version_toml = ["pyproject.toml:project.version"]
build_command = """
python -m pip install -e .[build]
uv lock --offline
git add uv.lock
uv build
"""

[tool.semantic_release.branches.main]
match = "(main|master)"
prerelease_token = "rc"
prerelease = false

[tool.semantic_release.changelog]
exclude_commit_patterns = [
'''chore(?:\([^)]*?\))?: .+''',
'''ci(?:\([^)]*?\))?: .+''',
'''refactor(?:\([^)]*?\))?: .+''',
'''style(?:\([^)]*?\))?: .+''',
'''test(?:\([^)]*?\))?: .+''',
'''build\((?!deps\): .+)''',
'''Initial [Cc]ommit.*''',
]
mode = "update"
insertion_flag = "<!-- version list -->"
template_dir = "templates"

[tool.semantic_release.changelog.default_templates]
changelog_file = "CHANGELOG.md"
output_format = "md"
mask_initial_release = true

[tool.semantic_release.changelog.environment]
block_start_string = "{%"
block_end_string = "%}"
variable_start_string = "{{"
variable_end_string = "}}"
comment_start_string = "{#"
comment_end_string = "#}"
trim_blocks = false
lstrip_blocks = false
newline_sequence = "\n"
keep_trailing_newline = false
extensions = []
autoescape = false

[tool.semantic_release.commit_author]
env = "GIT_COMMIT_AUTHOR"
default = "semantic-release <semantic-release>"

[tool.semantic_release.commit_parser_options]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]
other_allowed_tags = ["build", "chore", "ci", "docs", "style", "refactor", "test"]
allowed_tags = ["feat", "fix", "perf", "build", "chore", "ci", "docs", "style", "refactor", "test"]
default_bump_level = 0
parse_squash_commits = true
ignore_merge_commits = true

[tool.semantic_release.remote]
name = "origin"
type = "github"
ignore_token_for_push = false
insecure = false

[tool.semantic_release.publish]
dist_glob_patterns = ["dist/*"]
upload_to_vcs_release = true