GitHub actions

Time:2019-12-23

introduce

GitHub actions is a CI (continuous integration) tool officially launched by GitHub, which is still inBetaVersion, which can only be used after applying for internal test qualification, can be seen in your own code warehouse after successful applicationActionsNow.

GitHub actions

Instructions

Here is a brief introductionGithub ActionsPlease refer to the official documents for details.

term

  1. workflow
    Represents a continuous integration process
  2. job
    Represents the construction task. Each workflow can be composed of one or more jobs, which can support concurrent job execution. When all jobs are completed, the workflow ends
  3. step
    Each job consists of one or more steps, which are executed in sequence
  4. action
    Each step is composed of one or more actions, which are executed in sequence. Here, action needs to be explained in particular. Action can be a custom script or a script that references a third party. It depends on the GitHub open source community. Many actions can be reused directly, without writing by itself. GitHub has provided an action market, and various third-party actions can be searched , and there are many actions available.

Constructing environment

Each job can specify the corresponding operating system, which supportsWindows、Linux、macOSGitHub will provide a virtual machine to execute the corresponding job.

Hardware specifications:

  • Dual core CPU
  • 7GB memory
  • 14GB SSD

Restrictions on use:

  • Each warehouse can only support 20 concurrent workflows at the same time
  • 1000 calls of GitHub API per hour
  • Up to six hours per job
  • Users in the free version can execute up to 20 jobs concurrently, and Mac OS only supports up to 5 jobs

It can be seen that under this configuration, the continuous integration of ordinary projects is certainly no problem.

Build records

Through theActionsTab, you can see the workflow build record in the project:
GitHub actions

Click a record to enter the details page, where you canreal timeView eachactionConsole output for debugging:
GitHub actions

Example

The basic concepts are introduced in the previous section. Let’s take a look at a few examplesGithub ActionsHow it is used.

Automatically deploy hexo blog to GitHub page

First of all, I thought I could use itGithub ActionsThis is my blog. The project is hosted at https://github.com/monkeywie/monkeywie.github.io. At present, the project has two branches,masterThe branch is used to store the static files compiled by hexo, anotherhexoThe branch is used to store the hexo project environment and markdown articles,masterBranch throughGithub PageAfter configuration, you can use themonkeywie.github.ioDomain name access.
GitHub actions

After writing the blog, you need to execute the command manually once to deploy:

hexo clean&&hexo d

Then take it.hexoBranch code pushed to GitHub

git push

in useGithub ActionsAfter that, justhexoThe branch code is pushed to GitHub, and the rest is handed over toGithub ActionsOK, we need to generate a pair ofPublic and private keyDeployment operations for hexo because of the deployment commands provided with hexohexo dYou need to have read and write permission to git remote warehouse.

ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:XG1vkchp5b27tteZASx6ZrPRtTayGYmacRdjjRxR1Y0 [email protected]
The key's randomart image is:
+---[RSA 2048]----+
|             .+o=|
|           o *Eoo|
|          . X B .|
|       . . + X +.|
|        S . = O..|
|         o O B =.|
|          O = *.*|
|         o . o ++|
|              .oo|
+----[SHA256]-----+

First put~/.ssh/id_rsa.pubThe public key in is added to theDeploye keysChina:
GitHub actions

Again~/.ssh/id_rsaThe private key in is added to theSecretsIn, name is defined asACTION_DEPLOY_KEY, the purpose is to read the private key and add it to the virtual machine during construction to obtain git warehouse access rights:
GitHub actions

After the preparation is completed, follow the tutorial, andhexoBranch creation.github/workflows/main.yamlThe file is used to configure the hexo deployment.

name: CI

on:
  push:
    branches:
      - hexo
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/[email protected]
        with:
          ref: hexo
      - name: Use Node.js ${{ matrix.node_version }}
        uses: actions/[email protected]
        with:
          version: ${{ matrix.node_version }}
      - name: Setup hexo
        env:
          ACTION_DEPLOY_KEY: ${{ secrets.ACTION_DEPLOY_KEY }}
        run: |
          mkdir -p ~/.ssh/
          echo "$ACTION_DEPLOY_KEY" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan github.com >> ~/.ssh/known_hosts
          git config --global user.email "[email protected]"
          git config --global user.name "monkeyWie"
          npm install hexo-cli -g
          npm install
      - name: Hexo deploy
        run: |
          hexo clean
          hexo d

The specific configuration syntax is not described in detail here. You can refer to it in the official documents.

The construction process is as follows:

  1. MonitorhexoBranch push operation
  2. Run a job atubuntuUnder virtual machine environment
  3. Use the official actions / checkout @ V1 to pull the source code
  4. Use the official actions / setup-node @ V1 to install the node environment
  5. Use${{ secrets.ACTION_DEPLOY_KEY }}Read the private key just generated and set it to environment variable,${{ exp }}The writing method is the built-in expression syntax of actions. For details, please refer to: Contexts and expression syntax for GitHub actions
  6. Write private key to~/.ssh/id_rsaIn the document, andgithub.comDomain name added to~/.ssh/known_hostsFile to prevent interactive commands from popping up on the first SSH access.
  7. Configure git user information
  8. Dependencies for installing hexo command line tools and projects
  9. Calling the hexo command for deployment

