Skip to content
Open
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
85 changes: 85 additions & 0 deletions .github/workflows/publish-cli-to-pypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Publish Casp CLI to PyPI

on:
release:
types: [published]

jobs:
publish-pypi:
name: Build and Publish CLI
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Check for changes in cli/casp
id: check_changes
run: |
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || true)

if [ -z "$PREV_TAG" ]; then
echo "No previous tag found (likely first release). Publishing..."
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "Previous release tag found: $PREV_TAG"

if git diff --quiet "$PREV_TAG" HEAD -- cli/casp; then
echo "No changes detected in cli/casp."
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "Changes detected in cli/casp."
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
fi

- name: Set up Python
if: steps.check_changes.outputs.changed == 'true'
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install build dependencies
if: steps.check_changes.outputs.changed == 'true'
run: python -m pip install build --user

- name: Set version to release tag
if: steps.check_changes.outputs.changed == 'true'
working-directory: cli/casp
run: |
# Get the tag name from the release event (e.g., v1.0.0)
TAG_NAME=${{ github.event.release.tag_name }}
# Strip the leading 'v' to get the version (e.g., 1.0.0)
VERSION=${TAG_NAME#v}

echo "Updating version in pyproject.toml to $VERSION"
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml

- name: Build package
if: steps.check_changes.outputs.changed == 'true'
working-directory: cli/casp
run: python -m build

- name: Publish to PyPI
if: steps.check_changes.outputs.changed == 'true'
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.CASP_PYPI_API_TOKEN }}
packages_dir: cli/casp/dist/
skip_existing: true
63 changes: 63 additions & 0 deletions .github/workflows/publish-cli-to-testpypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Publish Casp CLI to TestPyPI

on:
push:
branches: [ master ]
paths:
- 'cli/casp/**'


jobs:
publish-testpypi:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install build dependencies
run: python -m pip install build --user

- name: Bump version for TestPyPI
working-directory: cli/casp
run: |
# Get the latest tag and strip the leading 'v' (e.g., v1.0.0 -> 1.0.0)
LAST_TAG=$(git describe --tags --abbrev=0)
VERSION=${LAST_TAG#v}
TIMESTAMP=$(date +%s)

# Set version to <last_tag>.<timestamp> (e.g., 1.0.0.1701234567)
echo "Updating version in pyproject.toml to $VERSION.$TIMESTAMP"
sed -i "s/^version = \".*\"/version = \"$VERSION.$TIMESTAMP\"/" pyproject.toml

- name: Build package
working-directory: cli/casp
run: python -m build

- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.CASP_TEST_PYPI_API_TOKEN }}
repository-url: https://test.pypi.org/legacy/
packages-dir: cli/casp/dist/
skip-existing: true
8 changes: 6 additions & 2 deletions cli/casp/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ build-backend = "setuptools.build_meta"

[project]
name = "casp"
version = "0.0.8"
# This is a placeholder version. The actual version is set
# in publish-cli-to-pypi.yaml and publish-cli-to-testpypi.yaml
# If you want to manually publish the CLI, you need to manually
# set the version here.
version = "0.0.8"
authors = [
{ name="PauloVLB", email="[email protected]" },
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm worried that with Paulo finishing his internship, this email won't be available anymore and the workflow might start failing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree. As mentioned in #4987, the publishing account should be validated.

I suggest creating a new ClusterFuzz account (since this one doesn't seem right) in both TestPyPI and PyPI and changing it.

We'd also need to change the secrets used in the pipelines (CASP_PYPI_API_TOKEN and CASP_TEST_PYPI_API_TOKEN).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To generate tokens, follow these steps in each environment:

  1. Go to pypi.org/manage/account/ or test.pypi.org/manage/account/
  2. Scroll down to "API tokens"
  3. Click "Add API Token"
  4. Provide a token name and scope (must include the CLI project)
  5. Click "Create token"

You can also find a step-by-step guide on how to publish locally on my notes, in the "Commands" section.

]
description = "A new, modern Command-Line Interface (CLI) for ClusterFuzz."
readme = "README.md"
license = "Apache-2.0"
requires-python = ">=3.6"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
Expand Down
Loading