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
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
3 changes: 1 addition & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

### If releasing new changes

- [ ] Added the `release` label to the PR
- [ ] Added exactly one version bump label: `bump-patch`, `bump-minor`, or `bump-major`
- [ ] Ran `pnpm changeset` to generate a changeset file

<!-- For more details check RELEASING.md -->
165 changes: 61 additions & 104 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,79 +1,50 @@
name: "Release"

on:
pull_request:
types: [closed]
push:
branches: [main]
paths:
- '.changeset/*.md'
workflow_dispatch:
inputs:
bump_type:
description: Version bump to apply
required: true
type: choice
options:
- patch
- minor
- major

permissions:
contents: read

# Concurrency control: only one release process can run at a time
# This prevents race conditions if multiple PRs with 'release' label merge simultaneously
# This prevents race conditions if multiple releasable changesets merge simultaneously
concurrency:
group: release
cancel-in-progress: false

jobs:
check-release-label:
name: Check for release label
check-changesets:
name: Check for changesets
runs-on: ubuntu-latest
# Run when PR with 'release' label is merged to main, or when manually triggered
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.merged == true &&
contains(github.event.pull_request.labels.*.name, 'release'))
outputs:
should-release: ${{ steps.check.outputs.should-release }}
bump-type: ${{ steps.check.outputs.bump-type }}
has-changesets: ${{ steps.check.outputs.has-changesets }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: main
fetch-depth: 0

- name: Check release conditions
- name: Check for changesets
id: check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
INPUT_BUMP_TYPE: ${{ inputs.bump_type }}
HAS_BUMP_MAJOR: ${{ contains(github.event.pull_request.labels.*.name, 'bump-major') }}
HAS_BUMP_MINOR: ${{ contains(github.event.pull_request.labels.*.name, 'bump-minor') }}
HAS_BUMP_PATCH: ${{ contains(github.event.pull_request.labels.*.name, 'bump-patch') }}
run: |
# Determine bump type from workflow input or PR labels
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
echo "bump-type=$INPUT_BUMP_TYPE" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
echo "Manual release requested with bump type '$INPUT_BUMP_TYPE'"
elif [ "$HAS_BUMP_MAJOR" = "true" ]; then
echo "bump-type=major" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
elif [ "$HAS_BUMP_MINOR" = "true" ]; then
echo "bump-type=minor" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
elif [ "$HAS_BUMP_PATCH" = "true" ]; then
echo "bump-type=patch" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
changeset_count=$(find .changeset -name '*.md' ! -name 'README.md' 2>/dev/null | wc -l)
if [ "$changeset_count" -gt 0 ]; then
echo "has-changesets=true" >> "$GITHUB_OUTPUT"
echo "Found $changeset_count changeset(s), ready to release"
else
echo "has-changesets=false" >> "$GITHUB_OUTPUT"
echo "No changesets to release"
fi

notify-approval-needed:
name: Notify Slack - Approval Needed
needs: check-release-label
if: needs.check-release-label.outputs.should-release == 'true'
needs: check-changesets
if: needs.check-changesets.outputs.has-changesets == 'true'
uses: posthog/.github/.github/workflows/notify-approval-needed.yml@main
with:
slack_channel_id: ${{ vars.SLACK_APPROVALS_CLIENT_LIBRARIES_CHANNEL_ID }}
Expand All @@ -83,13 +54,11 @@ jobs:
posthog_project_api_key: ${{ secrets.POSTHOG_PROJECT_API_KEY }}

release:
name: Bump versions and release
needs: [check-release-label, notify-approval-needed]
name: Bump version and release
needs: [check-changesets, notify-approval-needed]
runs-on: ubuntu-latest
# Use `always()` to ensure the job runs even if the check-release-label job fails
# but still depend on it to be able to use `needs.notify-approval-needed.outputs.slack_ts`
if: always() && needs.check-release-label.outputs.should-release == 'true'
environment: "Release" # This will require an approval from a maintainer, they are notified in Slack above
if: always() && needs.check-changesets.outputs.has-changesets == 'true'
environment: "Release"
permissions:
contents: write
actions: write
Expand All @@ -103,13 +72,12 @@ jobs:
thread_ts: ${{ needs.notify-approval-needed.outputs.slack_ts }}
message: "✅ Release approved! Version bump in progress..."
emoji_reaction: "white_check_mark"

- name: Get GitHub App token
id: releaser
uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.GH_APP_POSTHOG_PHP_RELEASER_APP_ID }}
private-key: ${{ secrets.GH_APP_POSTHOG_PHP_RELEASER_PRIVATE_KEY }} # Secrets available only inside the 'Release' environment, requires approval from a maintainer
private-key: ${{ secrets.GH_APP_POSTHOG_PHP_RELEASER_PRIVATE_KEY }}