holdhexoThe branch code is pushed to GitHub to trigger workflow, and theActionsTab to see how the project is built.
GitHub actions

At this point, the transformation is completed. In the future, the code can be deployed automatically only after the article is written and submitted directly. It’s not too convenient to write in a node environment.

Automatically create project release

Some projects usually create aGithub ReleaseAnd upload the compiled file toReleaseFor example:
GitHub actions

If the manual operation is used, the steps are not only repetitive and cumbersome (each time, the distribution package corresponding to each operating system must be compiled and uploaded), but also the most painful thing is that for the domestic network environment, the speed of uploading files is simply intolerable, and it’s hard to upload more than half of the files, because of the network reasons, but also to upload again. I believe that the people who have used them are very physical Meeting.

I was thinking if I could use itGithub ActionsTo createRelease, and do the corresponding compilation and upload, then the above problems can be solved, so search in the official marketReleaseKeyword, as expected, correspondingactionsThe following:

  • Create release: used to create a release
  • Upload release asset: used to upload resources to the corresponding release

Then create aGithub warehouse, the warehouse address I tested is https://github.com/monkeywie/github-actions-demo. The project is written in go language. The code is very simple, which is two Hello world level codes, including ordinary Go program and CGO program.

The construction process of the project is in the projectgit push --tagsWhen the workflow is triggered, theGithub ActionsCompileWindows、Linux、macOSThe 64 bit executable files corresponding to the three operating systems aretag nameandtag messageTo create the correspondingGithub ReleaseAnd upload the compiled file.

Also create a.github/workflows/main.ymlThe contents of the document are as follows:

name: CI

on:
  push:
    # Sequence of patterns matched against refs/tags
    tags:
      - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/[email protected]
      - name: Use Golang
        uses: actions/[email protected]
        with:
          go-version: "1.13.x"
      - name: Build normal
        run: |
          CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o normal-windows-x64.exe cmd/normal/main.go
          CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o normal-linux-x64 cmd/normal/main.go
          CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o normal-darwin-x64 cmd/normal/main.go
          zip normal-windows-x64.zip normal-windows-x64.exe
          zip normal-linux-x64.zip normal-linux-x64
          zip normal-darwin-x64.zip normal-darwin-x64
      - name: Build cgo
        run: |
          go get github.com/monkeyWie/xgo
          ~/go/bin/xgo -targets=windows/amd64,linux/amd64,darwin/amd64 -ldflags="-w -s" -pkg=cmd/cgo/main.go -out=cgo .
          mv cgo-windows-* cgo-windows-x64.exe
          mv cgo-linux-* cgo-linux-x64
          mv cgo-darwin-* cgo-darwin-x64
          zip cgo-windows-x64.zip cgo-windows-x64.exe
          zip cgo-linux-x64.zip cgo-linux-x64
          zip cgo-darwin-x64.zip cgo-darwin-x64
      - name: Create Release
        id: create_release
        uses: monkeyWie/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          draft: false
          prerelease: false

      - name: Upload Release normal windows
        uses: actions/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./normal-windows-x64.zip
          asset_name: normal-${{ steps.create_release.outputs.tag }}-windows-x64.zip
          asset_content_type: application/zip
      - name: Upload Release normal linux
        uses: actions/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./normal-linux-x64.zip
          asset_name: normal-${{ steps.create_release.outputs.tag }}-linux-x64.zip
          asset_content_type: application/zip
      - name: Upload Release normal darwin
        uses: actions/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./normal-darwin-x64.zip
          asset_name: normal-${{ steps.create_release.outputs.tag }}-darwin-x64.zip
          asset_content_type: application/zip

      - name: Upload Release cgo windows
        uses: actions/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./cgo-windows-x64.zip
          asset_name: cgo-${{ steps.create_release.outputs.tag }}-windows-x64.zip
          asset_content_type: application/zip
      - name: Upload Release cgo linux
        uses: actions/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./cgo-linux-x64.zip
          asset_name: cgo-${{ steps.create_release.outputs.tag }}-linux-x64.zip
          asset_content_type: application/zip
      - name: Upload Release cgo darwin
        uses: actions/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./cgo-darwin-x64.zip
          asset_name: cgo-${{ steps.create_release.outputs.tag }}-darwin-x64.zip
          asset_content_type: application/zip

