Sep 17, 2024
GitBook & Moderne: CI/CD for your docs
Sep 17, 2024
GitBook & Moderne: CI/CD for your docs
Automatically Generate Content on GitBook with GitHub Actions
Tutorials & tips
Tutorials & tips
Tutorials & tips
14 Jan 2022
Author
Author
Author
![](https://framerusercontent.com/images/ObSO21WfX7dsqfvUprsTf5P4YdQ.png)
![](https://framerusercontent.com/images/ObSO21WfX7dsqfvUprsTf5P4YdQ.png)
![](https://framerusercontent.com/images/ObSO21WfX7dsqfvUprsTf5P4YdQ.png)
Sometimes, it can be useful to automatically generate some of your documentation. Whether you're generating Markdown based on Docstrings, or you're adding a footer with a link to a feedback form at the bottom of every page, you can achieve this effect using GitBook, with help from the GitHub Sync feature.
For the purposes of this example, let's consider a company, CoolProductIncorporated who need to document their cool developer focused product. The team decides that at the end of each page of documentation, they want to add a footer that links to a video demo of their product. How might they achieve that?
We have a demo repository that implements the steps in this blog post. Check it out to see it in action!
Setup and prep
Create a GitBook space in the appropriate org
Create a new empty GitHub repo to sync content to
Set up sync with GitHub repo, making sure to choose initial import from GitBook
Add a
.gitbook.yaml
file in the root to tell GitBook we're storing our documentation in the docs folder. It should contain just the lineroot: ./docs/
. Create a folderdocs
in the root of your repository.
At this stage, the building blocks are laid to start making modifications to files using scripts.
Scripting the footer
At this point, it's time to start thinking about how the generated content will be generated. This will vary greatly depending on your use case. If you're generating content from docstrings, you may be able to find a program that outputs markdown in the format you're looking for. For other types of content generation, you might need to write a script yourself. For the purposes of this step, you need to run a program (in a format that can be run on GitHub Actions) that modifies your documentation and outputs Markdown.
Here's an example program written in Javascript, that adds a footer to every documentation page that doesn't already have it.
scripts/append-footer.js
var glob = require("glob");
var fsPromises = require("fs/promises");
var path = require("path");
const { spawn } = require("child_process");
// read environmental variables
const ghActor = process.env["GITHUB_ACTOR"];
const isGitHubActions = Boolean(process.env["GITHUB_ACTIONS"]);
const GITBOOK_ACTOR = "gitbook-bot";
console.log(`GitHub actions ${isGitHubActions}`);
console.log(`GitHub actor ${ghActor}`);
if (isGitHubActions) {
// If we're in GitHub Actions, only run this for pushes from GitBook
if (ghActor !== GITBOOK_ACTOR) {
process.exit(0);
}
}
// Load the footer from the footer.md file
const footer = require("fs").readFileSync(path.join(__dirname, "./footer.md"));
// find each markdown document in the docs directory
glob(path.join(__dirname, "../docs/**/*.md"), async (error, fileNames) => {
console.log(fileNames);
// for each document
const editPromises = fileNames.map(async (fileName) => {
// load the contents of the document
const fileContents = await (await fsPromises.readFile(fileName)).toString();
// if the document doesn't end with the footer text
if (!fileContents.endsWith(footer)) {
// add the footer text to the end of the document
const newFileContents = fileContents + footer;
await fsPromises.writeFile(fileName, newFileContents);
}
});
await Promise.all(editPromises);
spawn("git", ["add", "."]);
});
This example code depends on the glob npm package, so you'll need to add it to your package.json. If you don't already have a package.json, you can create one in your repository root using npm init -y
, and install glob with npm install --save glob
. You can store both append-footer.js
and footer.md
in the scripts
folder in your repository.
Remember - you don't have to use Javascript to modify or generate your documentation! This is just an example. Feel free to use any program that can run in GitHub actions.
Automating generation with GitHub Actions
Now that we have our script, we need to run it automatically each time our content is changed. To do that, we'll configure a GitHub Actions workflow. In our repository, we'll create a directory at .github/workflows
, to store our workflows. In there, we'll create a file called append-footer.yml
.
name: append-footer
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
with:
node-version: v16.x
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: npm install
run: npm ci
- name: Enforce docs footer
run: node ./scripts/append-footer.js
- name: Git Prep
run: |
git config --local user.email "footer-bot@coolproductinc.technology"
git config --local user.name "footer-bot[bot]"
git diff
git diff-index HEAD
git diff-index --quiet HEAD || git commit -am "docs(footer): ensure footer exists on all docs pages"
- name: Git Push
run: "git push origin $(git branch --show-current) || true"
This workflow does a lot - lets step through it.
We first name the workflow and configure it to run each time there's a push to the repository's main branch. The script itself ensures that we only run when GitBook pushes to main - no need to configure that here.
Using the ubuntu-latest base image, we use the setup-node action to ensure we're using the correct version of node.js, check out the contents of the repository, and install dependencies.
The next few steps are more interesting - first we run the script above, which will append the footer to all documentation pages that don't already have it, and stages the results in git.
At this point, we configure git. We set up a dummy email and name to be attached to the commit, and only if there was staged changes, commits the code. In the case that each documentation file already has the correct footer, there are no changes to commit, so we ignore them.
Finally, we push the new commit to GitHub. GitBook will read the changes and update its copy of the documentation.
CoolProductIncorporated no longer have to think about footers - they can trust that the robots will handle it, and focus on writing the very best documentation they can for their Cool Product!
Thanks!
Thanks for reading. We hope this article was helpful for you. If you have any questions, please feel free to get in touch with us.
Sometimes, it can be useful to automatically generate some of your documentation. Whether you're generating Markdown based on Docstrings, or you're adding a footer with a link to a feedback form at the bottom of every page, you can achieve this effect using GitBook, with help from the GitHub Sync feature.
For the purposes of this example, let's consider a company, CoolProductIncorporated who need to document their cool developer focused product. The team decides that at the end of each page of documentation, they want to add a footer that links to a video demo of their product. How might they achieve that?
We have a demo repository that implements the steps in this blog post. Check it out to see it in action!
Setup and prep
Create a GitBook space in the appropriate org
Create a new empty GitHub repo to sync content to
Set up sync with GitHub repo, making sure to choose initial import from GitBook
Add a
.gitbook.yaml
file in the root to tell GitBook we're storing our documentation in the docs folder. It should contain just the lineroot: ./docs/
. Create a folderdocs
in the root of your repository.
At this stage, the building blocks are laid to start making modifications to files using scripts.
Scripting the footer
At this point, it's time to start thinking about how the generated content will be generated. This will vary greatly depending on your use case. If you're generating content from docstrings, you may be able to find a program that outputs markdown in the format you're looking for. For other types of content generation, you might need to write a script yourself. For the purposes of this step, you need to run a program (in a format that can be run on GitHub Actions) that modifies your documentation and outputs Markdown.
Here's an example program written in Javascript, that adds a footer to every documentation page that doesn't already have it.
scripts/append-footer.js
var glob = require("glob");
var fsPromises = require("fs/promises");
var path = require("path");
const { spawn } = require("child_process");
// read environmental variables
const ghActor = process.env["GITHUB_ACTOR"];
const isGitHubActions = Boolean(process.env["GITHUB_ACTIONS"]);
const GITBOOK_ACTOR = "gitbook-bot";
console.log(`GitHub actions ${isGitHubActions}`);
console.log(`GitHub actor ${ghActor}`);
if (isGitHubActions) {
// If we're in GitHub Actions, only run this for pushes from GitBook
if (ghActor !== GITBOOK_ACTOR) {
process.exit(0);
}
}
// Load the footer from the footer.md file
const footer = require("fs").readFileSync(path.join(__dirname, "./footer.md"));
// find each markdown document in the docs directory
glob(path.join(__dirname, "../docs/**/*.md"), async (error, fileNames) => {
console.log(fileNames);
// for each document
const editPromises = fileNames.map(async (fileName) => {
// load the contents of the document
const fileContents = await (await fsPromises.readFile(fileName)).toString();
// if the document doesn't end with the footer text
if (!fileContents.endsWith(footer)) {
// add the footer text to the end of the document
const newFileContents = fileContents + footer;
await fsPromises.writeFile(fileName, newFileContents);
}
});
await Promise.all(editPromises);
spawn("git", ["add", "."]);
});
This example code depends on the glob npm package, so you'll need to add it to your package.json. If you don't already have a package.json, you can create one in your repository root using npm init -y
, and install glob with npm install --save glob
. You can store both append-footer.js
and footer.md
in the scripts
folder in your repository.
Remember - you don't have to use Javascript to modify or generate your documentation! This is just an example. Feel free to use any program that can run in GitHub actions.
Automating generation with GitHub Actions
Now that we have our script, we need to run it automatically each time our content is changed. To do that, we'll configure a GitHub Actions workflow. In our repository, we'll create a directory at .github/workflows
, to store our workflows. In there, we'll create a file called append-footer.yml
.
name: append-footer
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
with:
node-version: v16.x
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: npm install
run: npm ci
- name: Enforce docs footer
run: node ./scripts/append-footer.js
- name: Git Prep
run: |
git config --local user.email "footer-bot@coolproductinc.technology"
git config --local user.name "footer-bot[bot]"
git diff
git diff-index HEAD
git diff-index --quiet HEAD || git commit -am "docs(footer): ensure footer exists on all docs pages"
- name: Git Push
run: "git push origin $(git branch --show-current) || true"
This workflow does a lot - lets step through it.
We first name the workflow and configure it to run each time there's a push to the repository's main branch. The script itself ensures that we only run when GitBook pushes to main - no need to configure that here.
Using the ubuntu-latest base image, we use the setup-node action to ensure we're using the correct version of node.js, check out the contents of the repository, and install dependencies.
The next few steps are more interesting - first we run the script above, which will append the footer to all documentation pages that don't already have it, and stages the results in git.
At this point, we configure git. We set up a dummy email and name to be attached to the commit, and only if there was staged changes, commits the code. In the case that each documentation file already has the correct footer, there are no changes to commit, so we ignore them.
Finally, we push the new commit to GitHub. GitBook will read the changes and update its copy of the documentation.
CoolProductIncorporated no longer have to think about footers - they can trust that the robots will handle it, and focus on writing the very best documentation they can for their Cool Product!
Thanks!
Thanks for reading. We hope this article was helpful for you. If you have any questions, please feel free to get in touch with us.
Sometimes, it can be useful to automatically generate some of your documentation. Whether you're generating Markdown based on Docstrings, or you're adding a footer with a link to a feedback form at the bottom of every page, you can achieve this effect using GitBook, with help from the GitHub Sync feature.
For the purposes of this example, let's consider a company, CoolProductIncorporated who need to document their cool developer focused product. The team decides that at the end of each page of documentation, they want to add a footer that links to a video demo of their product. How might they achieve that?
We have a demo repository that implements the steps in this blog post. Check it out to see it in action!
Setup and prep
Create a GitBook space in the appropriate org
Create a new empty GitHub repo to sync content to
Set up sync with GitHub repo, making sure to choose initial import from GitBook
Add a
.gitbook.yaml
file in the root to tell GitBook we're storing our documentation in the docs folder. It should contain just the lineroot: ./docs/
. Create a folderdocs
in the root of your repository.
At this stage, the building blocks are laid to start making modifications to files using scripts.
Scripting the footer
At this point, it's time to start thinking about how the generated content will be generated. This will vary greatly depending on your use case. If you're generating content from docstrings, you may be able to find a program that outputs markdown in the format you're looking for. For other types of content generation, you might need to write a script yourself. For the purposes of this step, you need to run a program (in a format that can be run on GitHub Actions) that modifies your documentation and outputs Markdown.
Here's an example program written in Javascript, that adds a footer to every documentation page that doesn't already have it.
scripts/append-footer.js
var glob = require("glob");
var fsPromises = require("fs/promises");
var path = require("path");
const { spawn } = require("child_process");
// read environmental variables
const ghActor = process.env["GITHUB_ACTOR"];
const isGitHubActions = Boolean(process.env["GITHUB_ACTIONS"]);
const GITBOOK_ACTOR = "gitbook-bot";
console.log(`GitHub actions ${isGitHubActions}`);
console.log(`GitHub actor ${ghActor}`);
if (isGitHubActions) {
// If we're in GitHub Actions, only run this for pushes from GitBook
if (ghActor !== GITBOOK_ACTOR) {
process.exit(0);
}
}
// Load the footer from the footer.md file
const footer = require("fs").readFileSync(path.join(__dirname, "./footer.md"));
// find each markdown document in the docs directory
glob(path.join(__dirname, "../docs/**/*.md"), async (error, fileNames) => {
console.log(fileNames);
// for each document
const editPromises = fileNames.map(async (fileName) => {
// load the contents of the document
const fileContents = await (await fsPromises.readFile(fileName)).toString();
// if the document doesn't end with the footer text
if (!fileContents.endsWith(footer)) {
// add the footer text to the end of the document
const newFileContents = fileContents + footer;
await fsPromises.writeFile(fileName, newFileContents);
}
});
await Promise.all(editPromises);
spawn("git", ["add", "."]);
});
This example code depends on the glob npm package, so you'll need to add it to your package.json. If you don't already have a package.json, you can create one in your repository root using npm init -y
, and install glob with npm install --save glob
. You can store both append-footer.js
and footer.md
in the scripts
folder in your repository.
Remember - you don't have to use Javascript to modify or generate your documentation! This is just an example. Feel free to use any program that can run in GitHub actions.
Automating generation with GitHub Actions
Now that we have our script, we need to run it automatically each time our content is changed. To do that, we'll configure a GitHub Actions workflow. In our repository, we'll create a directory at .github/workflows
, to store our workflows. In there, we'll create a file called append-footer.yml
.
name: append-footer
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
with:
node-version: v16.x
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: npm install
run: npm ci
- name: Enforce docs footer
run: node ./scripts/append-footer.js
- name: Git Prep
run: |
git config --local user.email "footer-bot@coolproductinc.technology"
git config --local user.name "footer-bot[bot]"
git diff
git diff-index HEAD
git diff-index --quiet HEAD || git commit -am "docs(footer): ensure footer exists on all docs pages"
- name: Git Push
run: "git push origin $(git branch --show-current) || true"
This workflow does a lot - lets step through it.
We first name the workflow and configure it to run each time there's a push to the repository's main branch. The script itself ensures that we only run when GitBook pushes to main - no need to configure that here.
Using the ubuntu-latest base image, we use the setup-node action to ensure we're using the correct version of node.js, check out the contents of the repository, and install dependencies.
The next few steps are more interesting - first we run the script above, which will append the footer to all documentation pages that don't already have it, and stages the results in git.
At this point, we configure git. We set up a dummy email and name to be attached to the commit, and only if there was staged changes, commits the code. In the case that each documentation file already has the correct footer, there are no changes to commit, so we ignore them.
Finally, we push the new commit to GitHub. GitBook will read the changes and update its copy of the documentation.
CoolProductIncorporated no longer have to think about footers - they can trust that the robots will handle it, and focus on writing the very best documentation they can for their Cool Product!
Thanks!
Thanks for reading. We hope this article was helpful for you. If you have any questions, please feel free to get in touch with us.
Get the GitBook newsletter
Get the latest product news, useful resources and more in your inbox. 130k+ people read it every month.
Similar posts
![The GitBook logo on a blue, yellow and black gradient background.](https://framerusercontent.com/images/hDsrqgTVg44rSR6v8viotoxWlw.jpg)
![The GitBook logo on a blue, yellow and black gradient background.](https://framerusercontent.com/images/hDsrqgTVg44rSR6v8viotoxWlw.jpg)
![The GitBook logo on a blue, yellow and black gradient background.](https://framerusercontent.com/images/hDsrqgTVg44rSR6v8viotoxWlw.jpg)
New in GitBook: Our published documentation is now open source, so you can contribute
27 Mar 2024
![A photograph of Steve Ashby](https://framerusercontent.com/images/IADa8V9McGcE68KsuFgi0bGbpbY.webp)
Steve Ashby
![A black and yellow logo on a black background.](https://framerusercontent.com/images/tNbXRDYaJ3gaZrZ9pJzDcM7rq2s.jpg)
![A black and yellow logo on a black background.](https://framerusercontent.com/images/tNbXRDYaJ3gaZrZ9pJzDcM7rq2s.jpg)
![A black and yellow logo on a black background.](https://framerusercontent.com/images/tNbXRDYaJ3gaZrZ9pJzDcM7rq2s.jpg)
New in GitBook: Published content gets a new look, multi-space search and better performance
4 Mar 2024
![A photograph of Steve Ashby](https://framerusercontent.com/images/IADa8V9McGcE68KsuFgi0bGbpbY.webp)
Steve Ashby
![A gradient background with an illustration of a card in the centre. The card has a letter a and a sparkle in the top-right corner](https://framerusercontent.com/images/kI0PzfeiIw2suGNjjpIQ2q1QwZ0.jpg)
![A gradient background with an illustration of a card in the centre. The card has a letter a and a sparkle in the top-right corner](https://framerusercontent.com/images/kI0PzfeiIw2suGNjjpIQ2q1QwZ0.jpg)
![A gradient background with an illustration of a card in the centre. The card has a letter a and a sparkle in the top-right corner](https://framerusercontent.com/images/kI0PzfeiIw2suGNjjpIQ2q1QwZ0.jpg)
New in GitBook: Write with AI, turn snippets into docs, and more
2 Feb 2024
![A photograph of Steve Ashby](https://framerusercontent.com/images/IADa8V9McGcE68KsuFgi0bGbpbY.webp)
Steve Ashby
Get started for free
Play around with GitBook and set up your docs for free. Add your team and pay when you’re ready.
Get started for free
Play around with GitBook and set up your docs for free. Add your team and pay when you’re ready.
![](https://framerusercontent.com/images/b4KGxXlVMIfQ6gQeO4WZIfp8Ez8.png)