-
Notifications
You must be signed in to change notification settings - Fork 240
chore: upload posthog-js dist to S3 on release #3307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
0526f48
09f9d9d
b064f9b
33ae2d8
41e40e9
bbeadb3
fa44b4a
a8c6f89
2e0d22c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Upload posthog-js dist artifacts to S3 and append the version to versions.json. | ||
| # | ||
| # Usage: | ||
| # VERSION=1.365.0 ./upload-posthog-js-s3.sh <bucket> | ||
| # | ||
| # VERSION must be set as an environment variable (not an argument) to avoid | ||
| # shell injection if the value were ever attacker-influenced. | ||
| # | ||
| # Expects AWS credentials to be configured before invocation. | ||
| # | ||
| set -euo pipefail | ||
|
|
||
| BUCKET="${1:?Usage: VERSION=x.y.z $0 <bucket>}" | ||
| DIST_DIR="packages/browser/dist" | ||
|
|
||
| if [[ -z "${VERSION:-}" ]]; then | ||
| echo "ERROR: VERSION environment variable is required" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Validate version is strict semver (e.g. 1.365.0 or 1.365.0-beta.1). | ||
| # Prevents path traversal — no slashes, dots only in expected positions. | ||
| if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-][a-zA-Z0-9.]+)?$ ]]; then | ||
| echo "ERROR: Invalid version format: '$VERSION'" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "==> Uploading posthog-js v$VERSION to s3://$BUCKET/$VERSION/" | ||
| aws s3 cp "$DIST_DIR/" "s3://$BUCKET/$VERSION/" \ | ||
| --recursive \ | ||
| --exclude "*" \ | ||
| --include "*.js" \ | ||
| --cache-control "public, max-age=31536000, immutable" \ | ||
| --content-type "application/javascript" | ||
|
|
||
| echo "==> Updating versions.json in s3://$BUCKET/" | ||
| TMPDIR="$(mktemp -d)" | ||
| trap 'rm -rf "$TMPDIR"' EXIT | ||
|
|
||
| # Distinguish "file doesn't exist" from real errors (auth, network). | ||
| # A blind fallback to '[]' on any error would silently drop all previous versions. | ||
| if aws s3 cp "s3://$BUCKET/versions.json" "$TMPDIR/versions.json"; then | ||
| echo "Downloaded existing versions.json" | ||
| elif aws s3api head-object --bucket "$BUCKET" --key "versions.json" 2>/dev/null; then | ||
| echo "ERROR: versions.json exists but could not be downloaded" >&2 | ||
| exit 1 | ||
| else | ||
| echo "No existing versions.json found, starting fresh" | ||
| echo '[]' > "$TMPDIR/versions.json" | ||
| fi | ||
|
|
||
| if jq -e --arg v "$VERSION" '.[] | select(.version == $v)' "$TMPDIR/versions.json" > /dev/null 2>&1; then | ||
| echo "Version $VERSION already in versions.json, skipping" | ||
| else | ||
| jq --arg v "$VERSION" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ | ||
| '. + [{"version": $v, "timestamp": $ts}]' "$TMPDIR/versions.json" > "$TMPDIR/versions_updated.json" | ||
| aws s3 cp "$TMPDIR/versions_updated.json" "s3://$BUCKET/versions.json" \ | ||
| --content-type "application/json" | ||
|
Comment on lines
+57
to
+73
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like the riskiest bit to me, since one bad change will break the entire file. I'm assuming using jq to modify the file means it will only ever generate valid json. Is there any additional check we can run here to verify the contents match what we expect before publishing?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added some additional verification's using
This is a good point though. Breaking this file would mean breaking version synchronization. I'll make a note to add some server-side observability for this case. |
||
| echo "Added v$VERSION to versions.json" | ||
| fi | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -334,11 +334,107 @@ jobs: | |
| message: '❌ Failed to release `${{ matrix.package.name }}@v${{ steps.check-package-version.outputs.committed-version }}`! <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>' | ||
| emoji_reaction: 'x' | ||
|
|
||
| build-s3-artifacts: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The aws script is racey, so verified this workflow already limits concurrency to 1 👍 |
||
| name: Build posthog-js dist for S3 | ||
| needs: [version-bump, publish, notify-approval-needed] | ||
| runs-on: ubuntu-latest | ||
| # Run as long as the version bump committed — even if some matrix publishes failed, | ||
| # posthog-js might have succeeded and we still want the artifacts in S3. | ||
| if: always() && needs.version-bump.outputs.commit-hash != '' | ||
| permissions: | ||
| contents: read | ||
| outputs: | ||
| is-new-version: ${{ steps.check-version.outputs.is-new-version }} | ||
| committed-version: ${{ steps.check-version.outputs.committed-version }} | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ needs.version-bump.outputs.commit-hash }} | ||
| fetch-depth: 0 | ||
dustinbyrne marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| - name: Check posthog-js version | ||
| id: check-version | ||
| uses: PostHog/check-package-version@v2.1.0 | ||
dustinbyrne marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| with: | ||
| path: packages/browser | ||
|
|
||
| - name: Setup environment | ||
| if: steps.check-version.outputs.is-new-version == 'true' | ||
| uses: ./.github/actions/setup | ||
|
|
||
| - name: Upload dist artifact | ||
| if: steps.check-version.outputs.is-new-version == 'true' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: posthog-js-dist | ||
| path: packages/browser/dist/*.js | ||
| retention-days: 1 | ||
| if-no-files-found: error | ||
|
|
||
| upload-s3: | ||
| name: Upload posthog-js dist to S3 | ||
| needs: [build-s3-artifacts, version-bump, notify-approval-needed] | ||
| runs-on: ubuntu-latest | ||
| if: always() && needs.build-s3-artifacts.outputs.is-new-version == 'true' | ||
| environment: 'S3 Upload' # For OIDC credential scoping only — no required reviewers (single approval at NPM Release) | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| steps: | ||
| # Sparse checkout: only the upload script — no pnpm install/build runs here. | ||
| - name: Checkout upload script | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ needs.version-bump.outputs.commit-hash }} | ||
| sparse-checkout: .github/scripts | ||
|
|
||
| - name: Download dist artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: posthog-js-dist | ||
| path: packages/browser/dist | ||
|
|
||
| # Upload to US (us-east-1) | ||
| - name: Configure AWS credentials (US) | ||
| uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6 | ||
| with: | ||
| role-to-assume: ${{ vars.AWS_S3_UPLOAD_ROLE_ARN_US }} | ||
| aws-region: us-east-1 | ||
|
|
||
| - name: Upload dist and update manifest (US) | ||
| env: | ||
| VERSION: ${{ needs.build-s3-artifacts.outputs.committed-version }} | ||
| run: .github/scripts/upload-posthog-js-s3.sh posthog-js-prod-us | ||
|
|
||
| # Upload to EU (eu-central-1) | ||
| - name: Configure AWS credentials (EU) | ||
| uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6 | ||
| with: | ||
| role-to-assume: ${{ vars.AWS_S3_UPLOAD_ROLE_ARN_EU }} | ||
| aws-region: eu-central-1 | ||
|
|
||
| - name: Upload dist and update manifest (EU) | ||
| env: | ||
| VERSION: ${{ needs.build-s3-artifacts.outputs.committed-version }} | ||
| run: .github/scripts/upload-posthog-js-s3.sh posthog-js-prod-eu | ||
|
|
||
| - name: Notify Slack - S3 Upload Failed | ||
| continue-on-error: true | ||
| 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 upload posthog-js v${{ needs.build-s3-artifacts.outputs.committed-version }} dist to S3! <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, publish] | ||
| needs: [notify-approval-needed, publish, upload-s3] | ||
| runs-on: ubuntu-latest | ||
| if: always() && needs.publish.result == 'success' && needs.notify-approval-needed.outputs.slack_ts != '' | ||
| if: always() && needs.publish.result == 'success' && needs.upload-s3.result == 'success' && needs.notify-approval-needed.outputs.slack_ts != '' | ||
dustinbyrne marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.