confluence-publisher
A one-way publishing pipeline that syncs GitHub Markdown files to Confluence pages.
GitHub is the source of truth. Confluence is the generated presentation layer.
Quick start
- Add a
confluence-manifest.yamlto your repository root. - Copy an example workflow from
examples/workflows/into.github/workflows/. - Add the three required secrets/variables to your repository settings.
- Push or trigger manually — pages appear in Confluence within minutes.
See docs/ONBOARDING.md for a full step-by-step guide.
# confluence-manifest.yaml
defaults:
space_id: ENG
parent_id: '123456'
pages:
docs/architecture.md:
title: Architecture Overview
page_id: '234567' # existing Confluence page ID
docs/runbook.md:
title: Operations Runbook # no page_id — auto-created on first publish
# .github/workflows/publish-to-confluence.yml (minimal)
- uses: pipewell/confluence-publisher@v1
with:
confluence-base-url: ${{ vars.CONFLUENCE_BASE_URL }}
confluence-api-token: ${{ secrets.CONFLUENCE_API_TOKEN }}
confluence-email: ${{ vars.CONFLUENCE_EMAIL }}
Using a fine-grained/scoped Atlassian API token? See docs/ONBOARDING.md — these are rejected on the direct tenant domain and need confluence-cloud-id set instead.
What it does
- Triggers on push to
mainwhen files underdocs/**/*.mdchange - Converts Markdown to Confluence Storage Format using a custom
mistletoerenderer - Manages page identity via a checked-in YAML manifest (page IDs, not titles)
- Auto-creates pages when
page_idis absent; writes the new ID back via a[skip ci]commit - Uploads local images and Mermaid diagrams as page attachments
- Detects edit conflicts (Confluence version ahead of last published) and warns or fails
- Stores the Git commit SHA in the Confluence version message for traceability
- Adds an auto-generated banner to each page (source file, commit SHA, tool attribution) -- configurable via
defaults.attributionin the manifest or--no-attribution - Treats missing images, Mermaid render failures, and upload errors as hard build failures
Failure semantics
All failures exit non-zero. There are no silent failures.
| Failure | Behaviour |
|---|---|
| Markdown conversion error | Build fails; page not published |
| Local image not found on disk | Build fails; page not published (pre-flight check) |
mmdc not installed with Mermaid diagrams present |
Build fails; page not published |
| Mermaid render failure | Build fails; page not published |
| Confluence API error on create or update | Build fails; manifest unchanged |
| Attachment upload failure on a new page | Build fails; placeholder body stays in Confluence; page_id written to manifest; next push retries via the update path (no duplicate page created) |
| Attachment upload failure on an existing page | Build fails; page body not updated; manifest hash unchanged; next push retries |
| Manual edit conflict | Warning logged; page overwritten with GitHub content. --strict-conflicts makes this a build error while still overwriting |
The "Commit manifest state" step uses if: always() so page_id values are committed
to the repo even when the publish step exits non-zero, preserving the retry guarantee
across CI runs.
Supported Markdown
| Feature | Support |
|---|---|
| Headings H1-H6 | Full |
| Bold, italic, inline code | Full |
| Fenced code blocks with language label | Full |
| Tables | Full |
| Ordered and unordered lists (including nested) | Full |
| Blockquotes | Full |
| Horizontal rules | Full |
| External links | Full |
Internal links between managed .md files |
Resolved to Confluence page links |
| Local images | Uploaded as page attachments |
| External images | Rendered inline |
| Mermaid diagrams | Rendered to PNG via mmdc (requires Node in CI) |
| Strikethrough | Not supported -- raises a conversion error |
| Raw HTML | Not supported -- raises a conversion error |
Scope
This tool is intentionally narrow:
- One-way only. It does not sync Confluence edits back to GitHub.
- Not a real-time mirror. It runs on push and on a nightly validation schedule.
- Not a general-purpose renderer. It targets the Confluence Storage Format features needed for engineering documentation.
Known limitations
- Inline comments lose their anchor on republish. Confluence anchors an inline comment by embedding markup directly in the page body around the highlighted text. Every publish replaces the full page body with freshly-converted Markdown, so that anchor markup doesn't survive -- the comment thread is typically detached rather than deleted, but it no longer points at any specific text. Footer/page-level comments are unaffected, since they're stored separately from the body and never touched by this tool. Tracked in #11.
Documents
| Document | Purpose |
|---|---|
| ONBOARDING | Step-by-step guide for connecting a new repository |
| MANIFEST_SPEC | Full manifest format reference |
| ARCHITECTURE | System design and component breakdown |
| DECISIONS | Decision log with rationale |
| BRD | Business requirements and success metrics |
| TRD | Technical requirements and API reference |
| DELIVERY_PLAN | Phased delivery history |
Metadata
Release files for pipewell-confluence-publisher 1.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pipewell_confluence_publisher-1.2.2.tar.gz | 31.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pipewell_confluence_publisher-1.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.3 kB
Release files / pipewell_confluence_publisher-1.2.2.tar.gz
| Download URL | pipewell_confluence_publisher-1.2.2.tar.gz |
|---|---|
| Size | 31.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b667bce47ac1450f9b4d35695c4f6b0c662267394022fe81b6420d1906cab22f
|
|
BLAKE2b-256 checksum How to use checksums |
e9d598a97a7dc00fecd21c54bd5446c003a3ef0df587be1c3ad126d2f097155f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logRelease files / pipewell_confluence_publisher-1.2.2-py3-none-any.whl
| Download URL | pipewell_confluence_publisher-1.2.2-py3-none-any.whl |
|---|---|
| Size | 20.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bbe6e592447e893b79e4b08d85d01c1ee2beef345e1a8e71e2645e66f5254b5a
|
|
BLAKE2b-256 checksum How to use checksums |
6e4b65f141925adf4ed6f56988fab39d7f1678d2b592b94372f2c61d0430d31a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency log