Skip to content

Commit

Permalink
chore(ci): build-test pipeline & release prebuilt images (#3)
Browse files Browse the repository at this point in the history
* chore(ci): init mage build & test pipeline

* chore(ci): mage check - remove GOPRIVATE check, world-engine repo no longer private

* chore(ci): ci remove unused registry variable

* chore(ci): mage check - fix unused import

* chore(ci): prep image release to container registry

* chore(ci): fix workflow definition typo

* chore(ci): image release to github container registry

* chore(ci): image release - fix env var

* chore(ci): image release - fix push command

* chore(ci): image release - fix env ref

* chore(ci): image release - released to new GCP Artifact Registry

* chore(ci): image release - fix local image path

* chore(ci): build - cache & permissions

* chore(ci): docker-compose-prebuilt & README

* chore(ci): compressed local images

* chore(ci): dockerfile - use multistage docker build for smaller image size

* chore(ci): conditional if for main/prod branch
  • Loading branch information
heronimus authored Aug 31, 2023
1 parent 30ebd30 commit d51e331
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 18 deletions.
143 changes: 143 additions & 0 deletions .github/workflows/backend-mage-pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
name: template-mage-pipeline

## workflow will trigger on below condition,
## except image release that have jobs condition to trigger only on tagging
on:
pull_request:
branches:
- main
push:
branches:
- main
tags:
- 'v*.*.*'

env:
REGISTRY_URL: us-docker.pkg.dev

jobs:
mage-build-test:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
matrix:
go-version: [1.20.x]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- uses: actions/cache@v3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Mage - check
uses: magefile/mage-action@v2
with:
version: latest
args: check
- name: Mage - build & test
uses: magefile/mage-action@v2
with:
version: latest
args: test
- name: Docker show build images
run: |
docker image ls -a | grep starter-game-template
- name: Docker save local build images
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main'
run: |
docker save ${{ github.event.repository.name }}-nakama:latest | gzip > /tmp/${{ github.event.repository.name }}-nakama-latest.tar.gz
docker save ${{ github.event.repository.name }}-cardinal:latest | gzip > /tmp/${{ github.event.repository.name }}-cardinal-latest.tar.gz
docker save ${{ github.event.repository.name }}-testsuite:latest | gzip > /tmp/${{ github.event.repository.name }}-testsuite-latest.tar.gz
- name: Upload local build images to temporary artifact
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v3
with:
name: buildimage
path: /tmp/starter-game-template-*.tar.gz
images-release:
runs-on: ubuntu-latest
needs: mage-build-test
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main'
defaults:
run:
shell: bash
# Add "id-token" with the intended permissions.
permissions:
contents: 'read'
id-token: 'write'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Download local build images artifact
uses: actions/download-artifact@v3
with:
name: buildimage
path: /tmp/
- name: Load image and show build images
run: |
docker load --input /tmp/${{ github.event.repository.name }}-nakama-latest.tar.gz
docker load --input /tmp/${{ github.event.repository.name }}-cardinal-latest.tar.gz
docker load --input /tmp/${{ github.event.repository.name }}-testsuite-latest.tar.gz
docker image ls -a | grep starter-game-template
- name: GCP auth
id: auth
uses: google-github-actions/auth@v1
with:
workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}
- name: GCP - Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v1
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
- name: Docker - auth to artifact registry
run: |
gcloud auth configure-docker ${{ env.REGISTRY_URL }}
- name: Push image
run: |
IMAGE_ID_NAKAMA=${{ env.REGISTRY_URL }}/${{ github.repository_owner }}/${{ github.event.repository.name }}/nakama
IMAGE_ID_NAKAMA=$(echo $IMAGE_ID_NAKAMA | tr '[A-Z]' '[a-z]')
IMAGE_ID_CARDINAL=${{ env.REGISTRY_URL }}/${{ github.repository_owner }}/${{ github.event.repository.name }}/cardinal
IMAGE_ID_CARDINAL=$(echo $IMAGE_ID_CARDINAL | tr '[A-Z]' '[a-z]')
IMAGE_ID_TESTSUITE=${{ env.REGISTRY_URL }}/${{ github.repository_owner }}/${{ github.event.repository.name }}/testsuite
IMAGE_ID_TESTSUITE=$(echo $IMAGE_ID_TESTSUITE | tr '[A-Z]' '[a-z]')
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
[ "$VERSION" == "main" ] && VERSION=latest
[ "$VERSION" == "merge" ] && VERSION=latest
docker tag ${{ github.event.repository.name }}-nakama:latest $IMAGE_ID_NAKAMA:$VERSION
docker tag ${{ github.event.repository.name }}-cardinal:latest $IMAGE_ID_CARDINAL:$VERSION
docker tag ${{ github.event.repository.name }}-testsuite:latest $IMAGE_ID_TESTSUITE:$VERSION
docker push $IMAGE_ID_NAKAMA:$VERSION
docker push $IMAGE_ID_CARDINAL:$VERSION
docker push $IMAGE_ID_TESTSUITE:$VERSION
artifact-cleanup:
runs-on: ubuntu-latest
needs: [
mage-build-test,
images-release
]
if: always()
steps:
- name: Remove local build image artifact
uses: geekyeggo/delete-artifact@v2
with:
name: buildimage
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@ Alternatively, killing the `mage start` process will also stop Nakama and Cardin
Note, for now, if any Cardinal endpoints have been added or removed Nakama must be relaunched (via `mage stop` and `mage start`).
We will add a future to hot reload this in the future.

