fix: preserve async exception stack trace frames (#303) #69
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.changeset/*.md' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| # Concurrency control: only one release process can run at a time. | |
| # This prevents race conditions if multiple releasable changesets merge simultaneously. | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| jobs: | |
| check-changesets: | |
| name: Check for changesets | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has-changesets: ${{ steps.check.outputs.has-changesets }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: main | |
| fetch-depth: 0 | |
| - name: Check for changesets | |
| id: check | |
| run: | | |
| 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-changesets | |
| if: needs.check-changesets.outputs.has-changesets == 'true' | |
| uses: posthog/.github/.github/workflows/notify-approval-needed.yml@5fc4680761e8ac29a61b212756230eba0e276d8c | |
| 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 }} | |
| version-bump: | |
| name: Bump versions and commit to main | |
| needs: [check-changesets, notify-approval-needed] | |
| runs-on: ubuntu-latest | |
| if: always() && needs.check-changesets.outputs.has-changesets == 'true' | |
| environment: Release | |
| permissions: | |
| contents: write | |
| actions: write | |
| id-token: write | |
| outputs: | |
| committed: ${{ steps.version-bump-outputs.outputs.committed }} | |
| commit-sha: ${{ steps.version-bump-outputs.outputs.commit-sha }} | |
| env: | |
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 | |
| DOTNET_NOLOGO: true | |
| DOTNET_VERSION: "9.0.102" | |
| steps: | |
| - name: Notify Slack - Approved | |
| if: needs.notify-approval-needed.outputs.slack_ts != '' | |
| uses: posthog/.github/.github/actions/slack-thread-reply@cb0979b67dcd585828b61ac45927eef4da8f6287 # 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@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| client-id: ${{ secrets.GH_APP_POSTHOG_DOTNET_RELEASER_APP_ID }} | |
| private-key: ${{ secrets.GH_APP_POSTHOG_DOTNET_RELEASER_PRIVATE_KEY }} | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: main | |
| 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: Setup pnpm and Node.js | |
| uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2 | |
| with: | |
| # TODO: pnpm/setup does not read .nvmrc yet. Keep this in sync with .nvmrc | |
| # until https://github.com/jasongin/nvs/pull/315 lands. | |
| # pnpm/setup installs runtimes via pnpm runtime, which requires pnpm >=11.1.0. | |
| version: 11.7.0 | |
| runtime: node@24 | |
| cache: true | |
| install: false | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Apply changesets | |
| run: pnpm changeset version | |
| - name: Sync package versions to project files | |
| run: | | |
| set -euo pipefail | |
| set_version() { | |
| local project_file="$1" | |
| local version="$2" | |
| perl -0pi -e 's/<Version>[^<]+<\/Version>/<Version>'"$version"'<\/Version>/' "$project_file" | |
| } | |
| POSTHOG_VERSION=$(node -p "require('./src/PostHog/package.json').version") | |
| ASPNETCORE_VERSION=$(node -p "require('./src/PostHog.AspNetCore/package.json').version") | |
| AI_VERSION=$(node -p "require('./src/PostHog.AI/package.json').version") | |
| set_version "src/PostHog/PostHog.csproj" "$POSTHOG_VERSION" | |
| set_version "src/PostHog.AspNetCore/PostHog.AspNetCore.csproj" "$ASPNETCORE_VERSION" | |
| set_version "src/PostHog.AI/PostHog.AI.csproj" "$AI_VERSION" | |
| - name: Restore NuGet packages | |
| run: dotnet restore --locked-mode | |
| - name: Build | |
| run: dotnet build --configuration Release --no-restore | |
| - name: Test | |
| run: dotnet test --configuration Release --no-build | |
| - name: Check for version bump changes | |
| id: check-changes | |
| run: | | |
| if [ -z "$(git status --porcelain)" ]; then | |
| echo "No changes to commit" | |
| echo "has-changes=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has-changes=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Commit version bump | |
| id: commit-version-bump | |
| if: steps.check-changes.outputs.has-changes == 'true' | |
| uses: planetscale/ghcommit-action@a6b150b81dca5dd027baa898604418eec9e11465 # v0.2.22 | |
| with: | |
| commit_message: "chore: update package versions [version bump] [skip ci]" | |
| repo: ${{ github.repository }} | |
| branch: main | |
| env: | |
| GITHUB_TOKEN: ${{ steps.releaser.outputs.token }} | |
| - name: Set version bump outputs | |
| id: version-bump-outputs | |
| env: | |
| HAS_CHANGES: ${{ steps.check-changes.outputs.has-changes }} | |
| COMMIT_HASH: ${{ steps.commit-version-bump.outputs.commit-hash }} | |
| run: | | |
| if [ "$HAS_CHANGES" = "true" ]; then | |
| echo "committed=true" >> "$GITHUB_OUTPUT" | |
| echo "commit-sha=$COMMIT_HASH" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "committed=false" >> "$GITHUB_OUTPUT" | |
| echo "commit-sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Resolve release failure metadata | |
| id: release-failure-metadata | |
| if: failure() | |
| run: | | |
| set -euo pipefail | |
| package_name="" | |
| package_version="" | |
| separator="" | |
| for package_json in src/PostHog/package.json src/PostHog.AspNetCore/package.json src/PostHog.AI/package.json; do | |
| if [ -f "$package_json" ]; then | |
| package_name_part=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("name", ""))' "$package_json") | |
| version=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("version", ""))' "$package_json") | |
| if [ -n "$package_name_part" ] && [ -n "$version" ]; then | |
| package_name="${package_name}${separator}${package_name_part}" | |
| package_version="${package_version}${separator}${package_name_part}@v${version}" | |
| separator=", " | |
| fi | |
| fi | |
| done | |
| echo "package_name=$package_name" >> "$GITHUB_OUTPUT" | |
| echo "package_version=$package_version" >> "$GITHUB_OUTPUT" | |
| - name: Send failure event to PostHog | |
| if: failure() | |
| continue-on-error: true | |
| uses: PostHog/posthog-github-action@9a6a19d360820ab4d95ecc4a5a7564062c895f84 # v1.3.0 | |
| with: | |
| posthog-token: "${{ secrets.POSTHOG_PROJECT_API_KEY }}" | |
| event: "posthog-sdk-github-release-workflow-failure" | |
| properties: >- | |
| { | |
| "commitSha": "${{ github.sha }}", | |
| "jobStatus": "${{ job.status }}", | |
| "ref": "${{ github.ref }}", | |
| "repository": "${{ github.repository }}", | |
| "sdk": "posthog-dotnet", | |
| "jobName": "version-bump", | |
| "packageName": "${{ steps.release-failure-metadata.outputs.package_name || 'unknown' }}", | |
| "packageVersion": "${{ steps.release-failure-metadata.outputs.package_version || 'unknown' }}", | |
| "actionUrl": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", | |
| "alertText": ":rotating_light: Failed to prepare release for posthog-dotnet :rotating_light:", | |
| "alertContext": "The version bump/changelog step failed before packages were published." | |
| } | |
| - name: Notify Slack - Failed | |
| if: failure() && needs.notify-approval-needed.outputs.slack_ts != '' | |
| uses: posthog/.github/.github/actions/slack-thread-reply@cb0979b67dcd585828b61ac45927eef4da8f6287 # 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 bump versions for `posthog-dotnet`! <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>" | |
| emoji_reaction: "x" | |
| publish: | |
| name: Publish packages | |
| needs: [version-bump, notify-approval-needed] | |
| runs-on: ubuntu-latest | |
| if: always() && needs.version-bump.outputs.committed == 'true' | |
| permissions: | |
| contents: write | |
| actions: write | |
| id-token: write | |
| env: | |
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 | |
| DOTNET_NOLOGO: true | |
| DOTNET_VERSION: "9.0.102" | |
| PackageDirectory: ${{ github.workspace }}/build/packages/Release | |
| strategy: | |
| # If any package fails to publish, stop immediately. PostHog must publish before dependents. | |
| fail-fast: true | |
| max-parallel: 1 | |
| matrix: | |
| package: | |
| - name: PostHog | |
| path: src/PostHog | |
| project: src/PostHog/PostHog.csproj | |
| changelog: src/PostHog/CHANGELOG.md | |
| - name: PostHog.AspNetCore | |
| path: src/PostHog.AspNetCore | |
| project: src/PostHog.AspNetCore/PostHog.AspNetCore.csproj | |
| changelog: src/PostHog.AspNetCore/CHANGELOG.md | |
| - name: PostHog.AI | |
| path: src/PostHog.AI | |
| project: src/PostHog.AI/PostHog.AI.csproj | |
| changelog: src/PostHog.AI/CHANGELOG.md | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: ${{ needs.version-bump.outputs.commit-sha }} | |
| fetch-depth: 0 | |
| - name: Configure Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Fetch tags | |
| run: git fetch --tags --force | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 24 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Detect version change for ${{ matrix.package.name }} | |
| id: detect-version | |
| run: | | |
| set -euo pipefail | |
| PACKAGE_JSON="${{ matrix.package.path }}/package.json" | |
| CURRENT_VERSION=$(node -p "require('./${PACKAGE_JSON}').version") | |
| RELEASE_TAG="${{ matrix.package.name }}-v${CURRENT_VERSION}" | |
| if git diff --quiet HEAD^ HEAD -- "$PACKAGE_JSON"; then | |
| echo "${{ matrix.package.name }} version did not change in the version-bump commit" | |
| echo "has-new-version=false" >> "$GITHUB_OUTPUT" | |
| elif git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then | |
| echo "Tag $RELEASE_TAG already exists - no new version to release" | |
| echo "has-new-version=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "New ${{ matrix.package.name }} version detected: $CURRENT_VERSION" | |
| echo "has-new-version=true" >> "$GITHUB_OUTPUT" | |
| echo "version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Restore NuGet packages | |
| if: steps.detect-version.outputs.has-new-version == 'true' | |
| run: dotnet restore --locked-mode | |
| - name: Build and pack ${{ matrix.package.name }} | |
| if: steps.detect-version.outputs.has-new-version == 'true' | |
| run: dotnet build "${{ matrix.package.project }}" --configuration Release --no-restore | |
| - name: NuGet login | |
| if: steps.detect-version.outputs.has-new-version == 'true' | |
| uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1.2.0 | |
| id: login | |
| with: | |
| user: PostHog-Engineering | |
| - name: Publish ${{ matrix.package.name }} to NuGet | |
| if: steps.detect-version.outputs.has-new-version == 'true' | |
| env: | |
| NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }} | |
| PACKAGE_NAME: ${{ matrix.package.name }} | |
| PACKAGE_VERSION: ${{ steps.detect-version.outputs.version }} | |
| run: | | |
| package_file="${{ env.PackageDirectory }}/${PACKAGE_NAME}.${PACKAGE_VERSION}.nupkg" | |
| if [ ! -f "$package_file" ]; then | |
| echo "Package file not found: $package_file" >&2 | |
| find "${{ env.PackageDirectory }}" -type f -name '*.nupkg' -print >&2 || true | |
| exit 1 | |
| fi | |
| dotnet nuget push "$package_file" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate | |
| - name: Tag and push ${{ matrix.package.name }} | |
| if: steps.detect-version.outputs.has-new-version == 'true' | |
| env: | |
| RELEASE_TAG: ${{ steps.detect-version.outputs.tag }} | |
| RELEASE_VERSION: ${{ steps.detect-version.outputs.version }} | |
| PACKAGE_NAME: ${{ matrix.package.name }} | |
| run: | | |
| git tag -a "$RELEASE_TAG" -m "$PACKAGE_NAME $RELEASE_VERSION" | |
| git push origin "$RELEASE_TAG" | |
| - name: Create GitHub release for ${{ matrix.package.name }} | |
| if: steps.detect-version.outputs.has-new-version == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_TAG: ${{ steps.detect-version.outputs.tag }} | |
| CHANGELOG_FILE: ${{ matrix.package.changelog }} | |
| run: | | |
| if [ -f "$CHANGELOG_FILE" ]; then | |
| awk -v defText="See $CHANGELOG_FILE" ' | |
| /^## / { if (found_version) exit; found_version=1; next } | |
| found_version { print } | |
| END { if (!found_version) print defText } | |
| ' "$CHANGELOG_FILE" | sed '/[^[:space:]]/,$!d' | tac | sed '/[^[:space:]]/,$!d' | tac > release-notes.md | |
| else | |
| echo "See $CHANGELOG_FILE" > release-notes.md | |
| fi | |
| gh release create "$RELEASE_TAG" \ | |
| --target "${{ needs.version-bump.outputs.commit-sha }}" \ | |
| --title "$RELEASE_TAG" \ | |
| --notes-file release-notes.md | |
| - name: Send failure event to PostHog | |
| if: failure() | |
| continue-on-error: true | |
| uses: PostHog/posthog-github-action@9a6a19d360820ab4d95ecc4a5a7564062c895f84 # v1.3.0 | |
| with: | |
| posthog-token: "${{ secrets.POSTHOG_PROJECT_API_KEY }}" | |
| event: "posthog-sdk-github-release-workflow-failure" | |
| properties: >- | |
| { | |
| "commitSha": "${{ github.sha }}", | |
| "jobStatus": "${{ job.status }}", | |
| "ref": "${{ github.ref }}", | |
| "repository": "${{ github.repository }}", | |
| "sdk": "posthog-dotnet", | |
| "jobName": "publish", | |
| "packageName": "${{ matrix.package.name }}", | |
| "packageVersion": "${{ steps.detect-version.outputs.version || 'unknown' }}", | |
| "actionUrl": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", | |
| "alertText": ":rotating_light: Failed to release ${{ matrix.package.name }}@${{ steps.detect-version.outputs.version }} :rotating_light:", | |
| "alertContext": "The package publish step failed." | |
| } | |
| - name: Notify Slack - Failed | |
| if: failure() && needs.notify-approval-needed.outputs.slack_ts != '' | |
| uses: posthog/.github/.github/actions/slack-thread-reply@cb0979b67dcd585828b61ac45927eef4da8f6287 # 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 `${{ matrix.package.name }}@${{ steps.detect-version.outputs.version }}`! <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>" | |
| emoji_reaction: "x" | |
| notify-rejected: | |
| name: Notify Slack - Rejected | |
| needs: [version-bump, notify-approval-needed] | |
| runs-on: ubuntu-latest | |
| if: always() && (needs.version-bump.result == 'failure' || needs.version-bump.result == 'skipped') && needs.notify-approval-needed.outputs.slack_ts != '' | |
| steps: | |
| - name: Check for rejection | |
| id: check-rejection | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GITHUB_REPOSITORY_NAME: ${{ github.repository }} | |
| GITHUB_RUN_ID_VALUE: ${{ github.run_id }} | |
| run: | | |
| RESPONSE=$(gh api "/repos/$GITHUB_REPOSITORY_NAME/actions/runs/$GITHUB_RUN_ID_VALUE/approvals") | |
| REJECTED=$(echo "$RESPONSE" | jq '[.[] | select(.state == "rejected")] | length') | |
| if [ "$REJECTED" -gt 0 ]; then | |
| echo "was_rejected=true" >> "$GITHUB_OUTPUT" | |
| COMMENT=$(echo "$RESPONSE" | jq -r '.[] | select(.state == "rejected") | .comment // empty' | head -1) | |
| if [ -n "$COMMENT" ]; then | |
| { | |
| echo 'message<<EOF' | |
| echo "🚫 Release was rejected: $COMMENT" | |
| echo 'EOF' | |
| } >> "$GITHUB_OUTPUT" | |
| else | |
| echo "message=🚫 Release was rejected." >> "$GITHUB_OUTPUT" | |
| fi | |
| else | |
| echo "was_rejected=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Notify Slack - Rejected | |
| if: steps.check-rejection.outputs.was_rejected == 'true' | |
| continue-on-error: true | |
| uses: posthog/.github/.github/actions/slack-thread-reply@cb0979b67dcd585828b61ac45927eef4da8f6287 # 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: '${{ steps.check-rejection.outputs.message }}' | |
| emoji_reaction: 'no_entry_sign' | |
| notify-released: | |
| name: Notify Slack - Released | |
| needs: [notify-approval-needed, publish] | |
| runs-on: ubuntu-latest | |
| if: always() && needs.publish.result == 'success' && needs.notify-approval-needed.outputs.slack_ts != '' | |
| steps: | |
| - name: Notify Slack - Released | |
| uses: posthog/.github/.github/actions/slack-thread-reply@cb0979b67dcd585828b61ac45927eef4da8f6287 # 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: "🚀 Released updated posthog-dotnet packages successfully!" | |
| emoji_reaction: "rocket" |