The landscape of static site generation has evolved into a critical component of modern web development, requiring robust and secure deployment pipelines. For developers utilizing platforms like GitHub, the peaceiris/actions-gh-pages action stands out as a highly regarded tool for publishing build directories to GitHub Pages. This action specializes in taking a target build directory, creating a commit in a designated branch (typically gh-pages), and serving it via GitHub Pages infrastructure. It is designed to integrate seamlessly with any workflow that produces a build directory, making it compatible with a wide array of static site generators and web application frameworks.
While GitHub offers its own official GitHub Pages action, the peaceiris/actions-gh-pages action has gained significant traction within the developer community, evidenced by its high number of stars on GitHub. This popularity suggests a level of confidence in its quality, reliability, and long-term maintenance. The action is particularly noted for its flexibility, supporting a diverse ecosystem of tools including Jekyll, Hugo, MkDocs, Gatsby, GitBook, mdBook, Next.js, Nuxt, VuePress, React-Static, and Gridsome. It is essential to understand that this action does not perform the build process itself; rather, it assumes the build has already been completed by previous steps in the workflow and handles the subsequent deployment of the generated files.
Security and Authentication Tokens
Security is a paramount concern when configuring continuous integration and continuous deployment (CI/CD) workflows. The peaceiris/actions-gh-pages action supports three distinct types of tokens for authenticating and committing changes to the repository. Among these, the GITHUB_TOKEN is highly recommended for most use cases due to its superior security profile and ease of configuration.
The GITHUB_TOKEN is a temporary, automatically generated secret that GitHub Actions runners create for each workflow run. Unlike personal access tokens, which may grant broad access to a user's entire account or organization if compromised, the GITHUB_TOKEN is scoped strictly to the specific repository in which the workflow is running. This limitation ensures that even if the token were somehow exposed, an attacker would only have access to that single repository, significantly reducing the potential attack surface. Furthermore, the GITHUB_TOKEN requires zero manual setup. Developers do not need to store secrets in their repository settings; the action can simply reference ${{ secrets.GITHUB_TOKEN }}, and the runner will substitute the valid token at runtime. This eliminates the risk of human error in secret management and ensures that no human, including the developer themselves, can view the actual token value.
For scenarios requiring deployment to external repositories, the action supports the use of a deploy_key. This is necessary because the default GITHUB_TOKEN is typically insufficient for writing to a different repository. In such cases, developers must generate a deploy key in the target external repository and store it as a secret (e.g., ACTION_DEPLOY_KEY) in the source repository. The action then uses this key to authenticate and push changes to the external destination.
Basic Deployment Configuration
The fundamental usage of the peaceiris/actions-gh-pages action involves defining a step in a GitHub Actions workflow file (e.g., .github/workflows/gh-pages.yml). The action requires the github_token for authentication and the publish_dir parameter to specify the location of the built files.
A typical workflow step for deploying a site built with a generic static site generator or a Node-based application might look like this:
yaml
- name: Deploy to GitHub Pages 🚀
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: public
In this configuration, the action takes the contents of the public directory (a common default output directory for many static site generators) and deploys it to the gh-pages branch by default. For projects using Jekyll, the publish_dir might be set to _site, while for Node.js applications using tools like React or Vue, it is often set to build or dist, depending on the specific framework's configuration. The version specified in the example (@v3) indicates a major version of the action; however, users should always consult the latest README of the peaceiris/actions-gh-pages repository to ensure they are using the most current and stable version, such as @v4.
Advanced Deployment Scenarios
The peaceiris/actions-gh-pages action offers several configuration options to handle more complex deployment requirements, including publishing to custom branches, external repositories, and preserving historical assets.
Publishing to a Custom Branch
While gh-pages is the default branch for GitHub Pages for user and organization sites, project sites often use the main or master branch for hosting. The action allows developers to specify a different branch using the publish_branch parameter. This is particularly useful when deploying a project site where the source code and the deployed site reside in the same repository.
yaml
- name: Deploy to GitHub Pages 🚀
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: public
publish_branch: master
Deploying to an External Repository
In some organizational structures, the source code and the deployed site may need to reside in separate repositories. The action supports deployment to an external repository via the external_repository parameter. However, this configuration requires careful attention to authentication. The default GITHUB_TOKEN will likely not have the necessary permissions to write to a different repository. Therefore, a deploy_key must be used.
yaml
- name: Deploy to GitHub Pages 🚀
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
external_repository: username/external-repository
publish_branch: master
publish_dir: public
In this scenario, the deploy_key secret must contain the private key generated from the target external-repository. The publish_branch parameter specifies the branch in the external repository where the site will be hosted.
Preserving Old Files with keep_files
By default, the peaceiris/actions-gh-pages action performs a "clean" deployment, meaning it deletes all existing files in the target branch before copying the new build files. This ensures that the deployed site exactly matches the current build. However, this behavior can cause issues for applications that use hash-based filenames for assets (e.g., app.a1b2c3.js). If a user has the old version of the HTML page cached in their browser, but the associated JavaScript file has been deleted from the server during a clean deployment, the browser will receive a 404 error when trying to load the script. This can result in a blank page or a broken application state.
To mitigate this, the action provides a keep_files option. Setting this parameter to true prevents the action from deleting old files in the target branch. This allows previous versions of hashed assets to remain available, ensuring that users with cached old HTML files can still successfully load the corresponding JavaScript or CSS files. This is particularly useful for Vue applications and other single-page applications that rely on cached assets for performance.
yaml
- name: Deploy to GitHub Pages 🚀
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: public
keep_files: true
GitHub Pages Configuration Considerations
Deploying to GitHub Pages via a custom action like peaceiris/actions-gh-pages introduces specific configuration requirements that differ from the default Jekyll-based setup. GitHub Pages natively supports Jekyll, which processes files in the repository to generate a site. When using other static site generators, it is crucial to prevent GitHub from attempting to process the files with Jekyll, as this can lead to unexpected behavior or build failures.
The standard practice is to include a .nojekyll file in the root of the published directory. This file can be empty; its presence signals to GitHub Pages that Jekyll processing should be skipped. This is especially important for user and organization pages, which by default publish from the main branch. If the peaceiris/actions-gh-pages action is deploying to the gh-pages branch, the repository settings must be adjusted to reflect this. In the repository's GitHub Pages settings, the source should be set to the gh-pages branch rather than the main or master branch.
Integration with Static Site Generators
The peaceiris/actions-gh-pages action is designed to be agnostic to the underlying static site generator. It simply takes a directory and publishes it. This makes it highly versatile and compatible with a wide range of tools. Developers using Hugo, MkDocs, Gatsby, GitBook, mdBook, Next.js, Nuxt, VuePress, React-Static, or Gridsome can use the same action structure, merely adjusting the publish_dir to match their tool's output directory.
For example, a workflow using Hugo might first run the Hugo build step and then use the action to deploy the public directory. Similarly, a Vue project would run npm run build to generate the dist directory, which would then be deployed. The action's ability to work with any tool that produces a build directory makes it a universal solution for static site deployment on GitHub.
The action has been featured on the GitHub Blog alongside other popular actions like the Hugo Action and mdBook Action, highlighting its significance in the GitHub Actions ecosystem. It provides a straightforward and reliable way to bridge the gap between local development and public hosting, ensuring that developers can focus on content and functionality rather than deployment logistics.
Conclusion
The peaceiris/actions-gh-pages action represents a mature and secure solution for deploying static sites to GitHub Pages. By leveraging the GITHUB_TOKEN for authentication, it eliminates the need for manual secret management and reduces security risks. Its flexibility in supporting custom branches, external repositories, and asset preservation makes it suitable for a wide variety of deployment scenarios. Furthermore, its compatibility with numerous static site generators and web frameworks underscores its utility in the modern development landscape. Developers should ensure they configure their GitHub Pages settings correctly, particularly by using the .nojekyll file and selecting the appropriate publishing branch, to ensure a smooth and error-free deployment process. As the ecosystem of static site generators continues to expand, actions like peaceiris/actions-gh-pages will remain a vital tool for developers seeking reliable and efficient deployment pipelines.