CI/CD
GitHub Actions
Send CI/CD pipeline logs from GitHub Actions to Parseable. Follow the setup steps and practical guidance for using GitHub Actions in your Parseable…
Collect and analyze GitHub Actions workflow logs in Parseable for CI/CD observability.
Overview
Integrate GitHub Actions with Parseable to:
- Centralize CI/CD Logs - Collect all workflow logs in one place
- Debug Failures - Quickly find and analyze failed jobs
- Track Performance - Monitor build times and trends
- Audit Pipelines - Maintain compliance with log retention
Prerequisites
- GitHub repository with Actions enabled
- Parseable instance accessible from GitHub Actions runners
- GitHub Personal Access Token (for API access)
Method 1: Direct Log Shipping
Send logs directly from your workflow to Parseable.
Workflow Configuration
Add a step to send logs to Parseable:
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
id: build
run: |
echo "Starting build..."
# Your build commands here
npm ci
npm run build
echo "Build completed successfully"
- name: Send logs to Parseable
if: always()
run: |
curl -X POST "${{ secrets.PARSEABLE_URL }}/api/v1/ingest" \
-H "Authorization: Basic ${{ secrets.PARSEABLE_AUTH }}" \
-H "X-P-Stream: github-actions" \
-H "Content-Type: application/json" \
-d '[{
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"repository": "${{ github.repository }}",
"workflow": "${{ github.workflow }}",
"job": "${{ github.job }}",
"run_id": "${{ github.run_id }}",
"run_number": "${{ github.run_number }}",
"actor": "${{ github.actor }}",
"event": "${{ github.event_name }}",
"ref": "${{ github.ref }}",
"sha": "${{ github.sha }}",
"status": "${{ job.status }}",
"conclusion": "${{ steps.build.conclusion }}"
}]'Reusable Action
Create a reusable action for consistent logging:
# .github/actions/log-to-parseable/action.yml
name: Log to Parseable
description: Send workflow logs to Parseable
inputs:
parseable_url:
description: Parseable instance URL
required: true
parseable_auth:
description: Base64 encoded credentials
required: true
dataset:
description: Parseable dataset name
default: github-actions
status:
description: Job status
required: true
message:
description: Log message
default: ''
runs:
using: composite
steps:
- name: Send to Parseable
shell: bash
run: |
curl -X POST "${{ inputs.parseable_url }}/api/v1/ingest" \
-H "Authorization: Basic ${{ inputs.parseable_auth }}" \
-H "X-P-Stream: ${{ inputs.dataset }}" \
-H "Content-Type: application/json" \
-d '[{
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"repository": "${{ github.repository }}",
"workflow": "${{ github.workflow }}",
"job": "${{ github.job }}",
"run_id": "${{ github.run_id }}",
"run_number": "${{ github.run_number }}",
"actor": "${{ github.actor }}",
"event": "${{ github.event_name }}",
"ref": "${{ github.ref }}",
"sha": "${{ github.sha }}",
"status": "${{ inputs.status }}",
"message": "${{ inputs.message }}"
}]'Use the action in your workflow:
- name: Log success
if: success()
uses: ./.github/actions/log-to-parseable
with:
parseable_url: ${{ secrets.PARSEABLE_URL }}
parseable_auth: ${{ secrets.PARSEABLE_AUTH }}
status: success
message: Build completed successfully
- name: Log failure
if: failure()
uses: ./.github/actions/log-to-parseable
with:
parseable_url: ${{ secrets.PARSEABLE_URL }}
parseable_auth: ${{ secrets.PARSEABLE_AUTH }}
status: failure
message: Build failedMethod 2: OpenTelemetry Tracing
Use OpenTelemetry to trace your CI/CD pipelines.
Workflow with OTEL
name: CI Pipeline with Tracing
on:
push:
branches: [main]
env:
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.PARSEABLE_OTEL_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: "Authorization=Basic ${{ secrets.PARSEABLE_AUTH }},X-P-Stream=github-actions-traces"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup OTEL CLI
run: |
curl -L https://github.com/equinix-labs/otel-cli/releases/latest/download/otel-cli-linux-amd64 -o otel-cli
chmod +x otel-cli
sudo mv otel-cli /usr/local/bin/
- name: Build with tracing
run: |
otel-cli exec \
--name "build" \
--service "github-actions" \
--attrs "repository=${{ github.repository }},workflow=${{ github.workflow }}" \
-- npm run buildMethod 3: Webhook Integration
Use GitHub webhooks to capture workflow events.
Webhook Receiver
Create a webhook receiver that forwards events to Parseable:
// github-webhook-to-parseable.js
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.GITHUB_WEBHOOK_SECRET;
const PARSEABLE_URL = process.env.PARSEABLE_URL;
const PARSEABLE_AUTH = process.env.PARSEABLE_AUTH;
function verifySignature(payload, signature) {
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
const digest = 'sha256=' + hmac.update(JSON.stringify(payload)).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}
app.post('/webhook', async (req, res) => {
const signature = req.headers['x-hub-signature-256'];
if (!verifySignature(req.body, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = req.headers['x-github-event'];
const payload = req.body;
// Only process workflow events
if (event === 'workflow_run' || event === 'workflow_job') {
const logEntry = {
timestamp: new Date().toISOString(),
event_type: event,
action: payload.action,
repository: payload.repository?.full_name,
workflow: payload.workflow?.name || payload.workflow_run?.name,
run_id: payload.workflow_run?.id || payload.workflow_job?.run_id,
conclusion: payload.workflow_run?.conclusion || payload.workflow_job?.conclusion,
actor: payload.sender?.login,
url: payload.workflow_run?.html_url || payload.workflow_job?.html_url
};
try {
await axios.post(`${PARSEABLE_URL}/api/v1/ingest`, [logEntry], {
headers: {
'Authorization': `Basic ${PARSEABLE_AUTH}`,
'X-P-Stream': 'github-webhooks',
'Content-Type': 'application/json'
}
});
} catch (error) {
console.error('Error sending to Parseable:', error);
}
}
res.status(200).json({ status: 'received' });
});
app.listen(3000, () => {
console.log('GitHub webhook receiver listening on port 3000');
});Configure GitHub Webhook
- Go to your repository Settings → Webhooks
- Click Add webhook
- Set Payload URL to your webhook receiver
- Set Content type to
application/json - Set Secret to your webhook secret
- Select events: Workflow runs and Workflow jobs
Querying GitHub Actions Logs
Query your CI/CD logs in Parseable:
-- Get recent workflow runs
SELECT timestamp, repository, workflow, status, actor
FROM "github-actions"
ORDER BY timestamp DESC
LIMIT 100
-- Find failed builds
SELECT timestamp, repository, workflow, run_id, message
FROM "github-actions"
WHERE status = 'failure'
ORDER BY timestamp DESC
-- Build success rate by repository
SELECT
repository,
COUNT(*) as total_runs,
SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as successful,
ROUND(SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END)::float / COUNT(*) * 100, 2) as success_rate
FROM "github-actions"
WHERE timestamp > NOW() - INTERVAL '7 days'
GROUP BY repository
ORDER BY success_rate ASCGitHub Secrets Configuration
Add these secrets to your repository:
| Secret | Description |
|---|---|
PARSEABLE_URL | Your Parseable instance URL |
PARSEABLE_AUTH | Base64 encoded username:password |
PARSEABLE_OTEL_ENDPOINT | OTEL endpoint (for tracing) |
Best Practices
- Use Secrets - Never hardcode credentials in workflows
- Log on Failure - Always capture failure information
- Include Context - Add repository, workflow, and run details
- Use Consistent Streams - Organize logs by dataset
- Set Retention - Configure appropriate log retention
Troubleshooting
Logs Not Appearing
- Verify Parseable URL is accessible from GitHub runners
- Check authentication credentials are correct
- Verify the dataset exists or auto-creation is enabled
- Check workflow logs for curl errors
Authentication Failures
- Verify Base64 encoding of credentials
- Check the Parseable user has ingest permissions
- Verify secrets are properly configured
Next Steps
- Set up alerts for failed builds
- Create dashboards for CI/CD metrics
- Configure Jenkins for additional pipelines
Was this page helpful?