Skip to content

GitHub Actions

Unentropy provides two GitHub Actions for automated metrics tracking and quality enforcement.

ActionPurposeContext
track-metricsCollect and store metricsMain branch pushes
quality-gateEvaluate PR against thresholdsPull requests

Collects metrics, updates the database, and generates reports. Runs on main branch to build historical data.

name: Track Metrics
on:
push:
branches: [main]
jobs:
metrics:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: unentropy/track-metrics-action@v1

Type: string
Default: sqlite-local
Values: sqlite-local, sqlite-artifact, sqlite-s3

Storage backend for the metrics database.

- uses: unentropy/track-metrics-action@v1
with:
storage-type: sqlite-artifact

Required when storage-type is sqlite-s3:

Type: string
Required: Yes (for S3)

S3-compatible endpoint URL.

s3-endpoint: https://s3.amazonaws.com
s3-endpoint: https://<account-id>.r2.cloudflarestorage.com

Type: string
Required: Yes (for S3)

S3 bucket name.

s3-bucket: my-metrics-bucket

Type: string
Required: Yes (for S3)

S3 region.

s3-region: us-east-1
s3-region: auto # Cloudflare R2

Type: string
Required: Yes (for S3)

S3 access key ID from GitHub Secrets.

s3-access-key-id: ${{ secrets.S3_ACCESS_KEY_ID }}

Type: string
Required: Yes (for S3)

S3 secret access key from GitHub Secrets.

s3-secret-access-key: ${{ secrets.S3_SECRET_ACCESS_KEY }}

Used when storage-type is sqlite-artifact:

Type: string
Default: unentropy-metrics

Name of the database artifact.

artifact-name: my-project-metrics

Type: string
Default: ${{ github.ref_name }}

Branch to search for previous artifacts.

artifact-branch-filter: main

Type: string
Default: unentropy.json

Path to configuration file.

config-file: custom-config.json

Type: string
Default: unentropy-metrics.db

Database file key in storage.

database-key: production/metrics.db

Type: string
Default: index.html

Generated report filename.

report-name: metrics-report.html

Type: boolean

Whether workflow completed successfully.

- name: Check success
if: steps.metrics.outputs.success == 'true'
run: echo "Metrics collected"

Type: string

Storage backend type used.

Type: string

Database storage location identifier.

Type: string

Database file size in bytes.

Type: number

Number of metrics collected.

Type: number

Total workflow duration in milliseconds.

Type: string
Available: Artifact storage only

Workflow run ID where previous artifact was found.

Type: string
Available: Artifact storage only

ID of uploaded database artifact.

name: Track Metrics
on:
push:
branches: [main]
jobs:
metrics:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
steps:
- uses: actions/checkout@v4
- name: Run tests with coverage
run: bun test --coverage
- name: Track metrics
uses: unentropy/track-metrics-action@v1
with:
storage-type: sqlite-artifact
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: metrics-report
path: index.html
name: Track Metrics
on:
push:
branches: [main]
jobs:
metrics:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests with coverage
run: bun test --coverage
- name: Track metrics
uses: unentropy/track-metrics-action@v1
with:
storage-type: sqlite-s3
s3-endpoint: ${{ secrets.S3_ENDPOINT }}
s3-bucket: ${{ secrets.S3_BUCKET }}
s3-region: ${{ secrets.S3_REGION }}
s3-access-key-id: ${{ secrets.S3_ACCESS_KEY_ID }}
s3-secret-access-key: ${{ secrets.S3_SECRET_ACCESS_KEY }}
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: metrics-report
path: index.html

Evaluates PR metrics against baseline thresholds and posts results. Runs on pull requests.

name: Quality Gate
on:
pull_request:
jobs:
gate:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: unentropy/quality-gate-action@v1

Type: string
Default: sqlite-s3
Values: sqlite-local, sqlite-artifact, sqlite-s3

Storage backend where baseline database is stored. Must match the storage used by track-metrics.

- uses: unentropy/quality-gate-action@v1
with:
storage-type: sqlite-s3

Same as track-metrics action. Required when storage-type is sqlite-s3.

See track-metrics S3 inputs.

Type: string
Default: unentropy.json

Path to configuration file.

config-file: custom-config.json

