Skip to content

MormonJesus69420 is deploying the project #411

MormonJesus69420 is deploying the project

MormonJesus69420 is deploying the project #411

# Name of the workflow and an action title to display in the GitHub UI
name: Deploy Project
run-name: ${{ github.actor }} is deploying the project
# Decides when the workflow gets triggered, this is a "coarse" definition for whole workflow
# Jobs can refine it further or use the defaults defined here
# List of all events that can be used for triggering workflows:
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
on:
# Run on push to main branch and tags in the form v*.*.* eg.: v1.0.0
push:
branches:
- main
tags:
- v*.*.*
# Runs every time a pull request is created, updated, etc. can use "types" to run only on select PR activities
pull_request:
# Used to make sure that only one workflow in the specified group runs at the same time
concurrency:
# Define concurrency group which is then used to determine duplicate workflow runs
# The second property uses fallback values since not every run is a PR run
group: ${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}
cancel-in-progress: true
# Modify access granted to the workflow in the GITHUB_TOKEN
# Mainly used here to give checks a write permission to allow a test run reporter to publish test results
permissions:
contents: read
actions: read
checks: write # See the [[test-report-publisher]] step for explanation why this is needed
# List of jobs that this workflow executes, each job can run on different runners, have different steps, etc.
jobs:
# Unique identifier for this job, make sure it is unique, you can use "name" property to give it a more descriptive name
test-project:
# This name is displayed in the GitHub UI when the job is running
name: Build and Test the Project
# Defines what runner to run this job on, if you want you can use an array of tags/identifiers to match the runner name
# For example this can be written as [self-hosted, linux] and only runner matching all of these values will run it
runs-on: self-hosted-linux
# List of steps that this job executes in sequential order, any changes done in one step will carry over to others
# Be mindful of that when making changes to files
steps:
# Simple step which merely checks out the repository to the runner, making it available for other steps
- name: Checkout
# Specifies that this step should run a pre-defined action, meaning an action that was made by someone else or exists elsewhere
# In this case the provided identifier is a reference to a repository in: https://github.com/actions/checkout and the version is set tov4
uses: actions/checkout@v4
# This steps installs specified Java JDK
- name: Setup Java JDK
uses: actions/setup-java@v4
# Settings/Inputs/Parameters for the action
with:
# What JDK distribution to download and use
distribution: temurin # If you have no good reasons to choose something else, go with Temurin distribution
java-version: 21
architecture: x64
# Sets up caching and restoring of dependencies for the specified package manager
# NB! If you decide to use a non-standard path for package repositories you need to set up caching yourself
# In that case use the "@actions/cache" action
cache: maven
# Since the self hosted runner does not come with Maven, it must be installed manually
# Same for git, it is needed to upload the test results, hence why repo is initialized using "git init"
# Lastly gettext provides envsubst which is used in the [[verify-the-project]] step to replace env variables
- name: Install Maven and Initialize Repo
# Map of environment variables available for this step only, you can define it on job or workflow level too
env:
MAVEN_VERSION: 3.9.7 # So we can easily change the Maven version
run: | # Pipe allows to make the script multiline, if you need to run only one command you can skip it
sudo apt-get update -y
sudo apt-get install wget git gettext -y
wget https://downloads.apache.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz
sudo tar xzf apache-maven-$MAVEN_VERSION-bin.tar.gz -C /opt
sudo ln -s /opt/apache-maven-$MAVEN_VERSION/bin/mvn /usr/local/bin/mvn
echo "PATH=/opt/apache-maven-$MAVEN_VERSION/bin:$PATH" >> $GITHUB_ENV
git init
mvn -v
# This step imports secrets from Vault, it is recommended to use Vault as it allows checking and editing the secrets
# GitHub does not permit to check secret value or re-use the secrets
# Speak with Plattform team to set up a namespace if needed
# They should also create an approle "user" which allows fetching the secrets within a GitHub action
#
# The url must be in form: https://<URL>, while IDs are UUIDs
# When providing path to the secret you need to include "/data" after namespace and before the secret name
- name: Import Secrets
uses: hashicorp/vault-action@v3
with:
url: ${{ secrets.VAULT_URL }}
method: approle # Method used to authenticate against Vault
roleId: ${{ secrets.VAULT_ROLE_ID }}
secretId: ${{ secrets.VAULT_SECRET_ID }}
secrets: secret/v1/application/k8s/mlt/data/proxy * # The "*" at the end is a wildcard, it will get all secrets in the path
# This step actually builds, tests, and verifies the project using Maven #[[verify-the-project]]
# "envsubst" supplies proxy settings for Maven, proxy host address must be an IP address, not a URL
- name: Verify the Project
# Replace tags in settings.xml with values from environment and save it to a new file, then use it when running Maven
run: |
envsubst < .m2/settings.xml > .m2/replaced.xml
mvn -B -e -s .m2/replaced.xml verify
# This step uses the test-reporter action to publish test results in the workflow run #[[test-report-publisher]]
# It looks for any file named "TEST-...xml" in the project and uses it to publish the test results
# The job name in GitHub with the test results is "JUnit Test Results"
- name: Publish Test Report
uses: dorny/test-reporter@v1
# If defines conditions that need to be fulfilled to run this step, in this case this step will always run
# That is because the report should be published, even if the tests failed
if: always()
with:
name: JUnit Test Results # Name for the report
path: ./**/TEST-*.xml # Where to look for report files, any file named "TEST-...xml" anywhere in the project
reporter: java-junit # What reporter to use, since this project uses JUnit, the reporter is "java-junit"
fail-on-error: true # Fail this step if there are test errors
fail-on-empty: true # Fail this step if no test results were found
# This step uploads the JAR file as an artifact which can then be used in other jobs
- name: Upload the JAR File
uses: actions/upload-artifact@v4
with:
name: packaged-project # Artifact ID, used to reference the artifact in other jobs when downloading it #[[packaged-project-id]]
path: target/wls.jar # File(s) to include, the path is relative to the repository root
# Set "project.build.finalName --> ${project.artifactId}" in pom.xml to drop the version suffix
if-no-files-found: error # Fail if artifact is not found
overwrite: true # Allow overwriting of previous artifacts
# This job build a Docker image with relevant tags and labels, and publish it in Harbor
publish-image:
name: Build and Publish the Docker Image
# Defines that test-project job must finish successfully first, before this one can run
needs: test-project
# The if statement limits the job to only run if action was triggered on main branch or one of the tags
if: github.ref == "refs/heads/main" || startsWith(github.ref, "refs/tags/v")

