Skip to content

Export Automation

Export Confluence pages to PDF (or DOCX) from a CI/CD pipeline, parse the machine-readable report, and upload the result as a build artifact — no hosted service, no polling, and no data leaving your runner.

Automation is the CLI itself. There is no hosted export job to submit or poll: a single atlcli wiki export … --format pdf --report json call does the whole job on the runner and reports its result as one JSON document on stdout with a deterministic exit code.

  • An Atlassian API token stored as a CI/CD secret.
  • The Confluence base URL and (for Cloud) the account email.
  • View permission on the page(s) to export.

No ~/.atlcli/config.json is needed: the jobs below use profile-free auth via environment variables.

The export command:

  1. Fetches the page (or the whole tree/space) with token auth.
  2. Compiles a tagged, font-embedded PDF in-process (no browser).
  3. Writes the file atomically (nothing partial on failure).
  4. Prints an atlcli.export-report/1 JSON document on stdout and exits with a documented code.
name: Export handbook PDF
on:
workflow_dispatch:
jobs:
export:
runs-on: ubuntu-latest
steps:
- name: Install atlcli
run: curl -fsSL https://atlcli.sh/install.sh | bash
- name: Export to PDF
env:
ATLCLI_BASE_URL: ${{ vars.CONFLUENCE_BASE_URL }}
ATLCLI_EMAIL: ${{ vars.CONFLUENCE_EMAIL }}
ATLCLI_API_TOKEN: ${{ secrets.CONFLUENCE_TOKEN }}
run: |
atlcli wiki export "${{ github.event.inputs.page || '12345678' }}" \
--format pdf --scope tree --label-exclude internal \
--out-dir dist --report json --strict | tee report.json
- name: Summarize
run: |
jq -r '"Exported \(.outputs[0]) — \(.outputDetails[0].pageCount) pages, \(.warnings | length) warnings"' report.json
- name: Fail on an incomplete export
run: |
# `complete` is emitted for --format pdf and --format docx alike, so
# this gate is identical whichever format the job produces.
[ "$(jq -r '.complete' report.json)" = "true" ] || {
echo "Export incomplete:" >&2; jq '.notesByCode' report.json >&2; exit 1;
}
- uses: actions/upload-artifact@v4
with:
name: handbook-pdf
path: dist/*.pdf
export_pdf:
image: ubuntu:24.04
variables:
ATLCLI_BASE_URL: "$CONFLUENCE_BASE_URL"
ATLCLI_EMAIL: "$CONFLUENCE_EMAIL"
# ATLCLI_API_TOKEN is a protected/masked CI variable
before_script:
- apt-get update && apt-get install -y curl jq ca-certificates unzip
- curl -fsSL https://atlcli.sh/install.sh | bash
- export PATH="$HOME/.local/bin:$PATH"
script:
- atlcli wiki export "$PAGE_ID" --format pdf --out-dir dist --report json --strict | tee report.json
- jq -r '.outputs[0]' report.json
artifacts:
paths:
- dist/*.pdf
when: on_success

The report is a stable, versioned projection. Useful jq queries:

Terminal window
# The produced file path(s)
jq -r '.outputs[]' report.json
# Per-artifact metrics (pages, embedded images, skipped assets)
jq '.outputDetails[0]' report.json
# Fail the build on any warning yourself (equivalent to --strict)
test "$(jq '.warnings | length' report.json)" -eq 0
# List every issue with its severity and phase
jq -r '.issues[] | "\(.severity)\t\(.phase)\t\(.code)"' report.json
# Informational notes (timings, label filters, macros that rendered fine) are
# reported but never fail the build — they are not in `.warnings`
jq -r '.issues[] | select(.severity == "info") | .code' report.json
# Gate on ONE condition by code — the same code whichever format you export
jq -e '(.notesByCode["image-missing-alt"] // 0) == 0' report.json

severity is one of error, warning or info, and --strict trips on the first two only — see Note severity and --strict. If you are upgrading from a release where every note was reported as a warning, expect jq '.warnings | length' to drop and a previously-always-2 --engine ts --strict job to start passing.

Exit codes let the pipeline branch without parsing at all: 0 success, 2 warnings under --strict, 3 auth, 4 remote/API (e.g. page not found), 5 compile failure. See the full table.

Symptom Likely cause Fix
Exit 3, auth-error issue Bad or missing ATLCLI_API_TOKEN, or Cloud without ATLCLI_EMAIL Check the secret; Cloud needs the email, Data Center needs --auth-type bearer (no email)
Exit 1, “must use HTTPS” Plain-HTTP --base-url Use HTTPS, or add --allow-http for Data Center
Exit 4, page not found Wrong page id, or no view permission for the token’s user Verify the id and the token account’s permissions
Exit 1, “already exists” Output file exists Use --out-dir for a fresh name, or --force to overwrite
Jira and Confluence are trademarks of Atlassian Corporation Plc. atlcli is not affiliated with, endorsed by, or sponsored by Atlassian.