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
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

# This script generates an artifactbundle for protoc. This artifactbundle
# is used by the Swift package manger. The script is run by a GitHub action
# when a new pre-release is created for swift-protobuf.
# to create protoc-vXXX releases with artifactbundles.

set -eux

# Fetch the latest stable release from protocolbuffers/protobuf
AUTH="Authorization: token $GITHUB_TOKEN"
response=$(curl -sH "$AUTH" "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest")
TAG=$(echo "$response" | grep -m 1 '"tag_name":' | cut -d '"' -f 4)

# Fetch the latest stable release from protocolbuffers/protobuf
upstream_response=$(curl -sH "$AUTH" "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest")
TAG=$(echo "$upstream_response" | grep -m 1 '"tag_name":' | cut -d '"' -f 4)

# Remove 'v' prefix if present
TAG="${TAG#v}"
Expand All @@ -19,6 +20,29 @@ if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+$ ]]; then
exit 1
fi

echo "Latest upstream protoc version: $TAG"

# Check for the latest protoc-vXXX release in this swift-protobuf repo
swift_protobuf_response=$(curl -sH "$AUTH" "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases")
CURRENT_PROTOC_TAG=$(echo "$swift_protobuf_response" | jq -r '.[] | select(.tag_name | startswith("protoc-v")) | .tag_name' | head -n 1)

if [ -z "$CURRENT_PROTOC_TAG" ] || [ "$CURRENT_PROTOC_TAG" = "null" ]; then
echo "No existing protoc-vXXX release found. This will be the initial release."
CURRENT_PROTOC_VERSION=""
else
# Extract version from protoc-vX.Y format
CURRENT_PROTOC_VERSION="${CURRENT_PROTOC_TAG#protoc-v}"
echo "Current swift-protobuf protoc version: $CURRENT_PROTOC_VERSION"
fi

# Compare versions - if they match, no need to create a new release
if [ "$CURRENT_PROTOC_VERSION" = "$TAG" ]; then
echo "Protoc version $TAG is already released. No action needed."
exit 0
fi

echo "Creating new protoc release: protoc-v$TAG"

# Fetch all protoc release assets from protocolbuffers/protobuf
curl -LJ --output protoc-$TAG-osx-x86_64.zip -H 'Accept: application/octet-stream' https://github.com/protocolbuffers/protobuf/releases/download/v$TAG/protoc-$TAG-osx-x86_64.zip
curl -LJ --output protoc-$TAG-osx-aarch_64.zip -H 'Accept: application/octet-stream' https://github.com/protocolbuffers/protobuf/releases/download/v$TAG/protoc-$TAG-osx-aarch_64.zip
Expand Down Expand Up @@ -85,20 +109,35 @@ EOF
# Zip artifactbundle
zip -r protoc-$TAG.artifactbundle.zip protoc-$TAG.artifactbundle

# Get asset upload url for the latest swift-protobuf draft release
response=$(curl -sH "$AUTH" "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases")
upload_url=$(echo "$response" | jq -r '.[] | select(.draft == true) | .upload_url' | head -n 1)
SWIFT_PROTOBUF_TAG=$(echo "$response" | jq -r '.[] | select(.draft == true) | .tag_name' | head -n 1)

if [ -z "$SWIFT_PROTOBUF_TAG" ] || [ -z "$upload_url" ]; then
echo "Error: No draft release found"
# Create a new draft release for protoc-vXXX
echo "Creating draft release protoc-v$TAG"
create_response=$(curl -sH "$AUTH" -X POST "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases" \
-d "{
\"tag_name\": \"protoc-artifactbundle-v$TAG\",
\"name\": \"protoc v$TAG artifactbundle\",
\"body\": \"Protoc artifactbundle for version $TAG\",
\"draft\": true,
\"prerelease\": false,
\"make_latest\": false
}")

upload_url=$(echo "$create_response" | jq -r '.upload_url')
release_id=$(echo "$create_response" | jq -r '.id')

if [ -z "$upload_url" ] || [ "$upload_url" = "null" ] || [ -z "$release_id" ] || [ "$release_id" = "null" ]; then
echo "Error: Failed to create draft release"
echo "Response: $create_response"
exit 1
fi

# Remove the {?name,label} template from upload_url
upload_url=$(echo "$upload_url" | sed 's/{?name,label}//')
echo "Found draft release: $SWIFT_PROTOBUF_TAG"
echo "Created draft release with ID: $release_id"
echo "Upload URL: $upload_url"

# Upload asset
curl --data-binary @protoc-$TAG.artifactbundle.zip -H "$AUTH" -H "Content-Type: application/octet-stream" "$upload_url?name=protoc-$TAG.artifactbundle.zip"
echo "Uploading artifactbundle..."
upload_response=$(curl --data-binary @protoc-$TAG.artifactbundle.zip -H "$AUTH" -H "Content-Type: application/octet-stream" "$upload_url?name=protoc-$TAG.artifactbundle.zip")

echo "Upload completed successfully!"
echo "Draft release protoc-v$TAG created with artifactbundle"
16 changes: 16 additions & 0 deletions .github/workflows/draft_release_protoc_artifactbundle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Draft release protoc artifactbundle

on:
workflow_dispatch:

jobs:
draft-release:
runs-on: ubuntu-latest
steps:
- name: "Checkout code"
uses: actions/checkout@v4
- name: Draft release and upload artifactbundle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cd ${{ github.workspace }} && .github/scripts/draft_release_protoc_artifactbundle.sh

16 changes: 0 additions & 16 deletions .github/workflows/prerelease_protoc_artifactbundle.yml

This file was deleted.

88 changes: 45 additions & 43 deletions Documentation/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

---

When doing a release:
This document covers two types of releases:

1. **Swift Protobuf Library Releases** - New versions of the Swift protobuf library itself
2. **Protoc Artifactbundle Releases** - Updates to the bundled protoc compiler when new protoc versions are available

## Swift Protobuf Library Releases

When doing a Swift Protobuf library release:

1. Examine what has changed

Expand Down Expand Up @@ -48,48 +55,6 @@ When doing a release:
everything based on the PR descriptions and _semver_ tags in the repo. Just read
though was was generate to see if any tweaks are needed.

**Important:** Save this as a **draft** release first (do not publish yet).

1. Generate protoc artifact bundle if needed

First, check if there have been any new protoc releases since the last
time we bundled protoc. To do this check the binary target protoc version number
in the Package.swift. If there has been a new release of protoc then once you
have created the draft release, trigger the "Upload protoc artifactbundle"
workflow from the [Actions tab](https://github.com/apple/swift-protobuf/actions/workflows/prerelease_protoc_artifactbundle.yml).

This workflow will:
- Fetch the latest stable protoc release from protocolbuffers/protobuf
- Create a Swift Package Manager compatible artifact bundle
- Upload it to your draft release

Wait for the workflow to complete successfully before proceeding.

1. Update Package.swift with new artifact bundle

If there was a new protoc release and you uploaded a new artifact bundle in
the previous step. Create a pull request that updates the `Package.swift` file
to reference the new artifact bundle. You'll need to update two things:

- **URL**: Change to point to your new release tag
- **Checksum**: Download the artifact bundle and calculate its SHA256 hash

Example update:
```swift
.binaryTarget(
name: "protoc",
url: "https://github.com/apple/swift-protobuf/releases/download/[a.b.c]/protoc-X.Y.artifactbundle.zip",
checksum: "new-sha256-checksum-here"
),
```

To get the checksum copy it from the Github UI when looking at the draft release.bundle.zip

1. Publish the release

After the Package.swift PR is merged, return to your draft release and click
_Publish release_.

1. Publish the `SwiftProtobuf.podspec`

_Note:_ You must be an _owner_ of the pod to do this, see `pod trunk info SwiftProtobuf`
Expand All @@ -101,3 +66,40 @@ When doing a release:

_Note:_ This uses that local copy of `SwiftProtobuf.podspec`, but checks
against the sources on github.

## Protoc Artifactbundle Releases

Protoc artifactbundle releases are independent of Swift Protobuf library releases and follow
a `protoc-vX.Y` naming convention that matches the upstream protoc version.

### Creating a protoc release

1. **Trigger the workflow**

Go to the [Actions tab](https://github.com/apple/swift-protobuf/actions/workflows/draft_release_protoc_artifactbundle.yml)
and manually run the "Draft release protoc artifactbundle" workflow.

2. **What the workflow does automatically**

The workflow will:
- Check the latest protoc version from protocolbuffers/protobuf
- Check if we already have a matching `protoc-vX.Y` release
- If versions differ or no release exists:
- Download protoc binaries for all supported platforms
- Create a Swift Package Manager compatible artifact bundle
- Create a new draft release tagged `protoc-vX.Y`
- Upload the artifactbundle to the draft release
- If versions match, exit early (no action needed)

3. **Publish the release**

After the workflow completes successfully:
- Go to the [releases page](https://github.com/apple/swift-protobuf/releases)
- Find the draft `protoc-vX.Y` release
- Review the release notes and artifactbundle
- Click "Publish release"

4. **Use in Swift Protobuf**

The protoc release is now available with a stable URL that can be referenced
in `Package.swift`. Create a separate PR to update the reference in the `Package.swift`