Skip to content
Draft
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
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ Defaults to `https://us.i.posthog.com`

### `event`

**Required** The event name to send to PostHog.

Defaults to `event-from-github-actions`
The event name to send to PostHog (e.g., `"ci-metrics"`).

### `properties`

Expand Down Expand Up @@ -78,6 +76,14 @@ Job name to check for workflow status. Captures that job's conclusion (`success`

Note: Your metrics job must `needs` the target job and use `if: always()` to run even on failure.

### `annotation`

Create a PostHog annotation with the provided text (e.g., `"Deployed to production"`).

### `annotation-scope`

Annotation scope: `'project'` (default) or `'organization'`.

## Automatically Included Properties

The following GitHub context properties are automatically added to every event:
Expand Down Expand Up @@ -185,6 +191,15 @@ This enables:
github-token: ${{ secrets.GITHUB_TOKEN }}
```

### Create annotation on deploy

```yaml
- uses: PostHog/posthog-github-action@v1
with:
posthog-token: ${{ secrets.POSTHOG_API_KEY }}
annotation: "Deployed to production"
```

### Complete Workflow Example

```yaml
Expand Down
12 changes: 9 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ inputs:
required: false
default: "https://us.i.posthog.com"
event:
description: 'The event name e.g. "GitHubActionCompleted"'
required: true
default: "event-from-github-actions"
description: 'The event name to capture (e.g., "ci-metrics")'
required: false
properties:
description: "Properties to add to the event - as a JSON string. Must be possible to `JSON.parse(properties)`"
required: false
Expand All @@ -36,6 +35,13 @@ inputs:
status-job:
description: "Job name to check for workflow status (e.g., 'Django Tests Pass'). Captures that job's conclusion."
required: false
annotation:
description: "Create a PostHog annotation with the provided text (e.g., 'Deployed to production')"
required: false
annotation-scope:
description: "Annotation scope: 'project' (default) or 'organization'"
required: false
default: "project"
runs:
using: "node20"
main: "dist/index.js"
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

40 changes: 38 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@ const { PostHog } = require('posthog-node')
const core = require('@actions/core')
const github = require('@actions/github')

async function createAnnotation(apiHost, token, content, scope) {
const response = await fetch(`${apiHost}/api/projects/@current/annotations/`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
content,
scope: scope === 'organization' ? 'organization' : 'project',
date_marker: new Date().toISOString(),
}),
})

if (!response.ok) {
const error = await response.text()
throw new Error(`Failed to create annotation: ${response.status} ${error}`)
}

return response.json()
}

async function run() {
try {
const posthogToken = core.getInput('posthog-token')
Expand All @@ -13,10 +35,22 @@ async function run() {
const githubToken = core.getInput('github-token')
const runner = core.getInput('runner')
const statusJob = core.getInput('status-job')
const annotation = core.getInput('annotation')
const annotationScope = core.getInput('annotation-scope')

const properties = propertiesInput ? JSON.parse(propertiesInput) : {}
if (!eventName && !annotation) {
throw new Error('At least one of event or annotation is required')
}

// Create annotation (can be standalone or combined with event capture)
if (annotation) {
await createAnnotation(posthogAPIHost, posthogToken, annotation, annotationScope)
core.info(`Created annotation: ${annotation}`)
}

// Create octokit instance if any GitHub API feature is enabled
if (!eventName) return

// Event capture requires GitHub API for enrichment features
let octokit = null
if (captureRunDuration || captureJobDurations || statusJob) {
if (!githubToken) {
Expand All @@ -25,6 +59,8 @@ async function run() {
octokit = github.getOctokit(githubToken)
}

const properties = propertiesInput ? JSON.parse(propertiesInput) : {}

// Workflow duration (from GitHub API)
if (captureRunDuration) {
const { data: workflowRun } = await octokit.rest.actions.getWorkflowRun({
Expand Down