# Running with the prebuilt Docker Images

Prerequisites:
- Docker installed

Docker Images Container Registry URLs:
- Cardinal: `us-docker.pkg.dev/argus-labs/starter-game-template/cardinal:<latest/tag_version>`
- Nakama: `us-docker.pkg.dev/argus-labs/starter-game-template/nakama:<latest/tag_version>`


To start the starter-game-template Nakama and Cardinal with prebuilt Docker Images:

```bash
docker compose -f docker-compose-prebuilt.yml up --detach --wait
```

To check the services status & logs:

```bash
docker compose -f docker-compose-prebuilt.yml ps
docker compose -f docker-compose-prebuilt.yml logs
```

To stop Nakama and Cardinal:
```bash
docker compose -f docker-compose-prebuilt.yml down
```

# Verify the Server is Running

Visit `localhost:7351` in a web browser to access Nakama. For local development, use `admin:password` as your login
Expand Down
5 changes: 4 additions & 1 deletion cardinal/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.20
FROM golang:1.20 AS builder

WORKDIR /usr/src/app

Expand All @@ -7,6 +7,9 @@ copy vendor vendor/

RUN go build -v -o /usr/local/bin/app

FROM ubuntu:22.04
COPY --from=builder /usr/local/bin/app /usr/local/bin/

CMD ["app"]


74 changes: 74 additions & 0 deletions docker-compose-prebuilt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
version: "3"
services:
postgres:
command: postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all
environment:
- POSTGRES_DB=nakama
- POSTGRES_PASSWORD=localdb
expose:
- "5432"
image: postgres:12.2-alpine
ports:
- "5432:5432"
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres", "-d", "nakama"]
interval: 3s
timeout: 3s
retries: 5
volumes:
- data:/var/lib/postgresql/data
redis: # This doesn't have the correct persistence settings. Don't use on for prod.
image: redis:latest
command: redis-server # TODO: This runs without password. Don't use for prod.
expose:
- "6379"
ports:
- "6379:6379"
restart: always
cardinal:
image: us-docker.pkg.dev/argus-labs/starter-game-template/cardinal:${STARTER_VERSION:-latest}
restart: unless-stopped
depends_on:
- redis
expose:
- "3333"
ports:
- "3333:3333"
environment:
- CARDINAL_PORT=3333
- REDIS_ADDR=redis:6379
- REDIS_MODE=normal
nakama:
image: us-docker.pkg.dev/argus-labs/starter-game-template/nakama:${STARTER_VERSION:-latest}
restart: unless-stopped
depends_on:
- postgres
- cardinal
environment:
- CARDINAL_ADDR=${CARDINAL_ADDR:-http://cardinal:3333}
- CARDINAL_NAMESPACE=0
entrypoint:
- "/bin/sh"
- "-ecx"
- >
/nakama/nakama migrate up --database.address postgres:localdb@postgres:5432/nakama &&
exec /nakama/nakama --config /nakama/data/local.yml --database.address postgres:localdb@postgres:5432/nakama
extra_hosts:
- "host.docker.internal:host-gateway"
expose:
- "7349"
- "7350"
- "7351"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7350/"]
interval: 10s
timeout: 5s
retries: 5
links:
- "postgres:db"
ports:
- "7349:7349"
- "7350:7350"
- "7351:7351"
volumes:
data:
17 changes: 0 additions & 17 deletions magefiles/prereq.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,10 @@ import (
"bytes"
"errors"
"fmt"
"strings"

"github.com/magefile/mage/sh"
)

const (
goprivateEnv = "GOPRIVATE"
goprivateURLArgusLabs = "github.com/argus-labs"
goprivateURLWorldEngine = goprivateURLArgusLabs + "/world-engine"
)

// allOutput runs the command and returns the stdout and stderr. Nothing is printed to stdout and stderr.
func allOutput(cmd string, args ...string) (out string, err error) {
outWriter, errWriter := &bytes.Buffer{}, &bytes.Buffer{}
Expand Down Expand Up @@ -49,16 +42,6 @@ func checkPrereq(verbose bool) error {
}
}

check(goprivateEnv, func() error {
out, err := allOutput("go", "env", goprivateEnv)
if err != nil {
return fmt.Errorf("problem getting env variable %q", goprivateEnv)
} else if !strings.Contains(out, goprivateURLArgusLabs) {
return fmt.Errorf("the env variable %q should contain %q or %q", goprivateEnv, goprivateURLArgusLabs, goprivateURLWorldEngine)
}
return nil
})

check("Docker", func() error {
if _, err := allOutput("docker", "-v"); err != nil {
return fmt.Errorf("docker is not installed: %v", err)
Expand Down

0 comments on commit d51e331

Please sign in to comment.