Skip to content

fix(replay-vision): select Slack workspace for alerts #131090

fix(replay-vision): select Slack workspace for alerts

fix(replay-vision): select Slack workspace for alerts #131090

name: Build and deploy ml-mirror-image-scrub container image
on:
workflow_dispatch:
pull_request:
push:
branches:
- 'master'
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
changes:
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: read
timeout-minutes: 5
if: github.repository_owner == 'PostHog'
name: Determine need to run ml-mirror-image-scrub Docker build
outputs:
scrub_files: ${{ steps.filter.outputs.scrub_files }}
steps:
- name: Check out
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: .github/actions/paths-filter
sparse-checkout-cone-mode: false
- uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
id: app-token
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
with:
client-id: ${{ vars.GH_APP_POSTHOG_PATHS_FILTER_APP_ID }}
private-key: ${{ secrets.GH_APP_POSTHOG_PATHS_FILTER_PRIVATE_KEY }}
- uses: ./.github/actions/paths-filter
id: filter
with:
token: ${{ steps.app-token.outputs.token || github.token }}
# The image and the unit tests both build the replay-anonymizer addon from these crates and the workspace files cargo reads.
filters: |
scrub_files:
- 'nodejs/src/ingestion/pipelines/sessionreplay/ml-mirror-image-scrub-sidecar/**'
- 'rust/replay-anonymizer/**'
- 'rust/replay-anonymizer-node/**'
- 'rust/Cargo.toml'
- 'rust/Cargo.lock'
- 'rust/.cargo/config.toml'
- 'Dockerfile.ml-mirror-image-scrub'
- '.github/workflows/ci-ml-mirror-image-scrub-container.yml'
test:
needs: changes
name: Unit-test ml-mirror-image-scrub
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && needs.changes.outputs.scrub_files == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
defaults:
run:
working-directory: nodejs/src/ingestion/pipelines/sessionreplay/ml-mirror-image-scrub-sidecar
steps:
- name: Check out
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: .nvmrc
- name: Install dependencies
# Standalone package: own lockfile, outside the root pnpm workspace, so ignore the workspace.
run: corepack enable && CI=1 pnpm install --frozen-lockfile --ignore-workspace
- name: Lint
run: pnpm lint
- name: Format check
run: pnpm format:check
- name: Typecheck
# jest runs through babel (no type errors), so tsc is the only thing that typechecks the worker.
run: pnpm typecheck
- name: Install Rust
uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: 1.91.1
- name: Build the native addon
# src/pixel-convert.ts loads the addon at import, so every suite that reaches a detector needs it.
run: pnpm build:native
- name: Run unit tests
run: pnpm test:unit
build:
needs: changes
name: Build and push ml-mirror-image-scrub image
# Skipped on trunk-merge/** branches: merge-queue PRs are ephemeral, nothing
# pulls images pushed for them, and each constituent PR already built its own.
if: |
!startsWith(github.head_ref, 'trunk-merge/') &&
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && needs.changes.outputs.scrub_files == 'true') ||
(github.event_name == 'workflow_dispatch' && github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true') ||
(github.event_name == 'push' && github.ref == 'refs/heads/master' && needs.changes.outputs.scrub_files == 'true' && github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true'))
runs-on: depot-ubuntu-24.04
timeout-minutes: 30
permissions:
id-token: write # allow issuing OIDC tokens for this workflow run
contents: read # allow reading the repo contents
packages: write # allow push to ghcr.io
outputs:
digest: ${{ steps.build.outputs.digest }}
# ECR routing resolved once so the push target can't drift from the digest reader:
# master → posthog-ml-mirror-image-scrub via the master role; else → the -prs repo via the prs role.
env:
ECR_IMAGE: ${{ github.ref == 'refs/heads/master' && 'posthog-ml-mirror-image-scrub' || 'posthog-ml-mirror-image-scrub-prs' }}
ECR_ROLE: ${{ github.ref == 'refs/heads/master' && vars.AWS_ECR_POSTHOG_MASTER_PUBLISH_IAM_ROLE || vars.AWS_ECR_POSTHOG_PRS_PUBLISH_IAM_ROLE }}
steps:
- name: Assert master publish role is configured
if: github.ref == 'refs/heads/master'
env:
MASTER_ROLE: ${{ vars.AWS_ECR_POSTHOG_MASTER_PUBLISH_IAM_ROLE }}
run: |
if [[ -z "$MASTER_ROLE" ]]; then
echo "::error::AWS_ECR_POSTHOG_MASTER_PUBLISH_IAM_ROLE is not set — refusing to fall back to the PRS role on master."
exit 1
fi
- name: Check out
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Depot CLI
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1
- name: Docker meta and registry login
id: docker-meta
uses: ./.github/actions/docker-meta
with:
image-name: posthog-ml-mirror-image-scrub
# ECR repo + role resolved once at job level (see env above). ghcr/dockerhub unchanged.
ecr-image-name: ${{ env.ECR_IMAGE }}
aws-role-to-assume: ${{ env.ECR_ROLE }}
github-token: ${{ secrets.GITHUB_TOKEN }}
dockerhub-username: ${{ secrets.DOCKERHUB_USER }}
dockerhub-password: ${{ secrets.DOCKERHUB_TOKEN }}
# Prod deploys from private ECR; pause the public ghcr push during an embargo.
push-to-ghcr: ${{ vars.PUBLIC_IMAGE_PUSH_PAUSED != 'true' }}
- name: Build and push container image
id: build
uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0
with:
context: .
buildx-fallback: false
# Depot project "replay-vision-ingestion-ml-mirror-image-scrub".
project: 'hmrgpk84ch'
push: ${{ github.event_name == 'pull_request' || vars.CD_DEPLOY_ENABLED == 'true' }}
file: Dockerfile.ml-mirror-image-scrub
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}
annotations: ${{ steps.docker-meta.outputs.annotations }}
# Both arches: the charts-side Karpenter NodePool defaults to arm64 (Graviton), and an
# amd64-only manifest fails there with "no match for platform in manifest".
platforms: linux/amd64,linux/arm64
build-args: |
COMMIT_HASH=${{ github.sha }}
- name: Container image digest
env:
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
IMAGE_REGISTRY: ${{ steps.docker-meta.outputs.ecr-registry }}
COMMIT_SHA: ${{ github.sha }}
run: |
echo "Image digest: $IMAGE_DIGEST"
echo "Full image reference: $IMAGE_REGISTRY/$ECR_IMAGE:$COMMIT_SHA@$IMAGE_DIGEST"
echo "## Container image built :rocket:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image reference:** \`$IMAGE_REGISTRY/$ECR_IMAGE:$COMMIT_SHA@$IMAGE_DIGEST\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image SHA:** \`$COMMIT_SHA@$IMAGE_DIGEST\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Commit: \`$COMMIT_SHA\`" >> $GITHUB_STEP_SUMMARY
echo "- Digest: \`$IMAGE_DIGEST\`" >> $GITHUB_STEP_SUMMARY
- name: Report failure
if: failure()
uses: PostHog/posthog-github-action@58dea254b598fb5d469c0699c98af8288a7f7650 # v1.2.0
with:
posthog-token: ${{ secrets.POSTHOG_API_TOKEN }}
event: 'ml-mirror-image-scrub-image-build'
properties: '{"status": "failure", "commit_hash": "${{ github.sha }}"}'
- name: Report failure to DevEx PostHog
if: failure()
continue-on-error: true
uses: PostHog/posthog-github-action@58dea254b598fb5d469c0699c98af8288a7f7650 # v1.2.0
with:
posthog-token: ${{ secrets.POSTHOG_DEVEX_PROJECT_API_TOKEN }}
event: 'ml-mirror-image-scrub-image-build'
properties: '{"status": "failure", "commit_hash": "${{ github.sha }}"}'
deploy:
name: Deploy ml-mirror-image-scrub service
runs-on: ubuntu-24.04
timeout-minutes: 5
needs: build
if: github.repository_owner == 'PostHog' && vars.CD_DEPLOY_ENABLED == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/master'
permissions:
contents: read
steps:
- name: Check out
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Get deployer token
id: deployer
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
client-id: ${{ secrets.GH_APP_CHARTS_DEPLOYER_APP_ID }}
private-key: ${{ secrets.GH_APP_CHARTS_DEPLOYER_PRIVATE_KEY }}
owner: PostHog
repositories: charts
- name: Get PR labels
id: labels
uses: ./.github/actions/get-pr-labels
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Trigger ml-mirror-image-scrub deployment
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
token: ${{ steps.deployer.outputs.token }}
repository: PostHog/charts
event-type: commit_state_update
client-payload: |
{
"values": {
"image": {
"sha": "${{ github.sha }}@${{ needs.build.outputs.digest }}"
}
},
"release": "ml-mirror-image-scrub",
"commit": ${{ toJson(github.event.head_commit) }},
"repository": ${{ toJson(github.repository) }},
"labels": ${{ steps.labels.outputs.labels }},
"timestamp": "${{ github.event.head_commit.timestamp }}"
}