diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 20f61e23..00000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,82 +0,0 @@
-# CircleCI 2.0 configuration file. See .
-version: 2
-jobs:
- lint:
- docker:
- - image: node:lts
- steps:
- - checkout
-
- - run:
- name: Lint Markdown files
- command: make lint
-
- build:
- docker:
- - image: python:3.11
- steps:
- - checkout
-
- - restore_cache:
- key: dependency-cache-{{ checksum "requirements.txt" }}
-
- - run:
- name: Create a virtualenv
- command: |
- mkdir -p /tmp/venv/openfisca_doc
- python -m venv /tmp/venv/openfisca_doc
- echo "source /tmp/venv/openfisca_doc/bin/activate" >> $BASH_ENV
-
- - run:
- name: Install doc dependencies
- command: make install
-
- - save_cache:
- key: dependency-cache-{{ checksum "requirements.txt" }}
- paths:
- - /tmp/venv/openfisca_doc
-
- - run:
- name: Test doc
- command: make test-build
-
- - run:
- name: Build doc
- command: make html
-
- - run:
- name: Serve doc
- command: make prod
- background: true
-
- - run:
- name: Check for internal dead links
- command: wget --retry-connrefused --waitretry=1 --spider --recursive --page-requisites http://localhost:8000
-
- - persist_to_workspace:
- root: .
- paths:
- - build
-
- deploy:
- docker:
- - image: python:3.11
- steps:
- - checkout
- - attach_workspace:
- at: .
- - run:
- name: Publish openfisca.org/doc
- command: ./publish.sh
-workflows:
- version: 2
- build:
- jobs:
- - lint
- - build
- - deploy:
- requires:
- - build
- filters:
- branches:
- only: master
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 00000000..80c8ac66
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,39 @@
+name: Build
+
+on:
+ workflow_call:
+
+jobs:
+ build-and-cache:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: 3.11
+
+ - name: Cache dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ env.pythonLocation }}
+ key: build-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ github.sha }} # Cache the entire build Python environment
+ restore-keys: |
+ build-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}
+ build-${{ env.pythonLocation }}-
+
+ - name: Install dependencies
+ run: make install
+
+ - name: Check syntax
+ run: make test-build
+
+ - name: Cache built files
+ uses: actions/cache@v4
+ with:
+ path: build/html
+ key: build-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ github.sha }}
+
+ - name: Build doc
+ run: make html
diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
new file mode 100644
index 00000000..5eb99a8a
--- /dev/null
+++ b/.github/workflows/deploy.yaml
@@ -0,0 +1,42 @@
+name: Deploy
+
+on:
+ workflow_dispatch: # triggered by Core to rebuild the documentation when code comments change
+ push:
+ branches: [ master ]
+
+jobs:
+ validate:
+ uses: ./.github/workflows/validate.yaml
+
+ deploy:
+ runs-on: ubuntu-latest
+
+ needs: [ validate ] # also depends on `build-and-cache` job for cached build, not repeated to avoid building twice
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.11
+
+ - name: Restore built files
+ uses: actions/cache@v4
+ with:
+ path: build/html
+ key: build-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ github.sha }}
+ fail-on-cache-miss: true # depend entirely on the build step
+
+ - name: Deploy built directory to openfisca.org website
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ deploy_key: ${{ secrets.OPENFISCADOTORG_DEPLOY_KEY }}
+ publish_dir: build/html
+ external_repository: openfisca/openfisca.org
+ destination_dir: doc
+ publish_branch: gh-pages
+ user_email: bot@openfisca.org
+ user_name: OpenFisca Bot
+ commit_message: Publish latest changes from # will be suffixed with "openfisca/openfisca-doc@"
diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml
new file mode 100644
index 00000000..0e33d4a2
--- /dev/null
+++ b/.github/workflows/validate.yaml
@@ -0,0 +1,47 @@
+name: Validate
+
+on:
+ pull_request:
+ workflow_call:
+
+jobs:
+ build:
+ uses: ./.github/workflows/build.yaml
+
+ check-links:
+ runs-on: ubuntu-latest
+ needs: [ build ]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: 3.11
+
+ - name: Restore built files
+ uses: actions/cache@v4
+ with:
+ path: build/html
+ key: build-${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ github.sha }}
+ fail-on-cache-miss: true # depend entirely on the build step
+
+ - name: Serve doc
+ run: make prod &
+
+ - name: Check for internal dead links
+ run: wget --retry-connrefused --waitretry=1 --spider --recursive --page-requisites http://localhost:8000
+
+ lint:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Lint Markdown files
+ run: make lint
diff --git a/Makefile b/Makefile
index 5ecd2adc..9e1e982a 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ install:
test: lint test-build
test-build:
- @${MAKE} dummy SPHINXOPTS="-q -W"
+ @${MAKE} dummy SPHINXOPTS="--quiet --fail-on-warning"
lint: # requires Node and NPM to be installed
@npx --yes markdownlint-cli "**/*.md"
diff --git a/README.md b/README.md
index 324a7128..91cb6ecc 100644
--- a/README.md
+++ b/README.md
@@ -101,3 +101,9 @@ That's it! 🙌
## Using icons
You can use icons by choosing one from [Lucide](https://lucide.dev) and adapting the code `` with the relevant icon name.
+
+## Deploy
+
+The documentation is built as a static website on GitHub Actions with Sphinx. The built files are committed and pushed to the `doc` folder of the GitHub Pages-published branch of the `openfisca.org` repository.
+
+OpenFisca-Core triggers a deployment on the Doc repository whenever a new Core version is deployed, to ensure that the Python and Web API auto-generated documentations are up to date. This is done with [`workflow_dispatch`](https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event--fine-grained-access-tokens) using a personal access token of @openfisca-bot. This personal access token has a maximum lifetime of one year, and will thus need to be updated every year.
diff --git a/publish.sh b/publish.sh
deleted file mode 100755
index 224e1cc2..00000000
--- a/publish.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-set -ex
-
-git clone --branch gh-pages https://github.com/openfisca/openfisca.org.git
-mv build/html doc
-rm --recursive --force openfisca.org/doc
-mv doc openfisca.org/doc
-cd openfisca.org
-git fetch # Make sure we are up to date with git remote branches
-git add --all
-git config --global user.name "OpenFisca-Bot"
-git config --global user.email "bot@openfisca.org"
-git diff-index --quiet HEAD || git commit --message="[skip ci] Update doc"
-git push https://github.com/openfisca/openfisca.org.git gh-pages
-if git status --untracked-files=no ; then
- echo "There was an issue pushing to openfisca.org"
-fi
-rm --recursive --force $(git ls-files | grep --invert-match doc) # remove all files in the branch except the doc file.
-
-# keep the context while changing branch
-git checkout --detach
-git reset --soft origin/doc-html
-git checkout doc-html
-git add --all
-git diff-index --quiet HEAD || git commit --message="[skip ci] Update doc"
-git push