The construction process is as follows:

  1. Monitoring tag name isvThe first push
  2. Run a job atubuntuUnder virtual machine environment
  3. Pull source code, installgolang 1.13.xEnvironmental Science
  4. Usego buildCross compile 64 bit executable files under different operating systems, and compress them with zip
  5. UsexgoCross compile 64 bit executable files under different operating systems, and compress them with zip
  6. UsemonkeyWie/[email protected]Create a release that uses${{ secrets.GITHUB_TOKEN }}This isGithub ActionsA built-in secret key is used to authorize access to your own GitHub repository. The principle is to use this keyTOKENcallGithub APITo create a release, there is another${{ github.ref }}AlsoGithub ActionsA built-in variable, and then through the actionwithPass parameters.
  7. Useactions/[email protected]To upload a file, two expressions are used here${{ steps.create_release.outputs.upload_url }}and${{ steps.create_release.outputs.tag }}, you can get the specifiedactionThe first is to obtain the corresponding upload address of the created release, and the second is to obtain the corresponding tag (for example, v1.0.0), so that the uploaded file can be carried with the version number. Because of thisactionMultiple file uploads are not supported, so multiple actions are written to upload.

Next, I will type AtagAnd thenpushGo up and see the effect:

#Create a tag named v1.0.8 and add a description
Git tag - a "v1.0.8" - M 'release v1.0.8
Fixed the following bugs:
1. xxxxx
2. xxxxx'
#Push the tag to GitHub
git push --tags

And then you can see that there’s a new oneworkflowRunning:
GitHub actions

After runningReleasesPage view results:
GitHub actions

Perfect! In line with the expected results.

Note: since the official create release can not meet the requirements, IforkA copy of create release code means thattag nameIt’s output. Here’s the related PR, which hasn’t been merged yet. So the above action of creating release is my own warehousemonkeyWie/[email protected], and knowledge about go cross compile. If you are interested, please take a look at my blog: go cross compile.

Automatically build and deploy docker images

stayGithub ActionsThe virtual machine provided has been built indocker, and I happen to have a project built for domestic network reasonsDocker mirror imageVery slow, this is meforkThis is a cross compilation project for go project. The warehouse address is https://github.com/monkeywie/xgo. The main working principle of this project is to build various kinds of built-in works in dockerCross compilationAnd then provide the cross compilation function of go project. Here is an excerptDockerfileContent:

GitHub actions

Look at all theseapt-get install, you can see how slow it is to build locally. Next, useGithub ActionsTo help build and deploy images.

Because the image will be pushed todocker hubOn the official image warehouse, you need to verify the account information,
Here I have configured my user password toSecrets, so that you can access:
GitHub actions

Write build file.github/workflows/main.yml

name: CI

on:
  push:
    branches:
      - master
    paths:
      - "docker/base/*"

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/[email protected]
      - name: Docker login
        run: docker login -u liwei2633 -p ${{ secrets.DOCKER_HUB_PWD }}
      - name: Docker build base
        run: |
          docker pull liwei2633/xgo:base
          docker build --cache-from=liwei2633/xgo:base -t liwei2633/xgo:base ./docker/base
          docker push liwei2633/xgo:base
      - name: Docker build other
        run: |
          docker build -t liwei2633/xgo:go-1.12.10 ./docker/go-1.12.10
          docker push liwei2633/xgo:go-1.12.10
          docker build -t liwei2633/xgo:go-1.12.x ./docker/go-1.12.x
          docker push liwei2633/xgo:go-1.12.x
          docker build -t liwei2633/xgo:go-1.13.1 ./docker/go-1.13.1
          docker push liwei2633/xgo:go-1.13.1
          docker build -t liwei2633/xgo:go-1.13.x ./docker/go-1.13.x
          docker push liwei2633/xgo:go-1.13.x
          docker build -t liwei2633/xgo:go-latest ./docker/go-latest
          docker push liwei2633/xgo:go-latest

The construction process is as follows:

  1. Listen for the push operation of the master branch, anddocker/baseThe files in the directory can be built only when they are modified. The purpose of this is to avoid triggering workflow when other files that are not related to docker construction are changed
  2. Run a job atubuntuUnder virtual machine environment
  3. Pull source code
  4. Log in to docker hub through the previously configured${{ secrets.DOCKER_HUB_PWD }}There is no need to worry that the console output will expose the passwordsecretsThe accessed variables will be mosaic when output from the console
    GitHub actions
  5. To build a mirror, here’s a tip--cache-from=liwei2633/xgo:base, download the previous image in advanceliwei2633/xgo:base, and then you can use thedockerCache mechanism of
    GitHub actions
  6. Push images and compile and push images of different go versions

This wayGithub ActionsIt reduces the time of building image and deployment to13 minutes
GitHub actions

Although it’s still quite slow, it’s faster than the local construction. Once, the local construction waited for more than an hour. Because of network reasons, the installation of a software source failed directly, and it had to start again. So the decision was made,Github ActionsReally sweet!!

Epilogue

From the above three example projects, we can see thatGithub ActionsIt saves us a lot of time and repetitive operations, and most of the choreography functions can be easily realized through the official actions market. It’s really a conscience product that can be blown up, so hurry up to taste it.