GitHub Actions workflow for a Kotlin Spring app to GCP
Tags: cicd, kotlin, springboot, gcp
Published: 2023-05-25 16:57:22

If you, like I, are struggling to find a simple way to get a Kotlin spring boot application built and deployed to Google Cloud Platform (GCP), this might be a solution you can try! 

I found it the easiest to opt in for using Google Artifact Registry (GAR), Google Cloud Run, and obviously in that case, Docker. 

The app itself was built in Kotlin with Gradle, but should be practically the same if you're running a maven architecture and using Java. 

Using the following Dockerfile:

```dockerfile
FROM openjdk
COPY build/libs/**-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

```
This was the steps I needed to take in order to get it up and spinning in the cloud. 

First and foremost, you need to set up a [Service Account](https://console.cloud.google.com/iam-admin/serviceaccounts) in GCP IAM, with the principals `Service Account User`, `Artifact Registry Service Agent`, `Cloud Run Service Agent` and `roles/artifactregistry.createOnPushRepoAdmin`. Or at least trial and error lead me to those. 

You'll also have to generate a key, there's a comment in the workflow about it! :wink:

After that, using the following GitHub Actions workflow was the one that finally worked for me: 

```yml
name: Build and deploy JAR to GCP

on:
  push:
    branches:
      - main
    paths-ignore:
      - 'README.md'
      
env:
  IMAGE_URL: {region}/{project-id}/{repo}/{app}:${{ github.sha }}

# replace region with your region, ex: europe-north1-docker.pkg.dev
# also replace all project-id etc to match your situation. 


jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - id: 'auth'
        name: Authenticate GCP
        uses: google-github-actions/auth@v1
        with:
          credentials_json: '${{ secrets.GCP_SA_KEY }}'
          # Generated from IAM > ServiceAccounts > Actions > Keys > ADD KEYS > JSON. 

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v1
      - name: Use gcloud CLI
        run: gcloud info # Not requred, but can give you hints in the workflow if something goes wrong

      - name: Configure docker
        run: gcloud auth configure-docker {region} #Replace with your region

      - name: Set up Java version
        uses: actions/setup-java@v1
        with:
          java-version: '17'
      - name: Run tests
        run: ./gradlew test 
# you can replace with `mvn clean test` for maven
      - name: Build jar
        if: success() # only runs if all tests pass
        run: ./gradlew bootJar # mvn package work just fine for maven

      - name: Docker Build
        run: docker build -t $IMAGE_URL .
      - name: Docker Push
        run: docker push $IMAGE_URL

      - name: Update Cloud Run service
        uses: google-github-actions/deploy-cloudrun@v1
        with:
          service: {app} # same as the app in the $IMAGE_URL
          image: ${{ env.IMAGE_URL }}  
```

Of course you can also test and build the application before configuring docker and GCP, and the order is not super important. The only really important order is that your `- uses: actions/checkout@v3` is _before_ 
```yml
- id: 'auth'
  name: Authenticate GCP
  uses: google-github-actions/auth@v1
```
Else, it will not work. 

Hope this helps you / anyone along their way in the CI/CD ~~nightmare~~ happyfuntimes.