Sync markdown files from any git repo working tree to Confluence as a page hierarchy.
Uses mdfluence for markdown → Confluence conversion and upload. All mdfluence CLI options can be passed through gitfluence.
pip install gitfluencegitfluence <repo-path> # auto-detect prod vs int
gitfluence --dry-run <repo-path> # preview, no API calls
gitfluence --space MYSPACE . # override space
gitfluence --prefix "DEV" . # override auto-prefix
gitfluence --beautify-folders . # pass mdfluence options| Variable | Required | Description |
|---|---|---|
CONFLUENCE_HOST |
Yes | Confluence REST API base URL |
CONFLUENCE_TOKEN |
Yes* | PAT for Confluence (token > username/password) |
CONFLUENCE_USERNAME |
No | Username for basic auth |
CONFLUENCE_PASSWORD |
No | Password for basic auth |
CONFLUENCE_INT_HOST |
No | Integration Confluence REST API base URL (defaults to prod) |
CONFLUENCE_INT_TOKEN |
No* | PAT for integration writes |
CONFLUENCE_INT_USERNAME |
No | Username for integration basic auth |
CONFLUENCE_INT_PASSWORD |
No | Password for integration basic auth |
CONFLUENCE_SPACE |
Yes* | Confluence space key |
* On --dry-run, missing host defaults to https://dummy.example.com/api, missing tokens default to dummy and missing space defaults to DRY_RUN. In interactive mode, missing values are prompted.
Auth decision (per target): token > username+password > prompt > dry-run dummy.
macOS / Linux
Copy setenv.example.sh to setenv.sh and fill in your values:
cp setenv.example.sh setenv.shEdit setenv.sh with your Confluence details.
source setenv.shWindows (PowerShell)
Copy setenv.example.ps1 to setenv.ps1 and fill in your values:
Copy-Item setenv.example.ps1 setenv.ps1Edit setenv.ps1 with your Confluence details.
. .\setenv.ps1| Condition | Write target | Prefix |
|---|---|---|
| On default branch, clean, up-to-date with remote | Prod | (none) |
| Feature branch / dirty tree / behind remote | Integration | (none) |
All root-level pages from the repo are created as children of the Confluence space's home page. Subdirectories become nested child pages.
In integration mode (feature branches), the following hierarchy is created:
Space Homepage
└── {repo-name} (integration root)
└── Branch: {branch} (branch grouping page)
└── Page Title (content pages)
└── Sub Page
- Integration root — an empty page named after the repository directory, created under the space homepage. Deleting it removes all integration artifacts.
- Branch page — an empty page titled
Branch: {branch-name}under the integration root. Groups all content pages for that branch. Each branch gets its own grouping page. - Content pages — the actual documentation pages, created as children of the branch page with clean titles (no branch prefix).
Consumer repos can integrate using the composite action:
name: Sync to Confluence
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: geopanther/gitfluence@main
with:
repo_path: "."
extra_args: "--beautify-folders"
confluence_host: ${{ secrets.CONFLUENCE_HOST }}
confluence_token: ${{ secrets.CONFLUENCE_TOKEN }}
confluence_space: ${{ secrets.CONFLUENCE_SPACE }}| Input | Default | Description |
|---|---|---|
repo_path |
"." |
Root directory to sync |
dry_run |
"false" |
Preview mode |
gitfluence_version |
"latest" |
Version to install |
python_version |
"3.12" |
Python version |
extra_args |
"" |
Additional CLI args |
confluence_host |
— | Confluence host URL |
confluence_token |
— | Confluence API token |
confluence_int_host |
"" |
Confluence integration host URL |
confluence_int_token |
"" |
Confluence integration API token |
confluence_space |
— | Confluence space key |
These options are not available in mdfluence:
| Option | Description |
|---|---|
repo_path |
Root directory of the git working tree to sync (positional) |
--space |
Override Confluence space key |
--prefix |
Override auto-detected page title prefix |
-v / --verbose / --debug |
Enable debug logging |
-n (alias for --dry-run) |
Print what would be done without calling API |
--no-preface |
Disable the default preface (DO-NOT-EDIT banner) |
--no-postface |
Disable the default postface (metadata footer) |
--host-int |
Integration Confluence host (env: CONFLUENCE_INT_HOST) |
--token-int |
Integration Confluence token (env: CONFLUENCE_INT_TOKEN) |
--username-int |
Integration Confluence username |
--password-int |
Integration Confluence password |
Note:
--page-idis not supported. Pages are managed by directory hierarchy. Use--parent-idto anchor pages under a specific parent.
gitfluence changes the following mdfluence defaults to be enabled by default:
| Option | mdfluence default | gitfluence default |
|---|---|---|
--strip-top-header |
off | on |
--only-changed |
off | on |
--collapse-single-pages |
off | on |
--skip-empty |
off | on |
--skip-subtrees-wo-markdown |
off | on |
--enable-relative-links |
off | on |
Preface and postface behave differently from mdfluence:
- mdfluence:
--preface-markdown/--postface-markdownaccept an optional value; when given without a value they default to a static "Contents are auto-generated, do not edit." message. No template placeholders. - gitfluence: Both always require a value. All preface/postface sources (CLI string, file, and bundled defaults) support
{branch_name},{repo_origin},{username},{hostname},{timestamp}template placeholders. Bundled defaults are richer (repo origin, branch, author, timestamp).
All remaining mdfluence options are passed through unchanged:
Login: --host / -o, --token, --username / -u, --password / -p, --insecure
Page information: --title, --content-type (choices: page/blogpost), --message, --minor-edit, --strip-top-header, --remove-text-newlines, --replace-all-labels
Parent selection (mutually exclusive): --parent-title / --parent-id / --top-level
Preface (mutually exclusive): --preface-markdown / --preface-file / --no-preface
By default a "DO NOT EDIT" banner with repo origin and branch name is prepended. All preface sources support
{branch_name},{repo_origin},{username},{hostname},{timestamp}placeholders.
Postface (mutually exclusive): --postface-markdown / --postface-file / --no-postface
By default a metadata footer with repo origin, branch, author and timestamp is appended. All postface sources support the same placeholders as preface.
Directory: --collapse-single-pages, --no-gitignore, --skip-subtrees-wo-markdown
Directory titles (mutually exclusive): --beautify-folders / --use-pages-file
Empty dirs (mutually exclusive): --collapse-empty / --skip-empty
Relative links: --enable-relative-links, --ignore-relative-link-errors
Anchors: --convert-anchors / --no-convert-anchors
General: --only-changed, --max-retries
See CONTRIBUTING.md for development setup and guidelines.
MIT