preface

Recently, GitHub Actions has been added to the company’s internal project release process, and the whole experience is better. The main purpose of this article is to quickly build automated processes such as automated tests and packaged push Docker images for those who are new to GitHub Actions.

Create a project

This article focuses on the Go language as an example, of course, other languages are similar and have little to do with the language itself.

Here we start by creating a project on GitHub and writing a few simple pieces of code main.go:

var version = "0.0.1"

func GetVersion(a) string {
	return version
}

func main(a) {
	fmt.Println(GetVersion())
}
Copy the code

The content is very simple, just print the version number; Main_test. go:

func TestGetVersion1(t *testing.T) {
	tests := []struct {
		name string
		want string
	}{
		{name: "test1", want: "0.0.1"}},for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ifgot := GetVersion(); got ! = tt.want { t.Errorf("GetVersion() = %v, want %v", got, tt.want)
			}
		})
	}
}
Copy the code

We can run the unit test by executing Go Test.

$ go testPASS ok github.com/crossoverJie/go-docker 1.729 sCopy the code

Automatic test

Of course, the above process can be automated by Actions.

Create a.github/workflows/*.yml configuration file in the root path of the project and add the following content:

name: go-docker
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    if: github.ref = = 'refs/heads/main' || startsWith(github.ref, 'refs/tags')
    steps:
      - uses: actions/checkout@v2
      - name: Run Unit Tests
        run: go test
Copy the code

A quick explanation:

  • nameNeedless to say, create a noun for the current workflow.
  • onIt means under what event, in this case, does the code happenpushMore event definitions can be found in the official documentation:

Events that trigger workflows

  • jobsIs to define the task, there is only one nametestThe task.

This task is run in ubuntu-latest and only runs when the main branch has a push or a tag push.

The runtime uses actions/checkout@v2, an Action wrapped by someone else, using the official pull code Action.

  • Based on this logic, we can share and use others flexiblyActionTo simplify the process. Same thingGitHub ActionVery scalable.

Finally, run runs its own command, which naturally triggers the unit test.

  • This can be changed if it is Javamvn test.

We then automatically run unit tests whenever we push code on the main branch, or when we merge code from other branches, which is very convenient.

Same as our local run effect.

Automatic release

Next, consider automatically packaging Docker images and uploading them to Docker Hub. To do this, first create a Dockerfile:

FROM golang:1.15 AS builder
ARG VERSION=0.0.10
WORKDIR /go/src/app
COPY main.go .
RUN go build -o main -ldflags="-X 'main.version=${VERSION}'" main.go

FROM debian:stable-slim
COPY --from=builder /go/src/app/main /go/bin/main
ENV PATH="/go/bin:${PATH}"
CMD ["main"]
Copy the code

Ldflags is used here to pass some parameters into the packager at compile time, such as package time, go version, Git version, and so on.

VERSION is simply passed into the main. VERSION variable so that it can be retrieved at run time.

Docker build-t go-docker:last. Docker run --rm go-docker:0.0.10 0.0.10Copy the code

Then continue to write docker. Yml add automatic packaging docker and push to docker Hub.

deploy:
    runs-on: ubuntu-latest
    needs: test
    if: startsWith(github.ref, 'refs/tags')
    steps:
      - name: Extract Version
        id: version_step
        run: | echo "##[set-output name=version;] VERSION=${GITHUB_REF#$"refs/tags/v"}" echo "##[set-output name=version_tag;] $GITHUB_REPOSITORY:${GITHUB_REF#$"refs/tags/v"}" echo "##[set-output name=latest_tag;] $GITHUB_REPOSITORY:latest"
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: The ${{ secrets.DOCKER_USER_NAME }}
          password: The ${{ secrets.DOCKER_ACCESS_TOKEN }}

      - name: PrepareReg Names
        id: read-docker-image-identifiers
        run: | echo VERSION_TAG=$(echo ${{ steps.version_step.outputs.version_tag }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV echo LASTEST_TAG=$(echo ${{ steps.version_step.outputs.latest_tag }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
      - name: Build and push Docker images
        id: docker_build
        uses: Docker/[email protected]
        with:
          push: true
          tags: | ${{env.VERSION_TAG}} ${{env.LASTEST_TAG}}          build-args: | ${{steps.version_step.outputs.version}}Copy the code

A deploy job is added.

    needs: test
    if: startsWith(github.ref, 'refs/tags')
Copy the code

The running condition is that the single test process of the previous step runs, and the subsequent steps will be triggered only when a new tag is generated.

name: Login to DockerHub

In this step we need to log in to the DockerHub, so first we need to configure the hub’s user_name and access_token in the GitHub project.

Once configured, you can use the variable in the action.

The login action provided by Docker is used here (docker/login-action).

One thing to note is that we need to change the image name to lowercase, otherwise upload will fail, for example, my name J is uppercase, direct upload will report an error.

Therefore, perform this step to convert to lowercase before uploading.

Finally, upload to Docker Hub using these two variables.

In the future, whenever we tag, the Action will automatically perform the test, build, and upload process.

conclusion

GitHub Actions is so flexible that most of the features you need can be found in the Marketplace directly,

For example, you can use SSH to log in to your own server and execute some commands or scripts, which is a lot of imagination.

Use it like building blocks, you can flexibly fulfill your own needs.

Reference links:

How to Build a CI/CD Pipeline with Go, GitHub Actions and Docker