A composite GitHub Action that runs Conflux CLI commands for bidirectional Markdown-Confluence synchronisation. Pair this action with coroslabs/setup-conflux to install the Conflux binary first, then use this action to execute commands like push, pull, validate, and more.
name: Sync docs to Confluence
on:
push:
branches: [main]
paths: ['docs/**']
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: coroslabs/setup-conflux@v1
with:
github-token: ${{ secrets.CONFLUX_PAT }}
- uses: coroslabs/conflux-action@v1
with:
command: push
confluence-token: ${{ secrets.CONFLUENCE_TOKEN }}| Input | Required | Default | Type | Description |
|---|---|---|---|---|
command |
No | push |
string | CI-relevant: push, pull, rollback, validate, import. Local-only: init, new, preview, version. |
config |
No | '' (auto-discovery) |
string | Path to config file relative to working-directory. If empty, uses built-in discovery order. |
confluence-url |
No | -- | string | Confluence base URL (e.g., https://acme.atlassian.net/wiki). Overrides confluence.base-url in config. |
confluence-token |
Yes | -- | string | Confluence API token. Must be stored as a GitHub Actions secret — never hardcode. |
confluence-email |
No | -- | string | Confluence account email. Overrides confluence.auth.email in config. |
args |
No | '' |
string | Raw CLI arguments appended after the command. Escape hatch for flags not covered by typed inputs (e.g., --dry-run --verbose). Splits on whitespace — quoted arguments containing spaces are not supported. |
working-directory |
No | . |
string | Directory to run Conflux from. Config file path is resolved relative to this directory. |
Conflux is configured via a YAML file (typically .conflux.yaml) in your repository. The action inputs override specific config values, but the config file is where you define spaces, document mappings, and runtime behaviour.
Conflux searches for configuration in this order:
- Explicit flag —
--config <path>(set via theconfigaction input) - Project directory (current working directory):
conflux.yamlconflux.yml.conflux.yaml.conflux.yml.conflux/conflux.yaml.conflux/conflux.yml
- User config —
~/.config/conflux/config.yaml
The first file found wins. In CI, set the config input or place .conflux.yaml in your repository root.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
version |
string | No | 1.0 |
Config schema version. |
confluence |
object | Yes | -- | Connection and authentication settings. |
pages |
list | Yes | -- | Space and document mappings. |
settings |
object | No | See defaults | Runtime behaviour (workers, retries, conflict resolution). |
transform |
object | No | See defaults | Markdown-to-ADF conversion rules. |
validation |
object | No | See defaults | Pre-push validation checks. |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
confluence.base-url |
string | Yes | -- | Confluence instance URL. Must include /wiki for Cloud (e.g., https://acme.atlassian.net/wiki). Supports ${CONFLUENCE_BASE_URL} env var substitution. |
confluence.auth.email |
string | Yes | -- | Account email for API authentication. Supports ${CONFLUENCE_EMAIL}. |
confluence.auth.token |
string | Yes | -- | API token. Must use ${CONFLUENCE_TOKEN} — never hardcode tokens in config files. |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
pages[].space-key |
string | One of space-key / space-id |
-- | Confluence space key (e.g., DEV). |
pages[].space-id |
string | One of space-key / space-id |
-- | Numeric space ID. Use when the space key is ambiguous or has been changed. |
pages[].parent-id |
string | No | -- | Parent page ID. Documents are created as children of this page. |
pages[].documents |
list | Yes | -- | Document mappings for this space. |
documents[].path |
string | Yes | -- | File path or glob pattern (e.g., docs/**/*.md). |
documents[].page-id |
string | No | -- | Existing Confluence page ID to sync to. Required for updating a specific page. |
documents[].title |
string | No | Derived from filename | Page title in Confluence. Defaults to the filename without extension. |
documents[].labels |
list | No | [] |
Confluence labels applied to the page. |
documents[].preserve-hierarchy |
bool | No | false |
Mirror local directory structure as nested Confluence pages. |
documents[].exclude |
list | No | [] |
Glob patterns to exclude from matching (e.g., ["**/draft-*.md"]). |
documents[].settings.preserve-comments |
bool | No | true |
Keep existing page comments when pushing. |
documents[].settings.preserve-children |
bool | No | true |
Keep child pages that don't correspond to local documents. |
| Field | Type | Required | Default | Valid values | Description |
|---|---|---|---|---|---|
settings.workers |
int | No | 4 |
1–32 | Number of parallel workers for API operations. |
settings.rate-limit |
int | No | 5 |
>= 1 | Maximum API requests per second. |
settings.retry.max-attempts |
int | No | 3 |
>= 0 | Number of retry attempts for failed API calls. |
settings.retry.initial-backoff |
duration | No | 1s |
Go duration | Wait time before the first retry. |
settings.retry.max-backoff |
duration | No | 30s |
Go duration | Maximum wait time between retries. |
settings.conflict-resolution.strategy |
string | No | prompt |
prompt, force-local, force-remote, abort |
How to resolve conflicts between local and remote content. In CI, use force-local or abort — prompt requires interactive input. |
settings.git.enabled |
bool | No | true |
-- | Enable git-aware diffing (only push changed files). |
settings.git.base-ref |
string | No | -- | Git ref | Diff against this ref instead of the default branch. |
settings.attachments.enabled |
bool | No | true |
-- | Upload local images as Confluence attachments. |
settings.attachments.max-size |
int64 | No | 52428800 |
Bytes | Maximum attachment size (default 50 MB). |
settings.attachments.allowed-extensions |
list | No | [] |
File extensions | Allowlist of permitted file extensions. Empty means all allowed. |
settings.attachments.excluded-extensions |
list | No | [] |
File extensions | Denylist of blocked file extensions. |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
transform.alerts.enabled |
bool | No | true |
Convert GitHub-style alerts (> [!NOTE]) to Confluence panels. |
transform.alerts.mappings |
map | No | note:info, tip:note, important:warning, warning:warning, caution:error |
Map GitHub alert types to Confluence panel types. |
transform.code.use-macro |
bool | No | true |
Use Confluence code macro for fenced code blocks. |
transform.code.default-language |
string | No | text |
Default language when none is specified on a code block. |
transform.code.line-numbers |
bool | No | false |
Show line numbers in code blocks. |
transform.table.use-confluence-styles |
bool | No | true |
Apply native Confluence table styling. |
transform.table.header-style |
bool | No | true |
Style the first row as a header. |
transform.comments.enabled |
bool | No | true |
Enable comment synchronisation. |
transform.comments.include-on-pull |
bool | No | true |
Include Confluence comments when pulling to Markdown. |
transform.comments.inline-enabled |
bool | No | false |
Enable inline comment annotations in Markdown. |
transform.diagrams.enabled |
bool | No | false |
Render diagram code blocks (Mermaid, D2) as images. |
transform.diagrams.output-format |
string | No | svg |
Output format for rendered diagrams. |
transform.diagrams.mermaid.enabled |
bool | No | true |
Enable Mermaid diagram rendering. |
transform.diagrams.mermaid.theme |
string | No | default |
Mermaid theme. |
transform.diagrams.mermaid.cli-path |
string | No | -- | Path to mmdc binary. Uses PATH if not set. |
transform.diagrams.d2.enabled |
bool | No | true |
Enable D2 diagram rendering. |
transform.diagrams.d2.layout |
string | No | dagre |
Layout engine: dagre or tala. |
transform.diagrams.d2.theme |
int | No | 0 |
D2 theme ID (0–8). |
transform.diagrams.d2.cli-path |
string | No | -- | Path to d2 binary. Uses PATH if not set. |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
validation.check-internal-links |
bool | No | true |
Validate that internal Markdown links resolve to existing files. |
validation.check-images |
bool | No | true |
Validate that image paths point to existing files. |
validation.required-frontmatter |
list | No | [] |
List of frontmatter keys that must be present in every document. |
validation.warn-unsupported |
bool | No | true |
Warn when documents contain Markdown features not supported by Confluence. |
confluence:
base-url: ${CONFLUENCE_BASE_URL}
auth:
email: ${CONFLUENCE_EMAIL}
token: ${CONFLUENCE_TOKEN}
pages:
- space-key: DEV
documents:
- path: docs/**/*.md# Config schema version
version: "1.0"
confluence:
# Must include /wiki for Confluence Cloud
base-url: ${CONFLUENCE_BASE_URL}
auth:
email: ${CONFLUENCE_EMAIL}
# Always use env var substitution — never hardcode tokens
token: ${CONFLUENCE_TOKEN}
pages:
- space-key: DEV
parent-id: "123456789"
documents:
- path: docs/architecture/**/*.md
labels: [architecture, team-platform]
preserve-hierarchy: true
exclude:
- "**/draft-*.md"
- "**/wip-*.md"
settings:
preserve-comments: true
preserve-children: true
- path: docs/runbooks/**/*.md
labels: [runbooks, oncall]
preserve-hierarchy: true
- space-key: PROD
parent-id: "987654321"
documents:
- path: docs/releases/*.md
labels: [releases]
title: "Release Notes"
settings:
workers: 8
rate-limit: 10
retry:
max-attempts: 5
initial-backoff: 2s
max-backoff: 60s
conflict-resolution:
strategy: force-local # Use force-local or abort in CI — prompt requires interactive input
git:
enabled: true
base-ref: origin/main
attachments:
enabled: true
max-size: 52428800
allowed-extensions: [.png, .jpg, .jpeg, .gif, .svg, .webp, .pdf]
excluded-extensions: []
transform:
alerts:
enabled: true
mappings:
note: info
tip: note
important: warning
warning: warning
caution: error
code:
use-macro: true
default-language: text
line-numbers: false
table:
use-confluence-styles: true
header-style: true
comments:
enabled: true
include-on-pull: true
inline-enabled: false
diagrams:
enabled: true
output-format: svg
mermaid:
enabled: true
theme: default
d2:
enabled: true
layout: dagre
theme: 0
validation:
check-internal-links: true
check-images: true
required-frontmatter: [title]
warn-unsupported: trueconfluence:
base-url: ${CONFLUENCE_BASE_URL}
auth:
email: ${CONFLUENCE_EMAIL}
token: ${CONFLUENCE_TOKEN}
pages:
- space-key: DEV
parent-id: "123456789"
documents:
- path: docs/**/*.md
preserve-hierarchy: true
settings:
workers: 4
rate-limit: 5
retry:
max-attempts: 3
initial-backoff: 1s
max-backoff: 30s
# Use force-local in CI — prompt requires interactive input
conflict-resolution:
strategy: force-local
git:
enabled: true
# Diff against the merge base to push only changed files
base-ref: origin/main
attachments:
enabled: true
validation:
check-internal-links: true
check-images: true
warn-unsupported: trueTriggered when Markdown files under docs/ change on the default branch:
name: Sync docs to Confluence
on:
push:
branches: [main]
paths:
- 'docs/**'
- '.conflux.yaml'
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: coroslabs/setup-conflux@v1
with:
github-token: ${{ secrets.CONFLUX_PAT }}
- uses: coroslabs/conflux-action@v1
with:
command: push
confluence-url: ${{ vars.CONFLUENCE_URL }}
confluence-token: ${{ secrets.CONFLUENCE_TOKEN }}
confluence-email: ${{ vars.CONFLUENCE_EMAIL }}Use workflow_dispatch with a choice input for on-demand synchronisation:
name: Conflux manual sync
on:
workflow_dispatch:
inputs:
command:
description: 'Conflux command to run'
type: choice
required: true
default: push
options:
- push
- pull
- validate
- rollback
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: coroslabs/setup-conflux@v1
with:
github-token: ${{ secrets.CONFLUX_PAT }}
- uses: coroslabs/conflux-action@v1
with:
command: ${{ inputs.command }}
confluence-token: ${{ secrets.CONFLUENCE_TOKEN }}Pass arbitrary CLI flags via the args input:
- uses: coroslabs/conflux-action@v1
with:
command: push
confluence-token: ${{ secrets.CONFLUENCE_TOKEN }}
args: '--dry-run --verbose'| Token | Scope | Purpose |
|---|---|---|
GitHub fine-grained PAT (CONFLUX_PAT) |
contents:read on coroslabs/conflux |
Download Conflux binary from GitHub Releases (used by setup-conflux). |
Confluence API token (CONFLUENCE_TOKEN) |
Full API access | Read and write Confluence pages, attachments, and comments. Generate at id.atlassian.com/manage-profile/security/api-tokens. |
| Error | Cause | Resolution |
|---|---|---|
conflux: command not found |
Missing setup step | Add coroslabs/setup-conflux@v1 before this action. |
401 Unauthorized (GitHub) |
Invalid or expired PAT | Regenerate the PAT with contents:read scope on coroslabs/conflux. |
401 Unauthorized (Confluence) |
Invalid or expired API token | Regenerate at id.atlassian.com. |
config file not found |
No configuration file | Create .conflux.yaml in your repo root or set the config input. |
checksum mismatch |
Corrupt binary download | Re-run the workflow. If persistent, check the release assets. |
strategy: prompt in CI |
Interactive mode in non-interactive environment | Set settings.conflict-resolution.strategy to force-local or abort in your config file. |
Pin this action to a specific version for reproducible builds:
- Tag (
@v1) — convenient, follows semver. Recommended for most users. - SHA (
@<commit-sha>) — maximum reproducibility. Recommended for security-sensitive environments.
See GitHub's documentation on action security hardening for more guidance.