- name: Checkout repository
uses: actions/checkout@v6
Expand All @@ -118,69 +86,58 @@ jobs:
fetch-depth: 0
token: ${{ steps.releaser.outputs.token }}

- name: Bump version
id: bump-version
- name: Configure Git
run: |
current_version=$(grep -oP "public const VERSION = '\K[^']+" lib/PostHog.php)
IFS='.' read -ra version_parts <<< "$current_version"
major=${version_parts[0]}
minor=${version_parts[1]}
patch=${version_parts[2]}
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

if [ "${{ needs.check-release-label.outputs.bump-type }}" == "major" ]; then
new_version="$((major + 1)).0.0"
elif [ "${{ needs.check-release-label.outputs.bump-type }}" == "minor" ]; then
new_version="$major.$((minor + 1)).0"
else
new_version="$major.$minor.$((patch + 1))"
fi

sed -i "s/public const VERSION = '$current_version'/public const VERSION = '$new_version'/" lib/PostHog.php
sed -i "s/\"version\": \"$current_version\"/\"version\": \"$new_version\"/" composer.json
- name: Setup pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4

echo "current_version=$current_version" >> $GITHUB_OUTPUT
echo "new_version=$new_version" >> $GITHUB_OUTPUT
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm

if ! git diff --quiet lib/PostHog.php composer.json; then
echo "has_changes=true" >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Update CHANGELOG.md
env:
CURRENT_VERSION: ${{ steps.bump-version.outputs.current_version }}
NEW_VERSION: ${{ steps.bump-version.outputs.new_version }}
- name: Apply changesets and update version
id: apply-changesets
run: |
release_date=$(date +%Y-%m-%d)
echo -e "## $NEW_VERSION - $release_date\n\n* [Full Changelog](https://github.com/PostHog/posthog-php/compare/${CURRENT_VERSION}...${NEW_VERSION})\n\n$(cat CHANGELOG.md)" > CHANGELOG.md
pnpm changeset version
NEW_VERSION=$(node -p "require('./package.json').version")
./scripts/bump-version.sh "$NEW_VERSION"
echo "new-version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
echo "New version: $NEW_VERSION"

- name: Commit version bump
if: steps.bump-version.outputs.has_changes == 'true'
uses: planetscale/ghcommit-action@25309d8005ac7c3bcd61d3fe19b69e0fe47dbdde # v0.2.20
with:
commit_message: "chore: bump version to ${{ steps.bump-version.outputs.new_version }} [version bump]"
repo: ${{ github.repository }}
branch: main
file_pattern: "lib/PostHog.php composer.json CHANGELOG.md"
id: commit-version-bump
env:
GITHUB_TOKEN: ${{ steps.releaser.outputs.token }}
NEW_VERSION: ${{ steps.apply-changesets.outputs.new-version }}
run: |
git add -A
if git diff --staged --quiet; then
echo "No changes to commit"
echo "committed=false" >> "$GITHUB_OUTPUT"
else
git commit -m "chore: release $NEW_VERSION [version bump] [skip ci]"
git push origin main
echo "committed=true" >> "$GITHUB_OUTPUT"
fi

- name: Create GitHub release
if: steps.bump-version.outputs.has_changes == 'true'
if: steps.commit-version-bump.outputs.committed == 'true'
env:
GH_TOKEN: ${{ steps.releaser.outputs.token }}
NEW_VERSION: ${{ steps.bump-version.outputs.new_version }}
NEW_VERSION: ${{ steps.apply-changesets.outputs.new-version }}
run: |
LAST_CHANGELOG_ENTRY=$(awk -v defText="see CHANGELOG.md" '/^## /{if (flag) exit; flag=1} flag && /^##$/{exit} flag; END{if (!flag) print defText}' CHANGELOG.md)
gh release create "$NEW_VERSION" \
--target main \
--title "$NEW_VERSION" \
--notes "$LAST_CHANGELOG_ENTRY"
CHANGELOG_ENTRY=$(awk -v defText="see CHANGELOG.md" '/^## /{if (flag) exit; flag=1} flag && /^##$/{exit} flag; END{if (!flag) print defText}' CHANGELOG.md)
gh release create "$NEW_VERSION" --target main --title "$NEW_VERSION" --notes "$CHANGELOG_ENTRY"

