Handbook Development
The handbook site uses Hugo for static page generation from Markdown.
The handbook uses a base theme called Docsy. A custom theme override is located in the Docsy GitLab Theme project and automatically included in the handbook setup.
Support
For help and support with the development environment, please reach out in the public #handbook Slack channel.
If you encounter a problem or bug, please open an issue or MR in the respective handbook projects.
Edit the handbook in your browser
Follow the editing the handbook documentation.
Architecture Overview
flowchart TD A(docsy) --> B B(docsy-gitlab) --> H B(docsy-gitlab) --> I C(www-gitlab-com) --> H C(www-gitlab-com) --> I D(handbook) --> H E(handbook-internal) --> I H{build} --> |Deploy| F I{build} --> |Deploy| G F[handbook.gitlab.com] G[internal.gitlab.com]
There are four internal projects and one external project used in the process of building and deploying the internal and external handbooks.
- Docsy is the base theme used for both handbook sites.
- Docsy GitLab is an extension to the base Docsy theme with GitLab specific customizations and features. Docsy GitLab is included in both handbook sites.
- www-gitlab-com is the source repository of data files used by both handbook sites.
- handbook is the public handbook site.
- internal-handbook is the internal handbook site.
Run the handbook locally for edits
Supported methods:
- Docker or compatible runtime (all software preinstalled in a container image)
- Local installation (experienced users, more software dependencies, can break)
Requirements
- Command line:
git
,wget
(for syncing data). Additional requirements for local installation, see below. - Docker or compatible runtime (for running the Hugo environment in a container)
Clone the handbook Git repository
Cloning the repository allows you to manually edit the handbook locally. If you prefer to use the Web IDE, please continue reading the editing the handbook documentation.
We recommend using git to clone the repository and then editing the handbook with a text editor such as Visual Studio Code, Typora, Nova or Sublime to name a few.
Clone the repository:
git clone git@gitlab.com:gitlab-com/content-sites/handbook.git
git clone git@gitlab.com:gitlab-com/content-sites/internal-handbook.git
git clone git@gitlab.com:gitlab-com/content-sites/docsy-gitlab.git
Set up the repository
After cloning the repository, sync the required data files from the
data file location (currently the www-gitlab-com
repository). Without this
step, the handbook cannot be run locally.
Open a terminal, navigate into the cloned handbook repository path, and run the sync-data.sh
script.
Example for the public handbook:
cd handbook
./scripts/sync-data.sh
Running Hugo
Hugo needs to be run to generate the static files from the handbook markdown content. There are two ways to run Hugo:
Parameters for Hugo
The handbook is huge, and by default, the hugo server
command loads everything to memory.
The following options for the hugo
command can be helpful for debugging or otherwise running locally:
--environment=production
: generate a production build (asset minification, checksums, etc)- Note:
hugo v0.x.x+extended
version must be installed, usehugo version
to check - Note:
npm i
must be run as a prerequisite to installpostcss
andautoprefixer
dependencies
- Note:
--renderToDisk
: slower but requires less memory to run. Useful if you have less than 16GB allocated to docker machine--verbose
: enables verbose logging output--templateMetrics
and--templateMetricsHints
: prints metrics related to how frequently templates are invoked and how much time is being spent evaluating them--printMemoryUsage
: periodically prints memory usage while the site is building
Build static files
To render the entire site to disk (and inspect the output in ${PWD}/public
),
purge the generated files first, and then run Hugo.
make clean
docker run --rm -v $(pwd):$(pwd) -w $(pwd) hugomods/hugo:exts hugo
# or
hugo
Permissions
For some pages to render you may need a personal access token.
Generate one and export it as an environment variable prior to running hugo
commands:
export HUGOxPARAMSxGITLAB_API_KEY="<token>"
hugo ...
If you need to make changes to the underlying theme you’ll need to make changes in the Gitlab-Docsy
module.
Linting content
We use markdownlint-cli2
and Vale to enforce
rules in handbook content.
markdownlint
Refer to the markdown guide for style guide information, and guidance on rules.
We use markdownlint-cli2
in our pipelines with a slightly customized set of rules. Before pushing any changes, you
should run markdownlint-cli2
and fix any suggested changes to avoid pipeline failures.
To run markdownlint-cli2
using Docker, run:
docker run --rm -v $(pwd):$(pwd) -w $(pwd) davidanson/markdownlint-cli2 content/**/*.md
If you have markdownlint-cli2
installed locally, you can run the command in the relevant repository.
This method is recommended when editing the config file (look for the markdownlint
file), and testing the changes. To have markdownlint automatically fix some errors,
add the fix option:
markdownlint-cli2 --fix "content/**/*.md"
Rules are configured to be close to the GitLab documentation markdownlint, without some of the stricter styling rules. The relevant rules are also noted in the markdown guide
Vale
We use Vale to warn when some rules from the Handbook Markdown Guide. are broken. Vale is not run in pipelines.
To run Vale using Docker, run:
docker run --rm -v $(pwd):$(pwd) -w $(pwd) jdkato/vale content
Docsy GitLab Theme Development
Docsy is used as a base for the internal and public handbooks. Modifications and extensions have been added on top to ensure efficient handbook usage.
All Hugo partials and shortcodes should be added to this repository, instead of duplicating them locally into the handbook projects.
The Docsy GitLab theme is integrated into the public/internal handbook repositories using a Go module in go.mod.
Local Development
To develop on the Docsy GitLab theme locally build the handbook (or internal-handbook) project with the updated local copy of the docsy-gitlab theme following the steps below:
-
Add the following line to the bottom of the
go.mod
file in the handbook project:replace gitlab.com/gitlab-com/content-sites/docsy-gitlab => /YOUR/LOCAL/PATH/TO/docsy-gitlab
-
Run the Hugo server:
hugo server
-
Load the site locally:
open http://localhost:1313/
Any changes made to files in local docsy-gitlab
project will be rendered in the local instance.
Releases
Changes made to docsy-gitlab
will be made available to the handbook
and internal-handbook
after the version is bumped and deployed to each project. This includes all theme updates with partials, shortcodes, and any changes to /docs
. Much of this process has been automated, but a few manual steps are still required. To release a docsy-gitlab
change follow these steps:
- After the merge request is merged, a pipeline on the
main
brach will kick off. After the pipeline succeeds, therelease
job can be triggered manually. For example: https://gitlab.com/gitlab-com/content-sites/docsy-gitlab/-/pipelines/1304430830 - The release job will do three things:
- Create a release in the
docsy-gitlab
project. Example: https://gitlab.com/gitlab-com/content-sites/docsy-gitlab/-/releases/v0.3.25 - Create a merge request to
handbook
. Example: https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/6086 - Create a merge request to
internal-handbook
. Example: https://gitlab.com/gitlab-com/content-sites/internal-handbook/-/merge_requests/4771
- Create a release in the
- Assign a handbook backend maintainer or codeowner to each MR for review.
- Once the merge request to
handbook
andinternal-handbook
have been merged, the theme changes will be deployed to the sites.
For more information on the release process, see the release script.
NOTE: The release process depends on the GITLAB_TOKEN
access token to perform some actions. This token needs to be regularly refreshed. An issue has been created to trigger reminders to refresh the token.
Dependencies
Updating dependencies
Note: Before updating dependencies, review the
go.mod
file in the target project for additional notes and requirements.
Always update dependencies individually to isolate potential bugs and regressions. Never pull latest
but pin the dependencies to a specific released version.
hugo mod get server.com/project-name@version
Google Docsy
hugo mod get github.com/google/docsy@v0.9.1
Do not bump Docsy versions without testing them extensively in MR review apps.
Redirects
You can add redirects to the layouts/index.redirects
file in the relevant repository.
Refer to the GitLab Pages redirect documentation
for how these are formatted.
CI/CD Pipelines
Handbook & Internal Handbook
The CI/CD pipelines for the handbook
and internal-handbook
projects are roughly the same, and should remain that way.
build
stage
The build
stage performs a few linter and security jobs (handbooklint
, hugolint
, markdownlint
, and secret_detection
), and a build
job which builds the whole site and saves it as CI artifacts.
deploy
stage
The deploy
stage uses the artifacts generated in the build
stage to deploy the production site for changes to the main
branch or review apps which can be deployed for MRs.
notify
stage
The notify
stage has two jobs that are triggered on specific events:
post_comment_on_failure
posts a comment to the MR when themarkdownlint
orhandbooklint
jobs fail.notify_slack_on_build_failures
post a message to the #handbook-escalation Slack channel when there is a build failure on themain
branch. This type of failure would indicate a broken CI pipeline.
$BUILD_AND_TEST_ONLY
mode
The pipelines can be triggered to run in $BUILD_AND_TEST_ONLY
mode which means they will run all the test and build jobs, but none of the deploy or notify jobs. A pipeline can be triggered in $BUILD_AND_TEST_ONLY
mode by setting the $BUILD_AND_TEST_ONLY
CI variable to true
. This is used primarily by the downstream pipelines triggered from the www-gitlab-com
project.
$GITLAB_TOKEN
Tools or scripts that need to interact with the GitLab API to perform handbook tasks should use the GITLAB_TOKEN
CI variable. This is group level access token called Docsy GitLab Release
with a developer
role and has api
and write_repository
scopes. This token will expire after a year and will need to be refreshed. Follow the steps below to refresh the token:
- Create a new developer group level access token in <https://gitlab.com/groups/gitlab-com/content-sites/-/settings/access_tokens with api> and
write_repository
scopes. Give it the nameGITLAB_TOKEN_YYYY_MM_DD
(replace theYYYY_MM_DD
portion with the current date). - Update the value of GITLAB_TOKEN in docsy-gitlab, handbook, and internal-handbook with the new token value.
- Create a new release of Docsy GitLab Theme and ensure the pipeline works correctly.
- Delete the old token.
- A Zapier zap is configured with a webhook at the group level that should post to the
#handbook-escalation
channel when it is about to expire.
GitLab Pages Deployment
The deploy and review apps are configured in the pages
job in the .gitlab-ci.yml
configuration file.
-
Review app deploys can be run for merge requests by running the manual
pages
job, or by adding the~"deploy-review-app-always"
label to the MR. -
Production deploys are only run from the
main
branch. -
Conditional CI variables are used to configure the environment for review apps using GitLab Pages Multiple Deployments.
variables: PAGES_PREFIX: 'mr$CI_MERGE_REQUEST_IID' ENVIRONMENT: 'mr$CI_MERGE_REQUEST_IID' HUGO_BASEURL: "${CI_PAGES_URL}/${PAGES_PREFIX}"
The route map is configured in the .gitlab/route-map.yml
.
Docsy GitLab
The CI/CD pipeline for docsy-gitlab is responsible for building, testing, and releasing the Docsy GitLab theme used by both handbook
and internal-handbook
.
test
stage
The test
stage performs the markdownlint
, and secret_detection
jobs.
build
stage
The build
stage performs runs the hugo
command to ensure the theme builds successfully.
release
stage
The release
stage performs one manual job to create a new release of the theme and merge requests to both handbook
and internal-handbook
. See the Releases section for more details.
www-gitlab-com
The CI/CD pipeline for www-gitlab-com is responsible for triggering downstream builds of both handbook
and internal-handbook
in $BUILD_AND_TEST_ONLY
mode. This ensures that any changes to dependent data files in www-gitlab-com
will build successfully for both handbook
and internal-handbook
.
Danger review and reviewer roulette
Right now the handbook projects doesn’t use the Reviewer Roulette
feature of the danger-review
CI/CD component. See issue.
We use the architecture
plugin to provide guidance on how to review MRs that contain changes to
architecture evolution design documents.
In order to make Danger post message to MRs we need to setup a project token (api
scope with Developer
role) and
a CI/CD variable called DANGER_GITLAB_API_TOKEN
to contain this project token (Masked
but not Protected
).
For more details, follow the Danger documentation and inspect the MR adding the reviewer roulette to the public handbook.
A Zapier zap is configured with a webhook at the group level that should post to the #handbook-escalation
channel when it is about to expire.
Code quality report MR commenter
The CI/CD linting jobs generate code quality report artifacts for MR widget integration. If there are errors detected, a custom CI/CD job posts a Markdown table summary as MR comment, linking to helpful handbook editing resources.
The parse-codequality-report.sh
script in the handbook and internal-handbook generates the code quality report posted in the MR. Changes to these reports need to be applied to both projects.
The code quality report relies on the GITLAB_TOKEN
to perform the reporting actions on any MRs.
CI/CD maintenance tasks
- Test and bump the Hugo image versions, aligned with the
config/_default/config.yml
minimum version. - Test and bump the davidanson/markdownlint-cli2
Docker image tags in the
markdownlint
job. We are not using thelatest
tag to avoid production failures pulling different latest versions.
Architecture
The Markdown files get parsed by Hugo, and converted into static HTML files, including all assets (JS, CSS, images, etc.). The static files are uploaded to GitLab Pages.
Templates and Partials
Review the Hugo development documentation to learn more.
Triage bot
A triage bot exists to help triage issues and close stale merge requests. See the triage project readme for more information.