Check failure on line 137 in .github/workflows/deploy-project.yaml

View workflow run for this annotation

GitHub Actions / Deploy Project

Invalid workflow file

The workflow is not valid. .github/workflows/deploy-project.yaml (Line: 137, Col: 9): Unexpected symbol: '"refs/heads/main"'. Located at position 15 within expression: github.ref == "refs/heads/main" || startsWith(github.ref, "refs/tags/v") .github/workflows/deploy-project.yaml (Line: 211, Col: 9): Unexpected symbol: '"refs/heads/main"'. Located at position 15 within expression: github.ref == "refs/heads/main"
runs-on: self-hosted-linux
# Outputs allows a job to output values that can be picked up by _downstream_ jobs that _depend_ on this job
outputs:
# The metadata step produces an image name that is then used in deployment jobs
# Gets the value from the "meta" step: [[meta-step-id]]
image-name: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout
uses: actions/checkout@v4
# Sets up a Docker Build action which is then used to produce the Docker image
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
# See this step description in the first job
- name: Import Secrets
uses: hashicorp/vault-action@v3
with:
url: ${{ secrets.VAULT_URL }}
method: approle
roleId: ${{ secrets.VAULT_ROLE_ID }}
secretId: ${{ secrets.VAULT_SECRET_ID }}
secrets: secret/v1/application/k8s/mlt/data/harbor *
# Simple action that authenticates against the NLB's Harbor instance
# The url must be in form: https://<URL>, username and password should be for the GitHub robot user
# Ask Plattform team to create a robot user with access to your project(s) in Harbor registry
- name: Log in to Harbor Registry
uses: docker/login-action@v3
with:
registry: ${{ env.HARBOR_URL }}
username: ${{ env.HARBOR_USERNAME }}
password: ${{ env.HARBOR_PASSWORD }}
- name: Extract Metadata for Docker
# Give this step a unique ID for referencing it elsewhere, here it is used to get the value of tags #[[meta-step-id]]
id: meta
uses: docker/metadata-action@v5
with:
# Define to use for tags, can be multiple values if needed
images: harbor.nb.no/mlt/wls
# Defines list of tag types to use for generating the metadata
# the semver type uses GitHub tag in semver form and turns it into a proper tag for the image (semantic versioning: v4.2.0 -> 4.2.0)
# the ref type bases its version either on branch or PR event and generates the tag for the image based on that (branch -> branch-name, pr -> pr-number)
tags: |
type=semver,pattern={{version}}
type=ref,event=branch
type=ref,event=pr
# Downloads previously uploaded artifact with provided id/name, see [[packaged-project-id]] to see how it was defined
- name: Download the JAR File
uses: actions/download-artifact@v4
with:
name: packaged-project
# Builds and publishes the image in Harbor
- name: Build the Docker Image
uses: docker/build-push-action@v5
with:
push: true # Makes the action push image to Harbor, equivalent to "--output-type=registry"
context: . # Build context, makes the build process use actual files in the runner instead of using files from GitHub
file: ./docker/Dockerfile # Override the path to the Dockerfile, since this project has it in the docker folder
tags: ${{ steps.meta.outputs.tags }} # Set tags for the image using output from the meta step
labels: ${{ steps.meta.outputs.labels }} # Set labels for the image using output from the meta step
# Deploys the image to kubernetes stage environment
deploy-to-stage:
name: Deploy to Kubernetes Stage
needs: publish-image
# Runs only on main branch
# Can be changed to also run on tags, to ensure that stage & prod use same image after a new version release
if: github.ref == "refs/heads/main"
runs-on: self-hosted-linux
# Defines what environment this job references, this allows for setting deployment protections in the project
# Allows requiring a number of reviewers or specific reviewers, or allow only specific branches or tags
# It also permits setting specific secrets and variables
environment: stage
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Import Secrets
uses: hashicorp/vault-action@v3
with:
url: ${{ secrets.VAULT_URL }}
method: approle
roleId: ${{ secrets.VAULT_ROLE_ID }}
secretId: ${{ secrets.VAULT_SECRET_ID }}
secrets: secret/v1/application/k8s/mlt/data/k8s-stage *
# Installs and prepares a local kubectl instance
- name: Setup Kubectl
uses: azure/setup-kubectl@v4
# Script that sets some needed variables in deployment file, and then configures kubectl for deploying to stage
# Script itself is rather generic, especially for simple deployments, so it can be easily re-used
# Just make sure to set correct context and namespace when used in other projects
#
# K8S_HOST_URL - URL pointing where to host the app, there are two default options for both stage and prod
# K8S_STAGE_SERVER - URL to the stage server in form https://<IP_ADDRESS>:<PORT>
# K8S_STAGE_NB_NO_CA - certificate auth data, get it from the Plattform team
# K8S_STAGE_USER - name of the robot user that can deploy to the given namespace, get it from the Plattform team
# K8S_STAGE_NB_NO_TOKEN - credentials token for the robot user, get it from the Plattform team
- name: Deploy to Stage
run: |
echo "Deploying to stage: ${{ needs.publish-image.outputs.image-name }}"
sed -i "s|<image_name>|${{ needs.publish-image.outputs.image-name }}|g" k8s/stage/wls.yml
sed -i "s|<host_url>|${{ env.K8S_HOST_URL }}|g" k8s/stage/wls.yml
kubectl config set-cluster stagecl --server=${{ env.K8S_STAGE_SERVER }}
kubectl config set clusters.stagecl.certificate-authority-data ${{ env.K8S_STAGE_NB_NO_CA }}
kubectl config set-credentials ${{ env.K8S_STAGE_USER }} --token=${{ env.K8S_STAGE_NB_NO_TOKEN }}
kubectl config set-context mlt --cluster=stagecl --user=${{ env.K8S_STAGE_USER }} --namespace=mlt
kubectl config use-context mlt
kubectl config view
kubectl version
kubectl apply -f k8s/stage/wls.yml
kubectl rollout restart deploy/wls
deploy-to-prod:
name: Deploy to Kubernetes Prod
needs: publish-image
# Runs only on tags
if: startsWith(github.event.ref,"refs/tags/v")
runs-on: self-hosted-linux
environment: prod
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Import Secrets
uses: hashicorp/vault-action@v3
with:
url: ${{ secrets.VAULT_URL }}
method: approle
roleId: ${{ secrets.VAULT_ROLE_ID }}
secretId: ${{ secrets.VAULT_SECRET_ID }}
secrets: secret/v1/application/k8s/mlt/data/k8s-prod *
- name: Setup Kubectl
uses: azure/setup-kubectl@v4
# Same concept as in stage deployment, just using production values
- name: Deploy to Prod
run: |
echo "Deploying to prod:${{ needs.publish-image.outputs.image-name }}"
sed -i "s|<image_name>|${{ needs.publish-image.outputs.image-name }}|g" k8s/prod/wls.yml
sed -i "s|<host_url>|${{ env.K8S_HOST_URL }}|g" k8s/prod/wls.yml
kubectl config set-cluster prodcl --server=${{ env.K8S_PROD_SERVER }}
kubectl config set clusters.prodcl.certificate-authority-data ${{ env.K8S_PROD_NB_NO_CA }}
kubectl config set-credentials ${{ env.K8S_PROD_USER }} --token=${{ env.K8S_PROD_NB_NO_TOKEN }}
kubectl config set-context mlt --cluster=prodcl --user=${{ env.K8S_PROD_USER }} --namespace=mlt
kubectl config use-context mlt
kubectl config view
kubectl version
kubectl apply -f k8s/prod/wls.yml
kubectl rollout restart deploy/wls