Setting Up GitHub Actions for Antora with Private Repositories
This tutorial walks you through setting up a GitHub Actions workflow to automatically build and deploy an Antora documentation site that pulls content from private repositories.
Overview
When your Antora playbook references private GitHub repositories, the GitHub Actions workflow needs authentication to access them. This guide covers:
-
Creating a Personal Access Token (PAT) with correct permissions
-
Storing the PAT as a GitHub repository secret
-
Configuring the workflow to use the secret with Antora
-
Common gotchas and how to avoid them
|
This guide assumes you have an existing Antora playbook that references private repositories. If you’re new to Antora, see the official Antora documentation first. |
Architecture Overview
The following diagram shows how the CI/CD pipeline authenticates to access private repositories:
@startuml !theme plain skinparam backgroundColor transparent skinparam defaultFontName Segoe UI title GitHub Actions Antora Build Flow actor Developer as dev participant "GitHub\nRepository" as repo participant "GitHub Actions\nRunner" as runner participant "Private Repos\n(content sources)" as private participant "GitHub Pages" as pages dev -> repo : Push to main branch activate repo repo -> runner : Trigger workflow activate runner runner -> runner : Checkout repository runner -> runner : Install pnpm & dependencies runner -> private : Fetch content\n(using GIT_CREDENTIALS) note right: PAT stored in\nGIT_CREDENTIALS env var private --> runner : Return content sources runner -> runner : Build Antora site runner -> pages : Deploy artifact pages --> dev : Site available at\ndocs.foodtrucknerdz.com deactivate runner deactivate repo @enduml
|
If PlantUML diagrams don’t render, the flow is:
|
Prerequisites
Before you begin, ensure you have:
-
A GitHub repository containing your Antora playbook
-
One or more private repositories containing Antora component documentation
-
A GitHub account with permission to create Personal Access Tokens
-
Repository admin access to add secrets
Step 1: Create a Personal Access Token (PAT)
GitHub Actions needs a Personal Access Token to authenticate when accessing private repositories. The default GITHUB_TOKEN provided by Actions only has access to the repository running the workflow, not other private repositories.
Creating a Fine-Grained PAT (Recommended)
Fine-grained PATs offer more control over permissions and are the recommended approach:
-
Navigate to GitHub Personal Access Tokens (fine-grained)
-
Click Generate new token
-
Configure the token:
Setting Value Token name
antora-docs-builder(or similar descriptive name)Expiration
Set based on your security requirements (90 days recommended)
Resource owner
Select your organization (e.g.,
FoodTruckNerds)Repository access
Select All repositories or choose specific repositories that Antora needs to access
-
Under Permissions, expand Repository permissions and set:
Permission Access Level Purpose Contents
Read-only
Required to clone and read repository content
Metadata
Read-only
Required for repository access (automatically selected)
-
Click Generate token
-
Copy the token immediately — you won’t be able to see it again!
|
Security Best Practice: Never commit tokens to your repository. Always use GitHub Secrets. The token you create should have the minimum permissions necessary. Only grant access to the specific repositories your Antora playbook references. |
Alternative: Classic PAT
If fine-grained PATs aren’t available for your organization:
-
Navigate to GitHub Personal Access Tokens (classic)
-
Click Generate new token (classic)
-
Set a descriptive name and expiration
-
Select the
reposcope (full control of private repositories) -
Generate and copy the token
|
Classic PATs with |
Step 2: Add the PAT as a Repository Secret
Store the PAT securely in your repository’s secrets:
-
Navigate to your docs repository on GitHub
-
Go to Settings → Secrets and variables → Actions
-
Click New repository secret
-
Configure the secret:
Field Value Name
FTN_GITHUB_TOKEN(or your preferred name)Secret
Paste your Personal Access Token
-
Click Add secret
|
Naming Convention: Use a clear, descriptive name for your secret that indicates its purpose. Examples:
|
Step 3: Configure the GitHub Actions Workflow
Create or update your workflow file at .github/workflows/build-and-deploy.yml:
name: Build and Deploy Documentation
on:
push:
branches: [main]
workflow_dispatch: (1)
permissions: (2)
contents: read
pages: write
id-token: write
concurrency: (3)
group: "pages"
cancel-in-progress: false
jobs:
build:
strategy:
matrix:
node-version: [20]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4 (4)
- name: Configure Pages
uses: actions/configure-pages@v5 (5)
- name: Install pnpm
uses: pnpm/action-setup@v4 (6)
with:
package_json_file: 'site/package.json'
- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4 (7)
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
cache-dependency-path: 'site/pnpm-lock.yaml'
- name: Install dependencies
working-directory: ./site
run: pnpm install --frozen-lockfile
- name: Build Antora site
working-directory: ./site
env:
GIT_CREDENTIALS: "https://x-access-token:${{ secrets.FTN_GITHUB_TOKEN }}@github.com" (8)
run: pnpm exec antora --stacktrace antora-playbook.yml
- name: Upload artifact
uses: actions/upload-pages-artifact@v3 (9)
with:
path: site/build/site
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4 (10)
| 1 | workflow_dispatch allows manual triggering from the GitHub UI |
| 2 | Required permissions for GitHub Pages deployment |
| 3 | Prevents concurrent deployments that could conflict |
| 4 | actions/checkout — Clones your repository |
| 5 | actions/configure-pages — Configures GitHub Pages |
| 6 | pnpm/action-setup — Installs pnpm package manager |
| 7 | actions/setup-node — Sets up Node.js with caching |
| 8 | Critical: The GIT_CREDENTIALS format Antora expects |
| 9 | actions/upload-pages-artifact — Uploads the built site |
| 10 | actions/deploy-pages — Deploys to GitHub Pages |
Understanding the GIT_CREDENTIALS Format
The GIT_CREDENTIALS environment variable is how Antora authenticates to access private repositories. The format is critical:
https://x-access-token:<YOUR_PAT>@github.com
| Component | Description |
|---|---|
|
Protocol (must be HTTPS for GitHub) |
|
Username — GitHub requires this literal string when using PATs |
|
Your Personal Access Token (from secrets) |
|
The hostname (no trailing path) |
|
Common Mistake: Using your GitHub username instead of Wrong: Correct: GitHub’s authentication system specifically requires |
How Antora Uses GIT_CREDENTIALS
When Antora encounters a private repository URL in your playbook, it:
-
Parses the
GIT_CREDENTIALSenvironment variable -
Matches the hostname (
github.com) to the repository URL -
Injects the credentials into the Git clone operation
-
Clones the repository content
For detailed technical information, see the Antora Private Repository Authentication documentation.
Gotchas and Common Issues
Based on our experience setting up this pipeline, here are the issues you’re most likely to encounter:
Gotcha 1: Using GITHUB_TOKEN Instead of a PAT
The built-in GITHUB_TOKEN secret cannot access other private repositories:
# ❌ WRONG - This will fail for private repos
env:
GIT_CREDENTIALS: "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com"
# ✅ CORRECT - Use a custom PAT stored in secrets
env:
GIT_CREDENTIALS: "https://x-access-token:${{ secrets.FTN_GITHUB_TOKEN }}@github.com"
Why: GITHUB_TOKEN is scoped to only the repository running the workflow. It cannot authenticate to other repositories, even within the same organization.
Gotcha 2: Wrong Username in Credentials
# ❌ WRONG - Using personal username
GIT_CREDENTIALS: "https://myusername:${{ secrets.TOKEN }}@github.com"
# ✅ CORRECT - Using x-access-token
GIT_CREDENTIALS: "https://x-access-token:${{ secrets.TOKEN }}@github.com"
Why: GitHub’s authentication API expects the literal string x-access-token as the username when using Personal Access Tokens.
Gotcha 3: Secret Not Available in Workflow
If your workflow can’t find the secret:
-
Verify the secret name matches exactly (case-sensitive)
-
Check the secret is in the correct repository
-
For organization secrets, ensure your repository has access
-
Fork repositories don’t have access to secrets from the upstream repo
Gotcha 4: PAT Permissions Too Restrictive
If you get authentication errors despite correct credentials:
fatal: could not read Username for 'https://github.com': terminal prompts disabled
Your PAT may lack required permissions. Ensure:
-
Fine-grained PAT: Contents read access on all required repositories
-
Classic PAT:
reposcope selected
Gotcha 5: Path Doesn’t Exist in Repository
[05:20:21.257] FATAL (antora): the start path 'docs' does not exist in https://github.com/FoodTruckNerds/ftn-site-vercel.git (branch: main)
This usually means someone on your team hasn’t pushed their changes. See Troubleshooting Antora Builds for detailed diagnosis steps.
Verifying Your Setup
After committing your workflow:
-
Go to your repository’s Actions tab
-
You should see "Build and Deploy Documentation" workflow
-
Either push a change to
mainor click Run workflow (ifworkflow_dispatchis enabled) -
Monitor the workflow run for any errors
-
Once successful, visit your GitHub Pages URL
Testing Locally First
Before relying on CI/CD, test your playbook locally:
cd site
# Set credentials for local testing
export GIT_CREDENTIALS="https://x-access-token:YOUR_PAT_HERE@github.com"
# Run Antora with stack trace for debugging
pnpm exec antora --stacktrace antora-playbook.yml
|
Never commit your PAT to the repository! When testing locally, set the environment variable temporarily or use a |
References
Action Includes Reference
For detailed information about each GitHub Action used in this workflow, see GitHub Action Includes Reference.
Next Steps
-
Troubleshooting Antora Builds — Diagnose common build errors
-
Action Includes Reference — Understand each action in the workflow
-
Building Docs Locally — Test changes before pushing