# Notify in case of a failure
- name: Send failure event to PostHog
if: ${{ failure() }}
if: failure()
uses: PostHog/posthog-github-action@v1
with:
posthog-token: "${{ secrets.POSTHOG_PROJECT_API_KEY }}"
Expand All @@ -190,17 +147,17 @@ jobs:
"commitSha": "${{ github.sha }}",
"jobStatus": "${{ job.status }}",
"ref": "${{ github.ref }}",
"version": "${{ steps.bump-version.outputs.new_version }}"
"version": "${{ steps.apply-changesets.outputs.new-version }}"
}

- name: Notify Slack - Failed
if: ${{ failure() && needs.notify-approval-needed.outputs.slack_ts != '' }}
if: failure() && needs.notify-approval-needed.outputs.slack_ts != ''
uses: posthog/.github/.github/actions/slack-thread-reply@main
with:
slack_bot_token: ${{ secrets.SLACK_CLIENT_LIBRARIES_BOT_TOKEN }}
slack_channel_id: ${{ vars.SLACK_APPROVALS_CLIENT_LIBRARIES_CHANNEL_ID }}
thread_ts: ${{ needs.notify-approval-needed.outputs.slack_ts }}
message: "❌ Failed to release `posthog-php@${{ steps.bump-version.outputs.new_version }}`! <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
message: "❌ Failed to release `posthog-php@${{ steps.apply-changesets.outputs.new-version }}`! <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
emoji_reaction: "x"

notify-released:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ clover.xml
xdebug.log
.DS_Store
.env
node_modules/
53 changes: 37 additions & 16 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,45 @@
# Releasing

Releases are semi-automated via GitHub Actions. When a PR with the `release` and a version bump label is merged to `main`, the release workflow is triggered. You can also trigger the `Release` workflow manually from GitHub Actions and choose the bump type.
This repository uses [Changesets](https://github.com/changesets/changesets) for version management and an automated GitHub Actions workflow for releases.

You'll need an approval from a PostHog engineer. If you're an employee, you can see the request in the [#approvals-client-libraries](https://app.slack.com/client/TSS5W8YQZ/C0A3UEVDDNF) channel.
## How to Release

## Release Process
### 1. Add a Changeset

1. Either:
- **Create your PR** with the changes you want to release, add the `release` label, add exactly one version bump label (`bump-patch`, `bump-minor`, or `bump-major`), and **merge the PR** to `main`, or
- open the `Release` workflow in GitHub Actions, click **Run workflow**, and choose `patch`, `minor`, or `major`
When making a change that should be released, add a changeset:

Once the workflow is triggered, the following happens automatically:
```bash
pnpm changeset
```

1. A Slack notification is sent to the client libraries channel requesting approval
2. A maintainer approves the release in the GitHub `Release` environment
3. The version is bumped in `lib/PostHog.php` and `composer.json` based on the version label (`patch`, `minor`, or `major`, extracted from the label)
4. The `CHANGELOG.md` is updated with a link to the full changelog
5. Changes are committed and pushed to `main`
6. A git tag is created (e.g., `v1.8.0`)
7. A GitHub release is created with the changelog content
8. Slack is notified of the successful release
This prompts you to select the version bump (`patch`, `minor`, or `major`) and write a short release summary. Commit the generated file in `.changeset/` with your pull request.

Releases are installed directly from GitHub.
### 2. Merge the Pull Request

After review, merge the PR to `main`. No GitHub release label is required.

A push to `main` that includes `.changeset/*.md` changes automatically starts the release workflow. The workflow then:

1. Checks for pending changesets
2. Notifies the client libraries team in Slack for approval
3. Waits for approval from a maintainer via the GitHub `Release` environment
4. The workflow applies Changesets, syncs `lib/PostHog.php` and `composer.json`, tags the release, and creates a GitHub Release.
5. Notifies Slack when the release completes or fails

### Manual Trigger

You can also manually trigger the release workflow from the Actions tab with `workflow_dispatch`. Manual runs still require pending changesets.

## Version Bumping

Changesets determines the next version from the committed changeset files:

- **patch**: bug fixes, documentation updates, and internal changes
- **minor**: backwards-compatible features
- **major**: breaking changes

## Troubleshooting

### No changesets found

If the release workflow reports that no changesets were found, make sure your PR includes at least one releasable `.changeset/*.md` file.
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "posthog-php",
"version": "4.2.4",
"private": true,
"description": "Release metadata and changesets for the PostHog PHP SDK",
"packageManager": "pnpm@10.33.2",
"scripts": {
"changeset": "changeset"
},
"devDependencies": {
"@changesets/cli": "^2.30.0"
}
}
Loading
Loading