Hesham Meneisi
5 min readJul 4, 2020

--

Automate your React/Vue/Angular personal page using GitHub Actions

Automation saves your time, the most valuable non-renewable resource you have. Almost every developer has a personal page that they regularly update. So why not start the automation there?

In this article, I will take you through the detailed steps to automate your personal page. From building to releasing and deploying, all by just committing a change from the convenience of your favorite IDE.

Let’s get to business!

Step 1: Put your codebase on GitHub

If this is your main page on GitHub (i.e. your {User}/{User}.github.io repository), you cannot put your code on master.

GitHub has a restriction that your user page must be served from the master branch

So in this case, you have to push your code to a different branch (e.g. codebase). Here’s a quick snippet for moving to a different branch:

git branch codebase
# If this is a new repo, add all files and commit
git commit -am "first commit"
git push --set-upstream origin codebase

However, if this is a normal repository, then you can use the master branch for code and gh-pages for the distribution as usual.

Step 2: Add a release.config file

Using semantic-release is a great way to make sure you don’t end up with too many unnecessary releases every time you commit. We also have access to some awesome plugins like the semantic-release-gh-pages-plugin.

Here is a basic example of the ./release.config.js file you need to create:

const distZipPath = process.env.DIST_TAR_PATHmodule.exports = {
plugins: [
"@semantic-release/git",
],
verifyConditions: [
'@semantic-release/github',
],
prepare: [
],
publish: [
['@semantic-release/github',
{
'assets': [
{ 'path': distZipPath, 'label': 'Distribution' },
],
},
],
{
path: "@semantic-release/exec",
cmd: `tar -xzvf ${distZipPath}`
},
[
"@qiwi/semantic-release-gh-pages-plugin",
{
// Distribution directory (e.g. dist, build..)
"src": "build",
"msg": "ci: update dist",
// gh-pages by default, only set if you use codebase
"branch": "master",
// master by default, only set if you use codebase
"pullTagsBranch": "codebase",
}
]
],
}

I highlighted the parts you might need to change based on your repository/project.

Whenever a new release is created we add the distribution as an asset, unpack it, and publish the files using gh-pages. We will be setting the DIST_TAR_PATH var to point to the packed distribution in the next step.

Note that “src” has to point to whatever directory you unpack from “distZipPath”. This is determined by your npm/yarn setup and what directory you pack in the next step.

NOTE: If you don’t want to use semantic-release, you can simply skip this step and run “npm run deploy” or “yarn run deploy” after building in the next step. Refer to this for more details. With that said, I strongly recommend following the article so as not to run into unexpected issues (and because semantic-release is awesome!).

Step 3: Add some Actions!

GitHub Actions is rather new but by far my favorite CI/CD solution for small to medium projects. I just like keeping everything in one place! All you need to do is create a new workflow file and add two basic jobs: build/test and release.

For example, create a file named ./.github/workflows/ci-workflows.yml and start with the following head:

name: Build-Test-Releaseon:
push:
branches:
- codebase

This means the workflow will be triggered when you push to this branch. You should replace codebase with master if you store your code on master.

First, we need a job to test and build our project. Here’s an example using Yarn:

jobs:
test-and-build:
runs-on: ubuntu-latest env:
CI: true
steps:
- uses: actions/checkout@v1
- uses: borales/actions-yarn@v2.0.0
with:
cmd: install
- uses: borales/actions-yarn@v2.0.0
with:
cmd: build
- uses: borales/actions-yarn@v2.0.0
with:
cmd: test

And here’s what these steps look like when using npm:

- uses: actions/setup-node@v1
with:
node-version: 12.x

- name: Install
run: npm ci
- name: Build
run: npm run build
- name: Test
run: npm test

In this same job, we need to pack our distribution files into an archive and upload that as an artifact. Here’s how to do that:

- name: Pack
run: tar -czf dist.tar.gz build/
- name: Upload distribution artifact
uses: actions/upload-artifact@v1
with:
name: dist
path: dist.tar.gz

Uploading artifacts is currently the only way to preserve files when you need them in a different job. Note that the distribution directory might be called something else in your case (e.g. dist/ is the default for Vue).

The second job we need is the release job. This job will run the semantic-release action and decide whether or not to release+deploy a new version.

release:
needs: [ test-and-build ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Download distribution artifact
uses: actions/download-artifact@v1
with:
name: dist
- name: Semantic Release
uses: cycjimmy/semantic-release-action@v2
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
DIST_TAR_PATH: dist/dist.tar.gz
with:
branch: codebase
extra_plugins: |
@semantic-release/git@7.0.18
@semantic-release/exec@5.0.0
@qiwi/semantic-release-gh-pages-plugin@1.16.0-rc.1

Again, you will have to replace codebase with master if your code is stored on the master branch. The first step downloads the artifact uploaded by the previous job. Then semantic-release will proceed to execute what was specified in the release.config.js file earlier.

The whole file should look something like this:

name: Build-Test-Releaseon:
push:
branches:
- codebase
jobs:
test-and-build:
runs-on: ubuntu-latest env:
CI: true
steps:
- uses: actions/checkout@v1
- uses: borales/actions-yarn@v2.0.0
with:
cmd: install
- uses: borales/actions-yarn@v2.0.0
with:
cmd: build
- uses: borales/actions-yarn@v2.0.0
with:
cmd: test
- name: Pack
run: tar -czf dist.tar.gz build/
- name: Upload distribution artifact
uses: actions/upload-artifact@v1
with:
name: dist
path: dist.tar.gz
release:
needs: [ test-and-build ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Download distribution artifact
uses: actions/download-artifact@v1
with:
name: dist
- name: Semantic Release
uses: cycjimmy/semantic-release-action@v2
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
DIST_TAR_PATH: dist/dist.tar.gz
with:
branch: codebase
extra_plugins: |
@semantic-release/git@7.0.18
@semantic-release/exec@5.0.0
@qiwi/semantic-release-gh-pages-plugin@1.16.0-rc.1

I highlighted the parts you might need to change based on your repository/project.

Step 4: Get a Personal Access Token

If you noticed in the last step, we used the variable GH_TOKEN. This variable should be defined in the secrets section of the repository settings.

If you don’t already use a personal access token, make sure to create one in your account settings. Make sure the token you use can access the target repository and create releases.

And you are done! Now every time you commit something that triggers a new release, your personal page will be automatically updated!

If you are having any issues, comment and I will try to help. If you liked this article please recommend and for more articles like this consider following. Have a nice day while your automatons grind away!

--

--

Hesham Meneisi

I write to introspect, analyze problems, and find potential solutions. My approach to problem-solving has a highly analytical, no-nonsense style.