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
217 changes: 217 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
name: "Release"

on:
pull_request:
types: [closed]
branches: [master]

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
concurrency:
group: release
cancel-in-progress: false

jobs:
check-release-label:
name: Check for release label
runs-on: ubuntu-latest
# Run when PR with 'release' label is merged to master, or when manually triggered
if: |
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 }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: master
fetch-depth: 0

- name: Check release conditions
id: check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Determine bump type from PR labels
if ${{ contains(github.event.pull_request.labels.*.name, 'bump-major') }}; then
echo "bump-type=major" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
elif ${{ contains(github.event.pull_request.labels.*.name, 'bump-minor') }}; then
echo "bump-type=minor" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
elif ${{ contains(github.event.pull_request.labels.*.name, 'bump-patch') }}; then
echo "bump-type=patch" >> "$GITHUB_OUTPUT"
echo "should-release=true" >> "$GITHUB_OUTPUT"
fi

notify-approval-needed:
name: Notify Slack - Approval Needed
needs: check-release-label
if: needs.check-release-label.outputs.should-release == 'true'
uses: posthog/.github/.github/workflows/notify-approval-needed.yml@main
with:
slack_channel_id: ${{ vars.SLACK_APPROVALS_CLIENT_LIBRARIES_CHANNEL_ID }}
slack_user_group_id: ${{ vars.GROUP_CLIENT_LIBRARIES_SLACK_GROUP_ID }}
secrets:
slack_bot_token: ${{ secrets.SLACK_CLIENT_LIBRARIES_BOT_TOKEN }}
posthog_project_api_key: ${{ secrets.POSTHOG_PROJECT_API_KEY }}

release:
name: Bump versions and release
needs: [check-release-label, 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
permissions:
contents: write
actions: write
steps:
- name: Notify Slack - Approved
if: 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: "✅ Release approved! Version bump in progress..."
emoji_reaction: "white_check_mark"

- name: Get GitHub App token
id: releaser
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-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

- name: Checkout repository
uses: actions/checkout@v4
with:
ref: master
fetch-depth: 0
token: ${{ steps.releaser.outputs.token }}

- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Bump version
id: bump-version
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]}

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

echo "current_version=$current_version" >> $GITHUB_OUTPUT
echo "new_version=$new_version" >> $GITHUB_OUTPUT

- name: Update CHANGELOG.md
run: |
current_version="${{ steps.bump-version.outputs.current_version }}"
new_version="${{ steps.bump-version.outputs.new_version }}"
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

- name: Commit version bump
id: commit-version-bump
run: |
git add lib/PostHog.php composer.json CHANGELOG.md
if git diff --staged --quiet; then
echo "No changes to commit"
echo "committed=false" >> "$GITHUB_OUTPUT"
else
git commit -m "chore: bump version to ${{ steps.bump-version.outputs.new_version }} [version bump]"
git push origin master
echo "committed=true" >> "$GITHUB_OUTPUT"
fi
env:
GITHUB_TOKEN: ${{ steps.releaser.outputs.token }}

- name: Create and push tag
if: steps.commit-version-bump.outputs.committed == 'true'
run: |
git tag -a "${{ steps.bump-version.outputs.new_version }}" -m "${{ steps.bump-version.outputs.new_version }}"
git push origin "${{ steps.bump-version.outputs.new_version }}"

- name: Create GitHub release
if: steps.commit-version-bump.outputs.committed == 'true'
env:
GH_TOKEN: ${{ steps.releaser.outputs.token }}
run: |
# Extract the latest changelog entry
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 api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/PostHog/posthog-php/releases \
-f tag_name="${{ steps.bump-version.outputs.new_version }}" \
-f target_commitish='master' \
-f name="${{ steps.bump-version.outputs.new_version }}" \
-f body="$LAST_CHANGELOG_ENTRY" \
-F draft=false \
-F prerelease=false \
-F generate_release_notes=false

# Notify in case of a failure
- name: Send failure event to PostHog
if: ${{ failure() }}
uses: PostHog/posthog-github-action@v0.1
with:
posthog-token: "${{ secrets.POSTHOG_PROJECT_API_KEY }}"
event: "posthog-php-github-release-workflow-failure"
properties: >-
{
"commitSha": "${{ github.sha }}",
"jobStatus": "${{ job.status }}",
"ref": "${{ github.ref }}",
"version": "${{ steps.bump-version.outputs.new_version }}"
}

- name: Notify Slack - Failed
if: ${{ failure() && needs.notify-approval-needed.outputs.slack_ts != '' }}
uses: posthog/.github/.github/actions/slack-thread-reply@9b04bf3288aca2b4cd3883070858b034b4f7f334
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>"
emoji_reaction: "x"

notify-released:
name: Notify Slack - Released
needs: [notify-approval-needed, release]
runs-on: ubuntu-latest
if: always() && needs.release.result == 'success' && needs.notify-approval-needed.outputs.slack_ts != ''
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Notify Slack - Released
uses: posthog/.github/.github/actions/slack-thread-reply@9b04bf3288aca2b4cd3883070858b034b4f7f334
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: "🚀 posthog-php released successfully!"
emoji_reaction: "rocket"
File renamed without changes.
12 changes: 0 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,6 @@ lint: dependencies
printf "Please update PHP version to 5.5 or above for code formatting."; \
fi

release:
@printf "releasing ${VERSION}..."
@if [ "$(shell uname)" = "Darwin" ]; then \
sed -i '' -E -e "s/public const VERSION = '[^']*'/public const VERSION = '${VERSION}'/" ./lib/PostHog.php; \
else \
sed -i -E -e "s/public const VERSION = '[^']*'/public const VERSION = '${VERSION}'/" ./lib/PostHog.php; \
fi
@node -e "var fs = require('fs'), pkg = require('./composer'); pkg.version = '${VERSION}'; fs.writeFileSync('./composer.json', JSON.stringify(pkg, null, '\t'));"
@git changelog -t ${VERSION}
@git release ${VERSION}
@gh release create ${VERSION} --generate-notes

clean:
rm -rf \
composer.phar \
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# PostHog PHP

[![PHP Version](https://img.shields.io/packagist/php-v/posthog/posthog-php?logo=php)](https://packagist.org/packages/posthog/posthog-php)
[![CI](https://github.com/PostHog/posthog-php/actions/workflows/php.yml/badge.svg)](https://github.com/PostHog/posthog-php/actions/workflows/php.yml)

Please see the main [PostHog docs](https://posthog.com/docs).

Specifically, the [PHP integration](https://posthog.com/docs/integrations/php-integration) details.
Expand Down Expand Up @@ -27,3 +30,29 @@ Specifically, the [PHP integration](https://posthog.com/docs/integrations/php-in
1. [Download PHP](https://www.php.net/manual/en/install.php) and [Composer](https://getcomposer.org/download/)
2. `php composer.phar update` to install dependencies
3. `bin/test` to run tests (this script calls `./vendor/bin/phpunit --verbose test`)

## Releasing

Releases are semi-automated via GitHub Actions. When a PR with the `release` and a version bump label is merged to `master`, the release workflow is triggered.

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.

### Release Process

1. **Create your PR** with the changes you want to release
2. **Add the `release` label** to the PR
3. **Add a version bump label** that should be either `bump-patch`, `bump-minor` or `bump-major`
4. **Merge the PR** to `master`

Once merged, the following happens automatically:

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 `master`
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

Releases are installed directly from GitHub.
14 changes: 0 additions & 14 deletions RELEASING.md

This file was deleted.