No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-30 13:36:00 +00:00
dtrack-upload feat(dtrack-upload): take the endpoint and api key as inputs 2026-07-30 15:31:14 +02:00
notify-talk fix(notify-talk): Markdown-Umbrueche (Talk soft-break) + Default-Titel = Workflow-Name 2026-06-08 16:21:42 +00:00
sbom-merge feat: fs scans + client/server mode in trivy-sbom; add sbom-merge 2026-07-15 13:50:18 +02:00
trivy-sbom Merge pull request 'fix(trivy-sbom): honor trivy-version when installing trivy' (#2) from fix/trivy-install-tag into main 2026-07-30 10:12:33 +00:00
README.md feat(dtrack-upload): take the endpoint and api key as inputs 2026-07-30 15:31:14 +02:00

forgejo-actions

Shared composite actions for Forgejo / Codeberg CI.

  • notify-talk — post a build/run status into a Nextcloud Talk channel
  • trivy-sbom — CycloneDX SBOM of a container image or filesystem
  • sbom-merge — merge several CycloneDX SBOMs into one
  • dtrack-upload — publish a BOM to Dependency-Track

notify-talk — Nextcloud Talk build/run notification

Posts a Markdown status message into a Nextcloud Talk channel. Use it as a final if: always() step so it reports both success and failure.

- name: Notify Nextcloud Talk
  if: always()
  uses: https://codeberg.org/datatactics/forgejo-actions/notify-talk@main
  with:
    status: ${{ job.status }}
  env:
    TALK_BOT_PASSWORD: ${{ secrets.TALK_BOT_PASSWORD }}
    TALK_ROOM: ${{ vars.TALK_ROOM }}
    TALK_USER: ${{ vars.TALK_USER }}

Inputs

Input Required Default Description
status yes Job result; pass ${{ job.status }} → renders ✅ / ❌ / ⚪ / ❓
title no Build Header text → ### <icon> <title>
message no commit message Body line; falls back to the push commit message when empty

Required environment (provided by the caller)

The action embeds no credentials and no instance config — the calling job supplies everything via env::

Env Suggested source Value
TALK_BOT_PASSWORD repository/org secret Nextcloud app-password of the bot user
TALK_ROOM variable Talk conversation token (the last path segment of the chat URL)
TALK_USER variable Nextcloud bot username

The action fails fast (set -eu) if any of the three is unset. TALK_ROOM accepts either the bare token or a full chat URL (the last path segment is used).

Custom message example

- name: Notify Nextcloud Talk
  if: always()
  uses: https://codeberg.org/datatactics/forgejo-actions/notify-talk@main
  with:
    status: ${{ needs.deploy.result }}
    title: "Deploy"
    message: "Release ${{ github.ref_name }} deployed (${{ needs.deploy.result }})"
  env:
    TALK_BOT_PASSWORD: ${{ secrets.TALK_BOT_PASSWORD }}
    TALK_ROOM: ${{ vars.TALK_ROOM }}
    TALK_USER: ${{ vars.TALK_USER }}

Rendered into Talk:

### ✅ Deploy
**Repo:** <owner>/<repo>  **Branch:** <branch>  **Author:** <actor>
Release v1.4.0 deployed (success)
[View run](<server>/<owner>/<repo>/actions/runs/<n>)

trivy-sbom — CycloneDX SBOM of a container image or filesystem

Scans a container image or a filesystem path with Trivy (standalone or client/server mode), writes a CycloneDX SBOM, optionally strips licenses, and fails the job if the BOM has no components (guards against silently emitting an empty BOM after a transient scanner/registry hiccup). Pairs with sbom-merge and dtrack-upload.

- name: Trivy SBOM
  id: sbom
  uses: https://codeberg.org/datatactics/forgejo-actions/trivy-sbom@main
  with:
    image: docker.io/datatactics/rahla:${{ steps.meta.outputs.version }}
    output: sbom_rahla_${{ steps.meta.outputs.version }}.json
  env: # optional — only for a private registry
    TRIVY_USERNAME: ${{ vars.DOCKERHUB_USER }}
    TRIVY_PASSWORD: ${{ secrets.DOCKERHUB_PASS }}

Filesystem scan against a remote Trivy server:

- uses: https://codeberg.org/datatactics/forgejo-actions/trivy-sbom@main
  with:
    scan-type: fs
    path: webapp/
    server-url: http://trivy.dependencytrack.svc.cluster.local
    output: sbom_webapp.json

Inputs

Input Required Default Description
scan-type no image image (a container image) or fs (a filesystem path)
image when scan-type=image "" Image ref to scan
path no . Filesystem path to scan (used when scan-type=fs)
server-url no "" Trivy client/server URL — when set, scans in client mode (--server)
output no sbom.json SBOM filename
format no cyclonedx Trivy output format
scanners no vuln Trivy scanners
severity no MEDIUM,HIGH,CRITICAL Trivy severities
trivy-version no v0.69.3 Trivy release tag to install (only when trivy is not already on PATH)
strip-licenses no false Delete .licenses from components + metadata.component. Dependency-Track v4 rejected Trivy's license format; v5.0.2 ingests it fine (verified 2026-07) — set true only if you still upload to a DT v4 instance
min-components no 1 Fail if the SBOM has fewer than this many components

Outputs

Output Description
sbom-file Path to the generated SBOM
component-count Number of components in the SBOM

Registry credentials are not action inputs — Trivy reads TRIVY_USERNAME / TRIVY_PASSWORD (and other TRIVY_*) natively, so pass them via the caller's env:.


sbom-merge — merge CycloneDX SBOMs

Merges two or more CycloneDX SBOMs into one with the CycloneDX CLI — e.g. combine a container-image scan with a filesystem scan before uploading a single project to Dependency-Track.

- name: Scan image
  uses: https://codeberg.org/datatactics/forgejo-actions/trivy-sbom@main
  with:
    {
      image: "${{ env.IMAGE_REF }}",
      server-url: "${{ env.TRIVY_SERVER }}",
      output: sbom_image.json,
    }
- name: Scan webapp/
  uses: https://codeberg.org/datatactics/forgejo-actions/trivy-sbom@main
  with:
    {
      scan-type: fs,
      path: webapp/,
      server-url: "${{ env.TRIVY_SERVER }}",
      output: sbom_webapp.json,
    }
- name: Merge
  id: sbom
  uses: https://codeberg.org/datatactics/forgejo-actions/sbom-merge@main
  with:
    input-files: sbom_image.json sbom_webapp.json
    output: sbom_merged.json
- name: Upload
  uses: https://codeberg.org/datatactics/forgejo-actions/dtrack-upload@main
  with:
    {
      bom: "${{ steps.sbom.outputs.sbom-file }}",
      project-name: opsroom,
      project-version: "${{ github.ref_name }}",
    }
  env:
    {
      DTRACK_URL: "${{ vars.DTRACK_URL }}",
      DTRACK_API_KEY: "${{ secrets.DTRACK_API_KEY }}",
    }

Inputs

Input Required Default Description
input-files yes Space-separated list of BOM files to merge
output no sbom_merged.json Merged SBOM filename
output-version no v1_6 CycloneDX output spec version
cyclonedx-version no v0.32.0 CycloneDX CLI release tag to install (only when cyclonedx is not on PATH)

Outputs

Output Description
sbom-file Path to the merged SBOM
component-count Number of components in the merged SBOM

dtrack-upload — publish a BOM to Dependency-Track

POSTs a BOM to a Dependency-Track instance (multipart bom upload, autoCreate), then verifies DT returned a processing token — a rejected upload fails the job instead of going green. Optionally polls until DT finishes processing.

- name: Upload SBOM to Dependency-Track
  uses: https://codeberg.org/datatactics/forgejo-actions/dtrack-upload@main
  with:
    bom: ${{ steps.sbom.outputs.sbom-file }}
    project-name: datatactics/rahla
    project-version: ${{ steps.meta.outputs.version }}
    parent-uuid: cff07b40-c95c-47e9-9367-cb9e8df75dcd
  env:
    DTRACK_URL: ${{ vars.DTRACK_URL }} # the .../api/v1/bom endpoint
    DTRACK_API_KEY: ${{ secrets.DTRACK_API_KEY }}

Inputs

Input Required Default Description
bom yes Path to the BOM file to upload
dtrack-url no "" Dependency-Track BOM endpoint (falls back to DTRACK_URL)
dtrack-base-url no "" Dependency-Track base URL for status polling (derived from the endpoint if empty)
dtrack-api-key no "" Dependency-Track API key (falls back to DTRACK_API_KEY)
project-uuid no "" Dependency-Track project UUID
project-name no "" Dependency-Track projectName (required unless project-uuid is set)
project-version no "" Dependency-Track projectVersion
parent-uuid no "" Dependency-Track parentUUID
auto-create no true Create the project if it does not exist
verify-non-empty no true Refuse to upload a BOM with 0 components
wait-for-processing no false Poll DT until the BOM finishes processing
timeout-seconds no 120 Max wait when wait-for-processing: true

Outputs

Output Description
token Dependency-Track processing token

Required environment (provided by the caller)

DTRACK_URL and DTRACK_API_KEY can be supplied either via the dtrack-url/dtrack-api-key inputs above or as the env vars below.

Env Suggested source Value
DTRACK_URL variable The .../api/v1/bom endpoint
DTRACK_API_KEY secret DT API key with BOM_UPLOAD (+ PROJECT_CREATION_UPLOAD when auto-create: true) permission

Setup (notify-talk)

The credentials and channel config live outside the action:

  • A secret TALK_BOT_PASSWORD — the Nextcloud app-password of the bot user (repository- or organization-level).
  • Variables TALK_ROOM (channel token) and TALK_USER (bot username) — repository-, organization-, or instance-level so they can be shared.

The Nextcloud base URL is configured inside the action.


Conventions

  • Use the full action URL. A bare owner/repo@ref resolves against the default actions registry, not the repo you expect — always reference the full https://codeberg.org/... URL.
  • Pin the ref. @main tracks latest; pin a tag (e.g. @v1) once releases are tagged for reproducible builds.