Export Automation
Export Automation
Section titled “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 — with no separate hosted renderer or polling service. Page and attachment data travels between Confluence and 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 jsoncall does the whole job on the runner and reports its result as one JSON document on stdout with a deterministic exit code.
On this page
Section titled “On this page”- Prerequisites
- How it works
- GitHub Actions
- GitLab CI
- Parsing the report
- Troubleshooting
- Related topics
Prerequisites
Section titled “Prerequisites”- 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.
- Optional: a reviewed
.wiki-pdf-templatepack stored as a protected build input or repository artifact.
No ~/.atlcli/config.json is needed: the jobs below use
profile-free auth via environment variables.
How it works
Section titled “How it works”The export command:
- Fetches the page (or the whole tree/space) with token auth.
- Compiles a tagged, font-embedded PDF in-process (no browser).
- Writes the file atomically (nothing partial on failure).
- Prints an
atlcli.export-report/1JSON document on stdout and exits with a documented code.
When --template <pack> is present, atlcli validates and stores the pack
locally before the first Confluence request. The durable export job pins its
content hash rather than the caller’s file path.
GitHub Actions
Section titled “GitHub Actions”name: Export handbook PDFon: 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 \ --template ./templates/brand.wiki-pdf-template \ --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/*.pdfGitLab CI
Section titled “GitLab CI”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_successParsing the report
Section titled “Parsing the report”The report is a stable, versioned projection. Useful jq queries:
# 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 phasejq -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 exportjq -e '(.notesByCode["image-missing-alt"] // 0) == 0' report.jsonseverity 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.
Troubleshooting
Section titled “Troubleshooting”| 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 |
Exit 1, “PDF template validation failed” |
Missing, modified, or incompatible pack | Rebuild it with atlcli pdf-template build; do not patch archive members in CI |
Related topics
Section titled “Related topics”- DOCX and PDF Export — full command reference
- Create a PDF template from Word — build the reviewed pack used by the example
- PDF Template Authoring CLI — machine-mode authoring and schemas
- CI/CD Documentation — publishing docs into Confluence from CI
- Authentication — tokens and profiles