PUSH IMAGE TO GHCR
sudo nerdctl login ghcr.io -u patrick-hermann-sva -p $GITHUB_TOKEN
sudo nerdctl build -t ghcr.io/stuttgart-things/sthings-slides:v2 .
sudo nerdctl push ghcr.io/stuttgart-things/sthings-slides:v2
CREATE PULL REQUEST
gh pr create -t "tekton-test1" -b "added git tasks to taskfile"
CREATE REPOSITORY
gh repo create stuttgart-things/stagetime-operator \
--public \
--add-readme \
--description "stagetime operator" \
--clone \
--license Apache-2.0 \
-g Go
LIST AVAILABLE GITIGNORE TEMPLATES
gh api /gitignore/templates -q ".[]"
MERGE PULL REQUEST
gh pr merge $(gh pr list | grep "^[^#;]" | awk '{print $1}') --auto --rebase --delete-branch
CREATE RELEASE
gh release create {{ .PROJECT }}-{{ .VERSION_NUMBER_PREFIX }}{{ .UPDATED_VERSION_NUMBER }} --notes "released chart artifcact for {{ .PROJECT }}" {{ .PACKAGE }}
DELETE RELEASE
gh release delete {{ .PROJECT }}-{{ .VERSION_NUMBER_PREFIX }}{{ .UPDATED_VERSION_NUMBER }} -y || true
AUTO MERGE/REBASE PR
# GET LATEST PR AND AUTO MERGE + DELETE BRANCH
gh pr merge $(gh pr list | grep "^[^#;]" | awk '{print $1}') --auto --rebase --delete-branch
TEST WORKFLOW
name: ACTIONS RUNNER K8S SMOKE TEST
on:
workflow_dispatch:
jobs:
Smoke:
runs-on: k8s-docs
container: nginx:1.25.2-alpine
steps:
- name: Checkout code
uses: actions/checkout@v4
- run: |
echo "🎉 This job runs on kubernetes!"
cat /etc/os-release
ls -lta
USE OUTPUTS FROM JOBS IN REUSABLE WORKFLOWS
---
name: Build ansible collection
on:
workflow_call:
inputs:
runs-on:
required: true
type: string
outputs:
collection-version:
description: version of ansible collection
value: ${{ jobs.Ansible-Collection-Build.outputs.version }}
artifact-name:
description: name of uploaded ansible collection package
value: ${{ jobs.Ansible-Collection-Build.outputs.artifact }}
jobs:
Ansible-Collection-Build:
outputs:
version: ${{ steps.version.outputs.version }}
artifact: ${{ steps.build.outputs.artifact }}
runs-on: ${{ inputs.runs-on }}
container:
image: ${{ inputs.ansible-image }}
environment: ${{ inputs.environment-name }}
continue-on-error: ${{ inputs.continue-error }}
steps:
- name: Checkout code
id: git
uses: actions/[email protected]
with:
path: source
fetch-depth: "0"
- id: version
run: echo "version=$(yq -r '.version' source/${{ inputs.collection-file }})" >> "$GITHUB_OUTPUT"
shell: bash
---
name: Build Collection
on:
workflow_dispatch:
inputs:
runs-on:
type: string
required: false
default: ghr-deploy-configure-rke-cicd
environment-name:
type: string
required: true
default: k8s
jobs:
Build-Collection:
name: Build Ansible Collection
uses: stuttgart-things/stuttgart-things/.github/workflows/ansible-collection.yaml@main
with:
runs-on: ${{ inputs.runs-on }}
environment-name: ${{ inputs.environment-name }}
continue-error: false
Release-Collection:
name: Release-Collection
needs: Build-Collection
permissions:
contents: write
pull-requests: write
runs-on: ${{ inputs.runs-on }}
environment: ${{ inputs.environment-name }}
container:
image: eu.gcr.io/stuttgart-things/machineshop:v1.7.2
steps:
- name: Download artifact
id: download
uses: actions/[email protected]
with:
name: ${{ inputs.vm-name }}
- name: Release module
uses: ncipollo/[email protected]
with:
name: ${{ needs.Build-Collection.outputs.artifact-name }}
artifacts: ${{ needs.Build-Collection.outputs.artifact-name }}
body: "ansible-collection"
tag: ${{ needs.Build-Collection.outputs.collection-version }}
UPLOAD ARTIFACTS
- name: Upload collection
id: upload
uses: actions/[email protected]
with:
name: ${{ env.COLLECTION_PACKAGE }}
#path: ${{ github.workspace }}/*tar.gz*
path: ${{ env.COLLECTION_PACKAGE_PATH }}
ADD LABEL(S) TO PR
- name: Add please-review label on command in issue comment
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
with:
script: |
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ["please-review"]
})
GITHUB EVENT DATA IN WORKFLOW
#...
- name: Print Title of PR
run: echo The Title of your PR is ${{ github.event.pull_request.title }}
- name: Print branch name
run: echo The branch name from of your PR is ${{ github.event.pull_request.head.ref }}
# ..
SET ENV OUTPUTS
# STEP1
# SET WORKING DIRS AS ENV-VARS
echo "COLLECTION_FILEPATH=source/${{ inputs.collection-file }}" >> $GITHUB_ENV
echo "COLLECTION_ROLES_DIR=$GITHUB_WORKSPACE/$(yq -r ".namespace" source/${{ inputs.collection-file }})/$(yq -r ".name" source/${{ inputs.collection-file }})/roles" >> $GITHUB_ENV
# STEP2
# USE ENV VARS
count_plays=$(yq '.playbooks | keys' ${{ env.COLLECTION_FILEPATH }} | wc -l)
# ..
yq ".playbooks[$COUNTER].name" ${{ env.COLLECTION_FILEPATH }}
GITHUB EVENT TRIGGER
Workflow triggers are events that cause a workflow to run.
- Manually trigger a workflow run
- Configure custom-defined input properties, default input values, and required inputs for the event directly in your workflow
- Access the input values in the inputs context
on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
type: choice
options:
- info
- warning
- debug
tags:
description: 'Test scenario tags'
required: false
type: boolean
environment:
description: 'Environment to run tests against'
type: environment
required: true
jobs:
log-the-inputs:
runs-on: ubuntu-latest
steps:
- run: |
echo "Log level: $LEVEL"
echo "Tags: $TAGS"
echo "Environment: $ENVIRONMENT"
env:
LEVEL: ${{ inputs.logLevel }}
TAGS: ${{ inputs.tags }}
ENVIRONMENT: ${{ inputs.environment }}
- Workflow can be called by another workflow
- Inputs and secrets can be defined, which can be passed from the caller workflow and then used within the called workflow --> The event payload in the called workflow is the same event payload from the calling workflow
on:
workflow_call:
inputs:
config-path:
required: true
type: string
secrets:
envPAT:
required: true
In the reusable workflow, reference the input or secret that you defined in the on
key in the previous step
jobs:
reusable_workflow_job:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/labeler@v4
with:
repo-token: ${{ secrets.envPAT }}
configuration-path: ${{ inputs.config-path }}
K8S WORKFLOW-EXAMPLE
---
name: Build & Verify Terraform Module
on:
workflow_dispatch:
push:
branches:
- "main"
jobs:
Terraform-Validate:
runs-on: arc-runner-scale-set-vault-base-setup
container:
image: hashicorp/terraform:1.6
environment: k8s
continue-on-error: false
steps:
- name: Checkout code
uses: actions/[email protected]
- run: |
terraform init
terraform fmt
terraform validate
DISPATCH/INPUTS/USES EXAMPLE
---
name: Release Terraform
on:
workflow_dispatch:
inputs:
release-tag:
required: true
type: string
release-message:
required: true
type: string
jobs:
release-terraform:
if: github.event.ref == 'refs/heads/main'
name: Valdiate
uses: stuttgart-things/stuttgart-things/.github/workflows/release-terraform.yaml@main
with:
module-name: vsphere-vm
tag-name: "${{ github.event.inputs.release-tag }}"
release-message: "${{ github.event.inputs.release-message }}"
environment-name: k8s
runs-on: arc-runner-scale-set-vsphere-vm
continue-error: false
DISPATCH WORKFLOW W/ INPUT, IF AND NEEDS
---
name: Release-Golang
on:
workflow_dispatch:
inputs:
release-tag:
required: false
type: string
push:
tags:
- '*'
jobs:
Create-Git-Tag:
name: Release Golang
uses: stuttgart-things/stuttgart-things/.github/workflows/git-tag.yaml@main
if: github.ref_type != 'tag' && github.event.inputs.release-tag != ''
with:
tag-name: ${{ github.event.inputs.release-tag }}
environment-name: k8s
runs-on: arc-runner-scale-set-kaeffken
alpine-version: 3.19.0
continue-error: false
secrets: inherit
Release-Golang-Binaries:
name: Release Golang
uses: stuttgart-things/stuttgart-things/.github/workflows/release-golang.yaml@main
if: always()
needs: Create-Git-Tag
with:
module-name: kaeffken
environment-name: k8s
runs-on: arc-runner-scale-set-kaeffken
goreleaser-version: v1.23.0
golang-version: "1.21.5"
secrets: inherit
WORKFLOW REPOSITORY (STORES THE WORKFLOW)
---
name: Build & Verify Terraform Module
on:
workflow_call:
inputs:
runs-on:
required: true
type: string
terraform-version:
default: 1.6
required: true
type: string
tflint-version:
default: v0.50.0
required: true
type: string
environment-name:
default: k8s
required: true
type: string
continue-error:
default: false
required: true
type: boolean
jobs:
Terraform-Validate:
runs-on: ${{ inputs.runs-on }}
container:
image: hashicorp/terraform:${{ inputs.terraform-version }}
environment: ${{ inputs.environment-name }}
continue-on-error: ${{ inputs.continue-error }}
steps:
- name: Checkout code
uses: actions/[email protected]
- run: |
terraform init
terraform fmt
terraform validate
Terraform-Lint:
runs-on: arc-runner-scale-set-vault-base-setup
container:
image: ghcr.io/terraform-linters/tflint:${{ inputs.tflint-version }}
environment: k8s
continue-on-error: false
steps:
- name: Checkout code
uses: actions/[email protected]
- run: |
tflint --recursive
CODE REPOSITORY (IMPORTS THE WORKFLOW)
name: Terraform
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
jobs:
validate-terraform:
if: github.event.ref == 'refs/heads/main'
name: Valdiate
uses: stuttgart-things/stuttgart-things/.github/workflows/validate-terraform.yaml@main
with:
environment-name: k8s
runs-on: arc-runner-scale-set-flux2-cluster-bootstrap
terraform-version: 1.6
tflint-version: v0.50.0
continue-error: false
AUTHENTICATING WITH GITHUB APP GENERATED TOKENS
-
Set GitHub App name.
-
Set Homepage URL to anything you like, such as your GitHub profile page.
-
Uncheck Active under Webhook. You do not need to enter a Webhook URL.
-
Under Repository permissions: Contents select Access: Read & write.
-
Under Repository permissions: Pull requests select Access: Read & write.
-
Under Organization permissions: Members select Access: Read-only.
-
Create a Private key from the App settings page and store it securely.
-
Install the App on any repository where workflows will run requiring tokens.
-
Set secrets on your repository containing the GitHub App ID, and the private key you created in step 2. e.g. APP_ID, APP_PRIVATE_KEY.
-
The following example workflow shows how to use tibdex/github-app-token to generate a token for use with this action.
steps:
- uses: actions/checkout@v4
- uses: tibdex/github-app-token@v1
id: generate-token
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ steps.generate-token.outputs.token }}
SET ENV VARS DURING JOB
# SET ENV VAR
- name: Set labels for pull request
id: set-build-label
run: |
if [[ "${{ inputs.build-engine }}" == "gh-workflows" ]]; then
echo "LABEL=packer" >> $GITHUB_ENV
fi
# USE ENV VAR
- name: Create Pull Request for packer config
id: pr
uses: peter-evans/[email protected]
with:
branch: ${{ inputs.os-version }}-${{ inputs.lab }}-${{ inputs.cloud }}
labels: |
${{ env.LABEL }}
MULTIPLE CHOICE INPUTS (DISPATCH)
on:
workflow_dispatch:
inputs:
name:
type: choice
description: Who to greet
options:
- maypayne
- scorseese
- deniro
jobs:
greet:
runs-on: ubuntu-latest
steps:
- name: Send greeting
run: echo ${{ github.event.inputs.name }}"
DEFAULTS FOR INPUTS
# FOR EXAMPLE WHEN USING WORFLOW DISPATCH AND GIT TRIGGERS TO SET A DEFAULT VALUE
- name: Set default value
id: defaultname
run: |
USER_INPUT=${{ github.event.inputs.name }}
echo "value=${USER_INPUT:-"Octocat"}" >> "$GITHUB_OUTPUT"
- name: Do something with it
run: |
name="${{ steps.defaultname.outputs.value }}"
echo "Name: $name"
USE INLINE GITHUB SCRIPT FOR SETTING A GIT TAG
name: Create-Git-Tag
on:
workflow_dispatch:
inputs:
tag-name:
required: true
type: string
jobs:
Create-Git-Tag:
permissions:
contents: write
runs-on: arc-runner-scale-set-kaeffken
container:
image: alpine:3.19.0
environment: k8s
steps:
- name: Create Tag
uses: actions/github-script@v6
with:
script: |
github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'refs/tags/v${{ inputs.tag-name }}',
sha: context.sha
})
DECLARE GLOBAL VARIABLES
#..
env:
TEMPLATE_DIR: machineShop/templates
DESTINATION_DIR: clusters
jobs:
#..
steps:
#..
- run: |
machineShop render \
--source local \
--template ${TEMPLATE_DIR}/packer-${{ inputs.os-version }}-${{ inputs.cloud }}.yaml \
--values "provisioning=${{ inputs.ansible-provisioning }}, date=$(date '+%Y-%m-%d-%H-%M-%S'), dateShort=$(date '+%Y-%m-%d'), env=${{ inputs.env }}" \
--output file \
--destination ${DESTINATION_DIR}/${{ inputs.env }}/${{ inputs.cloud }}/bootstrap/packer-${{ inputs.os-version }}-${{ inputs.ansible-provisioning }}.yaml
#..
HELMFILE ACTION
on:
workflow_call:
inputs:
environment-name:
required: true
type: string
branch-name:
required: true
type: string
jobs:
build-helm:
environment: ${{ inputs.environment-name }}
steps:
- name: CHECKOUT GIT
uses: actions/checkout@v4
- name: SETUP HELMFILE
uses: mamezou-tech/[email protected]
EXAMPLE CONFIG
cat ~/.gitconfig
[url "https://${USERNAME}:${PASSWORD}@codehub.sva.de"]
insteadOf = https://codehub.sva.de
[user]
name = Patrick Hermann
email = [email protected]
[url "https://${USERNAME}:${PASSWORD}@github.com/stuttgart-things/"]
insteadOf = https://github.com/stuttgart-things/
[user]
name = Patrick Hermann
email = [email protected]
CREATE HUGO SITE
export SITE_NAME=BLOG
nerdctl run --user $(id -u):$(id -g) --rm -v $(pwd):/src klakegg/hugo:0.107.0-ext-alpine new site ${SITE_NAME} > --format yaml
CLONE THEME + CREATE CONFIG
export SITE_NAME=BLOG
cd ${SITE_NAME}
git clone https://github.com/alex-shpak/hugo-book ${SITE_NAME}/themes/hugo-book
cat <<EOF > ${SITE_NAME}/config.yaml
baseURL: http://example.org/
languageCode: en-us
title: My New Hugo Site
theme: hugo-book
EOF
RUN HUGO SITE
export SITE_NAME=BLOG
# EXAMPLE SITE
cp -R themes/hugo-book/exampleSite/content.en/* ./content
nerdctl run --user $(id -u):$(id -g) --rm -p 1315:1313 -v $(pwd)/blog:/src klakegg/hugo:0.107.0-ext-alpine server
BUILD STATIC CONTENT
nerdctl run --user $(id -u):$(id -g) --rm -p 1315:1313 -v $(pwd):/src klakegg/hugo:0.107.0-ext-alpine --verbose --destination public
RUN/VIEW STATIC CONTENT W/ NGINX
sudo nerdctl run -it --rm -p 8080:80 --name web -v public/:/usr/share/nginx/html nginx
YAML LINT
nerdctl run -it -v ./docs:/manifests cytopia/yamllint -- /manifests
DEPLOY GHA SCALE SET CONTROLLER
helm upgrade --install arc \
--namespace arc-systems \
--create-namespace \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
DEPLOY OPENEBS
helm repo add openebs https://openebs.github.io/charts
helm install openebs openebs/openebs --version 3.9.0 -n openebs --create-namespace
DEPLOY K8S AUTOSCALINGRUNNERSET
cat <<EOF > ./k8s-arc-scale-values.yaml
containerMode:
type: kubernetes
kubernetesModeWorkVolumeClaim:
accessModes: ["ReadWriteOnce"]
storageClassName: openebs-hostpath
resources:
requests:
storage: 1Gi
template:
spec:
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
value: "false"
EOF
GITHUB_CONFIG_URL="https://github.com/stuttgart-things/docs"
GITHUB_PAT="<$GITHUB_PAT>"
helm upgrade --install k8s-docs \
--namespace arc-runners \
--create-namespace \
--set githubConfigUrl="${GITHUB_CONFIG_URL}" \
--set githubConfigSecret.github_token="${GITHUB_PAT}" \
--values ./k8s-arc-scale-values.yaml \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --version 0.6.1