Type: string
Default: unentropy.db

Database file key in storage. Must match the key used by track-metrics.

database-key: production/metrics.db

Type: string
Values: off, soft, hard

Override quality gate mode from config file:

  • off: Skip evaluation
  • soft: Evaluate and comment, don’t fail build
  • hard: Fail build on threshold violations
quality-gate-mode: soft

Type: boolean
Default: true

Post/update PR comment with results.

enable-pr-comment: true

Type: string
Default: <!-- unentropy-quality-gate -->

HTML marker to identify quality gate comment.

pr-comment-marker: <!-- my-custom-marker -->

Type: number
Default: 30

Maximum metrics to show in PR comment.

max-pr-comment-metrics: 50

Type: string
Values: pass, fail, unknown

Overall gate status.

- name: Check gate
if: steps.gate.outputs.quality-gate-status == 'fail'
run: echo "Quality gate failed"

Type: string

Gate mode used.

Type: string

Comma-separated list of failing metric names.

- name: Log failures
if: steps.gate.outputs.quality-gate-status == 'fail'
run: echo "Failed: ${{ steps.gate.outputs.quality-gate-failing-metrics }}"

Type: string

URL of the PR comment (if created).

Type: number

Number of metrics collected from PR.

Type: number

Number of baseline builds used for comparison.

Type: string

Reference branch used for baseline.

name: Quality Gate
on:
pull_request:
jobs:
gate:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Run tests with coverage
run: bun test --coverage
- name: Quality gate
uses: unentropy/quality-gate-action@v1
with:
storage-type: sqlite-s3
quality-gate-mode: soft
s3-endpoint: ${{ secrets.S3_ENDPOINT }}
s3-bucket: ${{ secrets.S3_BUCKET }}
s3-region: ${{ secrets.S3_REGION }}
s3-access-key-id: ${{ secrets.S3_ACCESS_KEY_ID }}
s3-secret-access-key: ${{ secrets.S3_SECRET_ACCESS_KEY }}
name: Quality Gate
on:
pull_request:
jobs:
gate:
runs-on: ubuntu-latest
permissions:
pull-requests: write
actions: read
steps:
- uses: actions/checkout@v4
- name: Run tests with coverage
run: bun test --coverage
- name: Quality gate
uses: unentropy/quality-gate-action@v1
with:
storage-type: sqlite-artifact
quality-gate-mode: hard

Both actions need:

permissions:
actions: read # Download artifacts
contents: read # Checkout repository

Quality gate also needs:

permissions:
pull-requests: write # Post PR comments
permissions:
contents: read # Checkout repository

Quality gate also needs:

permissions:
pull-requests: write # Post PR comments

S3 access is controlled via credentials, not GitHub permissions.

Main branch + PR workflows together:

.github/workflows/metrics.yml
name: Metrics
on:
push:
branches: [main]
jobs:
track-metrics:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: bun test --coverage
- uses: unentropy/track-metrics-action@v1
with:
storage-type: sqlite-s3
s3-endpoint: ${{ secrets.S3_ENDPOINT }}
s3-bucket: ${{ secrets.S3_BUCKET }}
s3-region: ${{ secrets.S3_REGION }}
s3-access-key-id: ${{ secrets.S3_ACCESS_KEY_ID }}
s3-secret-access-key: ${{ secrets.S3_SECRET_ACCESS_KEY }}
.github/workflows/quality-gate.yml
name: Quality Gate
on:
pull_request:
jobs:
quality-gate:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Run tests
run: bun test --coverage
- uses: unentropy/quality-gate-action@v1
with:
storage-type: sqlite-s3
quality-gate-mode: soft
s3-endpoint: ${{ secrets.S3_ENDPOINT }}
s3-bucket: ${{ secrets.S3_BUCKET }}
s3-region: ${{ secrets.S3_REGION }}
s3-access-key-id: ${{ secrets.S3_ACCESS_KEY_ID }}
s3-secret-access-key: ${{ secrets.S3_SECRET_ACCESS_KEY }}
  • All S3 credentials must come from GitHub Secrets
  • Credentials are never logged or exposed in error messages
  • GITHUB_TOKEN is auto-detected for artifact operations
  • PR comments contain only metric values, no sensitive data