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
111 changes: 111 additions & 0 deletions .github/RELEASE_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Release Setup Guide

This guide explains how to set up automatic publishing to Packagist using GitHub Actions.

## Prerequisites

1. **Packagist Account**: Create an account at [packagist.org](https://packagist.org)
2. **GitHub Repository**: Ensure this repository is public on GitHub
3. **Packagist API Token**: Generate a token for automatic updates

## Setup Steps

### 1. Create Packagist Account and Submit Package

1. Go to [packagist.org](https://packagist.org) and create an account
2. Click "Submit" and enter your repository URL: `https://github.com/GetStream/getstream-php`
3. Packagist will automatically detect the package name from `composer.json`

### 2. Generate Packagist API Token

1. Go to your Packagist profile: https://packagist.org/profile/
2. Click "Show API Token" in the "API Token" section
3. Copy the token (it looks like: `pkg_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`)

### 3. Add GitHub Secrets

1. Go to your GitHub repository: https://github.com/GetStream/getstream-php
2. Click "Settings" → "Secrets and variables" → "Actions"
3. Click "New repository secret"
4. Add these secrets:

- **Name**: `PACKAGIST_TOKEN`
**Value**: Your Packagist API token from step 2

- **Name**: `STREAM_API_KEY`
**Value**: Your Stream API key (for running tests)

- **Name**: `STREAM_API_SECRET`
**Value**: Your Stream API secret (for running tests)

### 4. Enable Packagist Auto-Update

1. In your Packagist package page, go to "Settings"
2. Enable "Update by GitHub Hook"
3. Add the GitHub webhook URL: `https://packagist.org/api/github?username=YOUR_USERNAME&packageName=getstream/getstream-php`

## How It Works

### Automatic Publishing

When a PR is merged into `main` or `master`, the release workflow will:

1. Parse the PR title using Conventional Commit style.
- Required ticket format: `type: [FEEDS-1234] description`
- Keep `feat`/`fix`/`bug` at the beginning of the title
2. Decide the bump type:
- `feat:` => minor
- `fix:` or `bug:` => patch
- `feat!:` / `fix!:` / `BREAKING CHANGE` => major
3. Update `composer.json` and `src/Constant.php` via `scripts/release/bump_version.php`
4. Commit version files, create a `vX.Y.Z` tag, create a GitHub release
5. Trigger Packagist update

### Creating a Release

1. Open a PR with a Conventional Commit style title, for example:
- `feat: [FEEDS-1350] add feed search endpoint`
- `fix: [FEEDS-1402] handle nil reaction id`
- `feat!: [FEEDS-1410] remove deprecated batch API`
2. Merge the PR into `main` or `master`.
3. GitHub Actions will automatically perform release + Packagist update.

Titles like `chore:`, `docs:`, `test:` do not trigger a release.

### Manual Publishing (if needed)

If automatic publishing fails, you can manually trigger Packagist updates:

```bash
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_PACKAGIST_TOKEN" \
-d '{"repository":{"url":"https://github.com/GetStream/getstream-php"}}' \
https://packagist.org/api/update-package?username=YOUR_USERNAME
```

## Troubleshooting

### Common Issues

1. **"Package not found"**: Ensure the package is submitted to Packagist first
2. **"Invalid token"**: Verify the Packagist token is correct
3. **"Tests failing"**: Check that all tests pass before creating a release
4. **"Version already exists"**: Use a new version number

### Checking Status

- **GitHub Actions**: https://github.com/GetStream/getstream-php/actions
- **Packagist Package**: https://packagist.org/packages/getstream/getstream-php
- **Test Installation**: `composer require getstream/getstream-php`

## Security Notes

- Never commit API tokens to the repository
- Use GitHub Secrets for all sensitive data
- Regularly rotate your Packagist token
- Monitor the Actions logs for any security issues




13 changes: 12 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,23 @@ on:
branches: [master, main]

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
check-pr-title:
name: Validate PR title
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: aslafy-z/conventional-pr-title-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

test:
name: 🧪 Test & lint
needs: check-pr-title
if: always() && (github.event_name != 'pull_request' || needs.check-pr-title.result == 'success')
environment: ci
runs-on: ubuntu-latest

Expand Down
47 changes: 0 additions & 47 deletions .github/workflows/initiate_release.yml

This file was deleted.

47 changes: 0 additions & 47 deletions .github/workflows/prerelease.yml

This file was deleted.

89 changes: 77 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,103 @@ on:
pull_request:
types: [closed]
branches:
- main
- master

concurrency:
group: release-${{ github.event.pull_request.base.ref }}
cancel-in-progress: true

permissions:
contents: write

jobs:
release:
name: 🚀 Release
environment: ci
if: github.event.pull_request.merged && startsWith(github.head_ref, 'release-')
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/github-script@v7
ref: ${{ github.event.pull_request.base.ref }}

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
script: |
// Getting the release version from the PR source branch
// Source branch looks like this: release-1.0.0
const version = context.payload.pull_request.head.ref.split('-')[1]
core.exportVariable('VERSION', version)
php-version: '8.1'
tools: composer:v2

- name: Skip when PR is already released
id: already_released
run: |
if git log --oneline --grep="(pr #${{ github.event.pull_request.number }})" -n 1 | grep -q "chore(release):"; then
echo "value=true" >> "$GITHUB_OUTPUT"
else
echo "value=false" >> "$GITHUB_OUTPUT"
fi

- name: Determine and apply version bump
id: release_meta
if: steps.already_released.outputs.value != 'true'
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
run: |
PR_BODY_FILE=$(mktemp)
printf '%s' "$PR_BODY" > "$PR_BODY_FILE"
php scripts/release/bump_version.php \
--title "$PR_TITLE" \
--body-file "$PR_BODY_FILE" \
--output "$GITHUB_OUTPUT"

- name: Stop when PR does not require release
if: steps.already_released.outputs.value == 'true' || steps.release_meta.outputs.should_release != 'true'
run: |
if [ "${{ steps.already_released.outputs.value }}" = "true" ]; then
echo "PR #${{ github.event.pull_request.number }} is already released; skipping."
exit 0
fi
echo "No release type found in PR title; skipping."
exit 0

- name: Commit version files
if: steps.already_released.outputs.value != 'true' && steps.release_meta.outputs.should_release == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add composer.json src/Constant.php
if git diff --cached --quiet; then
echo "No version changes to commit."
exit 0
fi
git commit -m "chore(release): v${{ steps.release_meta.outputs.version }} (pr #${{ github.event.pull_request.number }})"
git push origin "HEAD:${{ github.event.pull_request.base.ref }}"

- name: Create release tag
if: steps.already_released.outputs.value != 'true' && steps.release_meta.outputs.should_release == 'true'
run: |
git tag "${{ steps.release_meta.outputs.tag }}"
git push origin "${{ steps.release_meta.outputs.tag }}"

- name: Create release on GitHub
if: steps.already_released.outputs.value != 'true' && steps.release_meta.outputs.should_release == 'true'
uses: ncipollo/release-action@v1
with:
tag: ${{ env.VERSION }}
tag: ${{ steps.release_meta.outputs.tag }}
token: ${{ secrets.GITHUB_TOKEN }}
body: |
Release ${{ env.VERSION }}

Install with: `composer require getstream/getstream-php:^${{ env.VERSION }}`
Release v${{ steps.release_meta.outputs.version }}

- Bump type: `${{ steps.release_meta.outputs.bump }}`
- Previous: `${{ steps.release_meta.outputs.previous_version }}`
- Next: `${{ steps.release_meta.outputs.version }}`

Install with: `composer require getstream/getstream-php:^${{ steps.release_meta.outputs.version }}`

- name: Update Packagist
if: steps.already_released.outputs.value != 'true' && steps.release_meta.outputs.should_release == 'true'
env:
PACKAGIST_TOKEN: ${{ secrets.PACKAGIST_TOKEN }}
PACKAGIST_USERNAME: ${{ vars.PACKAGIST_USERNAME }}
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,26 @@ This creates clean, typed models with automatic JSON handling - no boilerplate c

## Development

### Release Workflow

Releases are automated when a pull request is merged into `main` or `master`.

- PR titles must follow Conventional Commit format (for example: `feat: ...`, `fix: ...`).
- Ticket prefix is required in the subject: `type: [FEEDS-1234] description`.
- Keep the commit type first so release automation can parse it.
- Version bump is derived from PR title/body:
- `feat:` => minor
- `fix:` or `bug:` => patch
- `feat!:` / `fix!:` / `BREAKING CHANGE` => major
- Non-release types like `chore:`, `docs:`, `test:` do not create a release.
- The release workflow updates `composer.json` and `src/Constant.php`, pushes a tag, creates a GitHub release, and triggers Packagist.

Examples:

- `feat: [FEEDS-1350] add feed retention endpoint`
- `fix: [FEEDS-1402] handle missing reaction id`
- `feat!: [FEEDS-1410] remove deprecated follow API`

### Linting and Code Quality

```bash
Expand Down
Loading
Loading