Skip to content

Repository files navigation

Continuous integration

This document is the maintainer guide for GitHub Actions, changelog synchronization, notifications, and deployment automation in tenzir/news.

Workflow map

Path Purpose
actions/sync/action.yaml Triggers this repository's synchronization workflow from a source repository.
workflows/sync.yaml Serializes changelog synchronization and sends Discord notifications.
workflows/changelog-x-relay.yaml Relays newly added stable releases to the workflows Worker for X drafting.
workflows/changelog-check.yaml Tests the shared changelog helpers and campaign identities on pull requests.
workflows/rebuild-content.yaml Requests a tenzir/content rebuild after a push to main.
scripts/ Contains deterministic parsing and notification helpers.

Changelog synchronization

Source repositories trigger workflows/sync.yaml. The workflow clones the source repository and synchronizes its changelog into a top-level project directory.

Synchronization architecture

The workflow runs in tenzir/news and uses concurrency: group: "sync" to serialize updates. This avoids concurrent source repositories racing while they pull and push the same target repository.

Each run performs these steps:

  1. Validate that the source exists in the tenzir organization.
  2. Clone the source repository.
  3. Synchronize the primary changelog and configured module changelogs.
  4. Validate campaign identities used by the X publisher.
  5. Commit and push the result to main.
  6. Notify configured destinations about new entries and releases.
  7. Dispatch a rebuild request to tenzir/content.

Top-level changelog config IDs and unreleased entry filename stems must use lowercase kebab-case. Synchronization fails before committing an invalid identity, so publication cannot be the first place an invalid campaign is detected.

The workflow uses these organization or repository settings:

Setting Purpose
vars.TENZIR_GITHUB_APP_ID Identifies the Tenzir GitHub App.
secrets.TENZIR_GITHUB_APP_PRIVATE_KEY Creates installation tokens.

Add a project

Add a workflow like this to the source repository:

name: Sync to News

on:
  push:
    branches: [main]
    paths:
      - "changelog/**"
  workflow_dispatch:

jobs:
  sync:
    name: Trigger news sync
    runs-on: ubuntu-latest

    steps:
      - name: Generate app token
        id: app-token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ vars.TENZIR_GITHUB_APP_ID }}
          private-key: ${{ secrets.TENZIR_GITHUB_APP_PRIVATE_KEY }}
          repositories: news

      - name: Trigger sync workflow
        uses: tenzir/news/.github/actions/sync@main
        with:
          token: ${{ steps.app-token.outputs.token }}

The action derives the following defaults from the source repository:

  • project: The repository name, such as mcp for tenzir/mcp.
  • target: The project name and target directory in tenzir/news.
  • path: changelog.

Override the target when the synchronized directory and source repository have different names:

- uses: tenzir/news/.github/actions/sync@main
  with:
    token: ${{ steps.app-token.outputs.token }}
    target: platform

For an initial import, set skip_notifications: true. Remove it after the first synchronization.

Synchronize module changelogs

For a repository with module changelogs, add each module path to the source workflow trigger and pass the paths through extra_paths:

on:
  push:
    branches: [main]
    paths:
      - "changelog/**"
      - "plugins/*/changelog/**"

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: Generate app token
        id: app-token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ vars.TENZIR_GITHUB_APP_ID }}
          private-key: ${{ secrets.TENZIR_GITHUB_APP_PRIVATE_KEY }}
          repositories: news

      - uses: tenzir/news/.github/actions/sync@main
        with:
          token: ${{ steps.app-token.outputs.token }}
          extra_paths: "plugins/*/changelog"

The extra_paths input accepts space-separated glob patterns. Each matching directory remains under the target project. For example, plugins/foo/changelog synchronizes to PROJECT/plugins/foo/changelog in this repository.

Trigger synchronization directly

You can also dispatch the workflow without the composite action:

gh workflow run sync.yaml \
  --repo tenzir/news \
  --field project=PROJECT \
  --field path=changelog

Notifications

The synchronization workflow can notify Discord and trigger the X drafting workflow. Setting skip_notifications: true adds [skip notifications] to the sync commit, which suppresses both channels.

Discord notifications

Configure these optional repository secrets:

Secret Purpose
DISCORD_CHANGELOG_WEBHOOK Notifies about new unreleased entries.
DISCORD_RELEASE_WEBHOOK Notifies about new top-level releases.

When a secret is absent, the workflow skips the corresponding notification. Notification failures don't fail the synchronization run.

X automation

Every push to main runs workflows/changelog-x-relay.yaml. The workflow collects every added manifest matching PROJECT/changelog/releases/VERSION/manifest.yaml. Automatic posts are limited to the tenzir (Tenzir Node) and platform projects. The relay skips prereleases and refuses pushes containing more than one eligible release. This prevents repository onboarding and historical backfills from publishing stale release bursts; dispatch the intended URL manually after inspecting such a push.

For every eligible release, the relay sends the permanent https://tenzir.com/changelog/ID/VERSION/ URL to the workflows Cloudflare Worker in tenzir/infra (website/workflows/). The Worker fetches the page's public Markdown representation, drafts one Premium-length post when the release contains at least one feature, validates the copy and URL placement, and publishes to @tenzir_company. A Durable Object ledger keyed by the permanent URL prevents duplicate posts. See the Worker's README for the complete publication and recovery design.

This repository needs one Actions secret:

Secret Purpose
WORKFLOWS_NEWS_TOKEN Authenticates the relay against the Worker. Mirrors the workflows-news-token value in the Cloudflare Secrets Store.

Manual dispatches take one canonical stable release URL. They default to a dry run, which drafts and validates the post without accessing the ledger or X. To recover an ambiguous write, inspect @tenzir_company and delete the uncertain post when present. Then manually dispatch the same URL with Draft and validate without publishing cleared and Retry after deleting the uncertain X post enabled.

Website rebuilds

Every push to main runs workflows/rebuild-content.yaml. It sends a news-updated repository dispatch to tenzir/content, which rebuilds tenzir.com/changelog.

The workflow uses the same Tenzir GitHub App settings as synchronization and requests a token scoped to the content repository.

Validate CI changes

Run these checks before committing changes to the notification scripts:

uv run --with-requirements .github/scripts/requirements.txt \
  python .github/scripts/test_changelog.py
uv run --with-requirements .github/scripts/requirements.txt \
  python .github/scripts/changelog.py
uvx ruff check .github/scripts
uvx ruff format --check .github/scripts
git diff --check

About

Product updates: aggregated changelogs from the Tenzir ecosystem.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Sponsor this project

Used by

Contributors