From 7d61582b38288c165130b5d2308270a0c70529f7 Mon Sep 17 00:00:00 2001 From: Marta Paciorkowska Date: Tue, 28 Apr 2026 16:10:37 +0200 Subject: [PATCH 1/6] feat: a reusable action for sending usage metrics to PostHog --- .github/actions/posthog/action.yml | 80 ++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 .github/actions/posthog/action.yml diff --git a/.github/actions/posthog/action.yml b/.github/actions/posthog/action.yml new file mode 100644 index 0000000..064ac19 --- /dev/null +++ b/.github/actions/posthog/action.yml @@ -0,0 +1,80 @@ +name: PostHog Capture +description: Send a workflow analytics event to PostHog + +inputs: + api_key: + description: "PostHog project API key" + required: true + github_repository: + description: "GitHub repository in the format 'owner/repo' (e.g. 'entur/gha-meta')" + required: true + workflow_inputs: + description: "Workflow inputs as a JSON string (e.g. toJSON(inputs))" + required: false + default: "{}" + workflow_name: + description: "Name of the workflow. Used as the event name: {workflow_name}_executed" + required: true + +runs: + using: composite + steps: + - name: Send event + shell: bash + env: + POSTHOG_API_KEY: ${{ inputs.api_key }} + WORKFLOW_INPUTS: ${{ inputs.workflow_inputs }} + WORKFLOW_NAME: ${{ inputs.workflow_name }} + GITHUB_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ inputs.github_repository }} + run: | + set +e + set +o pipefail + + # Resolve version by finding this reusable workflow's entry in the caller's run. + # (GITHUB_WORKFLOW_REF is the caller's ref, not the reusable workflow's ref) + RUN_DATA=$(curl -sf \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || echo "{}") + + GHA_SHA=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GITHUB_REPOSITORY)) | .sha' | head -1) + GHA_REF=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GITHUB_REPOSITORY)) | .ref // ""' | head -1) + + WORKFLOW_VERSION="" + if [ -n "$GHA_REF" ]; then + WORKFLOW_VERSION="${GHA_REF}" + elif [ -n "$GHA_SHA" ]; then + WORKFLOW_VERSION="${GHA_SHA:0:7}" + fi + + echo "Workflow version: $WORKFLOW_VERSION" + + payload=$(jq -n \ + --arg api_key "$POSTHOG_API_KEY" \ + --arg repo "$GITHUB_REPOSITORY" \ + --arg name "$WORKFLOW_NAME" \ + --arg version "$WORKFLOW_VERSION" \ + --argjson inputs "$WORKFLOW_INPUTS" \ + --arg event "$GITHUB_EVENT_NAME" \ + --arg run_id "$GITHUB_RUN_ID" \ + '{ + api_key: $api_key, + event: ($name + "_executed"), + distinct_id: $repo, + properties: ( + { + workflow_name: $name, + workflow_version: $version, + repository: $repo, + event_name: $event, + run_id: $run_id + } + + ($inputs | with_entries(.key = ("input_" + .key))) + ) + }') + + curl -s --max-time 5 \ + -H "Content-Type: application/json" \ + -d "$payload" \ + https://eu.posthog.com/capture/ || true From 643c7ecc017a3f4029fbb06d2d10878fb8f174e8 Mon Sep 17 00:00:00 2001 From: Marta Paciorkowska Date: Wed, 29 Apr 2026 10:08:31 +0200 Subject: [PATCH 2/6] Splits sending event into smaller steps, renames event --- .github/actions/posthog/action.yml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/actions/posthog/action.yml b/.github/actions/posthog/action.yml index 064ac19..269c23f 100644 --- a/.github/actions/posthog/action.yml +++ b/.github/actions/posthog/action.yml @@ -13,20 +13,15 @@ inputs: required: false default: "{}" workflow_name: - description: "Name of the workflow. Used as the event name: {workflow_name}_executed" + description: "Name of the workflow. Used as the event name in PostHog." required: true runs: using: composite steps: - - name: Send event + - name: Resolve action version + id: workflow_version shell: bash - env: - POSTHOG_API_KEY: ${{ inputs.api_key }} - WORKFLOW_INPUTS: ${{ inputs.workflow_inputs }} - WORKFLOW_NAME: ${{ inputs.workflow_name }} - GITHUB_TOKEN: ${{ github.token }} - GITHUB_REPOSITORY: ${{ inputs.github_repository }} run: | set +e set +o pipefail @@ -49,6 +44,19 @@ runs: fi echo "Workflow version: $WORKFLOW_VERSION" + echo "workflow_version=${WORKFLOW_VERSION}" >> "$GITHUB_OUTPUT" + - name: Send event + shell: bash + env: + POSTHOG_API_KEY: ${{ inputs.api_key }} + WORKFLOW_INPUTS: ${{ inputs.workflow_inputs }} + WORKFLOW_NAME: ${{ inputs.workflow_name }} + WORKFLOW_VERSION: ${{ steps.workflow_version.outputs.workflow_version }} + GITHUB_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ inputs.github_repository }} + run: | + set +e + set +o pipefail payload=$(jq -n \ --arg api_key "$POSTHOG_API_KEY" \ @@ -60,7 +68,7 @@ runs: --arg run_id "$GITHUB_RUN_ID" \ '{ api_key: $api_key, - event: ($name + "_executed"), + event: $name, distinct_id: $repo, properties: ( { From 2720ea8e576b4a9bf3fc134ddc8af489e0a77c57 Mon Sep 17 00:00:00 2001 From: Marta Paciorkowska Date: Wed, 29 Apr 2026 12:27:58 +0200 Subject: [PATCH 3/6] Limits building output just to properties, sends event using external gha --- .github/actions/posthog/action.yml | 75 +++++++++++++++--------------- .gitignore | 4 +- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/.github/actions/posthog/action.yml b/.github/actions/posthog/action.yml index 269c23f..618c514 100644 --- a/.github/actions/posthog/action.yml +++ b/.github/actions/posthog/action.yml @@ -5,15 +5,15 @@ inputs: api_key: description: "PostHog project API key" required: true - github_repository: - description: "GitHub repository in the format 'owner/repo' (e.g. 'entur/gha-meta')" + gha_repository: + description: "GitHub repository where the reusable workflow lives, in the format 'owner/repo' (e.g. 'entur/gha-helm')" required: true workflow_inputs: description: "Workflow inputs as a JSON string (e.g. toJSON(inputs))" required: false default: "{}" workflow_name: - description: "Name of the workflow. Used as the event name in PostHog." + description: "Name of the workflow. Used as the event name in PostHog (lint, deploy, etc.)" required: true runs: @@ -21,20 +21,22 @@ runs: steps: - name: Resolve action version id: workflow_version + env: + GHA_REPOSITORY: ${{ inputs.gha_repository }} shell: bash run: | set +e - set +o pipefail + set -o pipefail # Resolve version by finding this reusable workflow's entry in the caller's run. # (GITHUB_WORKFLOW_REF is the caller's ref, not the reusable workflow's ref) RUN_DATA=$(curl -sf \ -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "Accept: application/vnd.github+json" \ - "https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || echo "{}") + "https://api.github.com/repos/${GHA_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || echo "{}") - GHA_SHA=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GITHUB_REPOSITORY)) | .sha' | head -1) - GHA_REF=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GITHUB_REPOSITORY)) | .ref // ""' | head -1) + GHA_SHA=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GHA_REPOSITORY)) | .sha' | head -1) + GHA_REF=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GHA_REPOSITORY)) | .ref // ""' | head -1) WORKFLOW_VERSION="" if [ -n "$GHA_REF" ]; then @@ -45,44 +47,43 @@ runs: echo "Workflow version: $WORKFLOW_VERSION" echo "workflow_version=${WORKFLOW_VERSION}" >> "$GITHUB_OUTPUT" - - name: Send event + - name: Build properties + id: build_properties shell: bash env: - POSTHOG_API_KEY: ${{ inputs.api_key }} + GITHUB_TOKEN: ${{ github.token }} + GHA_REPOSITORY: ${{ inputs.gha_repository }} WORKFLOW_INPUTS: ${{ inputs.workflow_inputs }} WORKFLOW_NAME: ${{ inputs.workflow_name }} WORKFLOW_VERSION: ${{ steps.workflow_version.outputs.workflow_version }} - GITHUB_TOKEN: ${{ github.token }} - GITHUB_REPOSITORY: ${{ inputs.github_repository }} run: | set +e - set +o pipefail + set -o pipefail - payload=$(jq -n \ - --arg api_key "$POSTHOG_API_KEY" \ - --arg repo "$GITHUB_REPOSITORY" \ - --arg name "$WORKFLOW_NAME" \ - --arg version "$WORKFLOW_VERSION" \ - --argjson inputs "$WORKFLOW_INPUTS" \ + properties=$(jq -n \ --arg event "$GITHUB_EVENT_NAME" \ + --argjson inputs "$WORKFLOW_INPUTS" \ + --arg name "$WORKFLOW_NAME" \ + --arg repo "$GHA_REPOSITORY" \ --arg run_id "$GITHUB_RUN_ID" \ + --arg version "$WORKFLOW_VERSION" \ '{ - api_key: $api_key, - event: $name, - distinct_id: $repo, - properties: ( - { - workflow_name: $name, - workflow_version: $version, - repository: $repo, - event_name: $event, - run_id: $run_id - } - + ($inputs | with_entries(.key = ("input_" + .key))) - ) - }') - - curl -s --max-time 5 \ - -H "Content-Type: application/json" \ - -d "$payload" \ - https://eu.posthog.com/capture/ || true + event_name: $event, + gha_repository: $repo, + run_id: $run_id, + workflow_name: $name, + workflow_version: $version + } + + ($inputs | with_entries(.key = ("input_" + .key)))' + ) + echo "properties=$(echo "$properties" | jq -c .)" >> "$GITHUB_OUTPUT" + - name: Send event to PostHog + uses: PostHog/posthog-github-action@58dea254b598fb5d469c0699c98af8288a7f7650 # v1.2.0 + continue-on-error: true + with: + capture-run-duration: 'true' + event: ${{ inputs.workflow_name }} + github-token: ${{ github.token }} + posthog-api-host: https://eu.i.posthog.com + posthog-token: ${{ inputs.api_key }} + properties: ${{ steps.build_properties.outputs.properties }} diff --git a/.gitignore b/.gitignore index e62667f..e68c876 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ # Intellij IDEA -.idea \ No newline at end of file +.idea +.vscode/settings.json +.DS_Store From 38f8a955a5dcd5288c17f1dea91319cb9b92aab9 Mon Sep 17 00:00:00 2001 From: Marta Paciorkowska Date: Wed, 29 Apr 2026 16:29:27 +0200 Subject: [PATCH 4/6] Apply suggestions from code review Co-authored-by: Glenn Terjesen <48587132+Glenn-Terjesen@users.noreply.github.com> --- .github/actions/posthog/action.yml | 55 +++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/.github/actions/posthog/action.yml b/.github/actions/posthog/action.yml index 618c514..766a412 100644 --- a/.github/actions/posthog/action.yml +++ b/.github/actions/posthog/action.yml @@ -33,9 +33,10 @@ runs: RUN_DATA=$(curl -sf \ -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "Accept: application/vnd.github+json" \ - "https://api.github.com/repos/${GHA_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || echo "{}") + "https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || echo "{}") - GHA_SHA=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GHA_REPOSITORY)) | .sha' | head -1) + GHA_SHA=$(echo "$RUN_DATA" | jq -r --arg repo "$GHA_REPOSITORY" \ + '(.referenced_workflows // [])[] | select(.path | startswith($repo)) | .sha' | head -1) GHA_REF=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GHA_REPOSITORY)) | .ref // ""' | head -1) WORKFLOW_VERSION="" @@ -56,27 +57,35 @@ runs: WORKFLOW_INPUTS: ${{ inputs.workflow_inputs }} WORKFLOW_NAME: ${{ inputs.workflow_name }} WORKFLOW_VERSION: ${{ steps.workflow_version.outputs.workflow_version }} - run: | - set +e - set -o pipefail - - properties=$(jq -n \ - --arg event "$GITHUB_EVENT_NAME" \ - --argjson inputs "$WORKFLOW_INPUTS" \ - --arg name "$WORKFLOW_NAME" \ - --arg repo "$GHA_REPOSITORY" \ - --arg run_id "$GITHUB_RUN_ID" \ - --arg version "$WORKFLOW_VERSION" \ - '{ - event_name: $event, - gha_repository: $repo, - run_id: $run_id, - workflow_name: $name, - workflow_version: $version - } - + ($inputs | with_entries(.key = ("input_" + .key)))' - ) - echo "properties=$(echo "$properties" | jq -c .)" >> "$GITHUB_OUTPUT" + set +e + set -o pipefail + + # Strip inputs whose key names suggest sensitive content + SAFE_INPUTS=$(echo "$WORKFLOW_INPUTS" | jq -c ' + with_entries( + select( + (.key | test("token|secret|key|password|credential|auth"; "i")) | not + ) + ) + ') + + properties=$(jq -n \ + --arg event "$GITHUB_EVENT_NAME" \ + --argjson inputs "$SAFE_INPUTS" \ + --arg name "$WORKFLOW_NAME" \ + --arg repo "$GHA_REPOSITORY" \ + --arg run_id "$GITHUB_RUN_ID" \ + --arg version "$WORKFLOW_VERSION" \ + '{ + event_name: $event, + gha_repository: $repo, + run_id: $run_id, + workflow_name: $name, + workflow_version: $version + } + + ($inputs | with_entries(.key = ("input_" + .key)))' + ) + echo "properties=$(echo "$properties" | jq -c .)" >> "$GITHUB_OUTPUT" - name: Send event to PostHog uses: PostHog/posthog-github-action@58dea254b598fb5d469c0699c98af8288a7f7650 # v1.2.0 continue-on-error: true From 6b983008ae76ca8cafcf456dbbb14dad2d55fc1a Mon Sep 17 00:00:00 2001 From: Marta Paciorkowska Date: Wed, 29 Apr 2026 17:00:13 +0200 Subject: [PATCH 5/6] fix indentation --- .github/actions/posthog/action.yml | 39 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/.github/actions/posthog/action.yml b/.github/actions/posthog/action.yml index 766a412..2a12bd8 100644 --- a/.github/actions/posthog/action.yml +++ b/.github/actions/posthog/action.yml @@ -25,7 +25,6 @@ runs: GHA_REPOSITORY: ${{ inputs.gha_repository }} shell: bash run: | - set +e set -o pipefail # Resolve version by finding this reusable workflow's entry in the caller's run. @@ -36,7 +35,7 @@ runs: "https://api.github.com/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || echo "{}") GHA_SHA=$(echo "$RUN_DATA" | jq -r --arg repo "$GHA_REPOSITORY" \ - '(.referenced_workflows // [])[] | select(.path | startswith($repo)) | .sha' | head -1) + '(.referenced_workflows // [])[] | select(.path | startswith($repo)) | .sha' | head -1) GHA_REF=$(echo "$RUN_DATA" | jq -r '(.referenced_workflows // [])[] | select(.path | startswith($GHA_REPOSITORY)) | .ref // ""' | head -1) WORKFLOW_VERSION="" @@ -57,33 +56,33 @@ runs: WORKFLOW_INPUTS: ${{ inputs.workflow_inputs }} WORKFLOW_NAME: ${{ inputs.workflow_name }} WORKFLOW_VERSION: ${{ steps.workflow_version.outputs.workflow_version }} - set +e - set -o pipefail - - # Strip inputs whose key names suggest sensitive content - SAFE_INPUTS=$(echo "$WORKFLOW_INPUTS" | jq -c ' - with_entries( - select( + run: | + set -o pipefail + + # Strip inputs whose key names suggest sensitive content + SAFE_INPUTS=$(echo "$WORKFLOW_INPUTS" | jq -c ' + with_entries( + select( (.key | test("token|secret|key|password|credential|auth"; "i")) | not ) ) ') - properties=$(jq -n \ + properties=$(jq -n \ --arg event "$GITHUB_EVENT_NAME" \ - --argjson inputs "$SAFE_INPUTS" \ - --arg name "$WORKFLOW_NAME" \ + --argjson inputs "$SAFE_INPUTS" \ + --arg name "$WORKFLOW_NAME" \ --arg repo "$GHA_REPOSITORY" \ - --arg run_id "$GITHUB_RUN_ID" \ - --arg version "$WORKFLOW_VERSION" \ - '{ - event_name: $event, - gha_repository: $repo, + --arg run_id "$GITHUB_RUN_ID" \ + --arg version "$WORKFLOW_VERSION" \ + '{ + event_name: $event, + gha_repository: $repo, run_id: $run_id, - workflow_name: $name, - workflow_version: $version + workflow_name: $name, + workflow_version: $version } - + ($inputs | with_entries(.key = ("input_" + .key)))' + + ($inputs | with_entries(.key = ("input_" + .key)))' ) echo "properties=$(echo "$properties" | jq -c .)" >> "$GITHUB_OUTPUT" - name: Send event to PostHog From 62e603040032e1934269b9f42ced64361072cc3f Mon Sep 17 00:00:00 2001 From: Marta Paciorkowska Date: Thu, 30 Apr 2026 09:55:37 +0200 Subject: [PATCH 6/6] adds per job duration metrics to posthog export --- .github/actions/posthog/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/posthog/action.yml b/.github/actions/posthog/action.yml index 2a12bd8..f59c728 100644 --- a/.github/actions/posthog/action.yml +++ b/.github/actions/posthog/action.yml @@ -89,6 +89,7 @@ runs: uses: PostHog/posthog-github-action@58dea254b598fb5d469c0699c98af8288a7f7650 # v1.2.0 continue-on-error: true with: + capture-job-durations: 'true' capture-run-duration: 'true' event: ${{ inputs.workflow_name }} github-token: ${{ github.token }}