Skip to content

Commit

Permalink
Add new versions.json and update build and release workflow to use it (
Browse files Browse the repository at this point in the history
…#3)

* Add new versions.json and update build and release workflow to use it

* Debug logging

* Correct function name

* Change to pass matrix json

* Remove raw for tools object

* Escape tools json

* Remove escaping

* Fix quoting

* confirmation step

* Stop quoting the

* Use double quotes

* add r to revision number and fix all versions tag

* Add deprecations and add naming to all versions tag

* Clean up some logic for getting the k8s version

* Use env vars for image paths

* fix env vars

* Use correct variable

* Update Readme

* Only run on versions.json change

* Change revision to be random 4 char string

* Only apply revision to main builds

* change to 6 char random revision

* Update readme

* Change to revision hash driven from versions.json

* Update readme

* Update deprecations node

* Fix revision hash not being passed through
  • Loading branch information
APErebus authored Oct 1, 2024
1 parent 6fe9596 commit 71e4322
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 62 deletions.
132 changes: 89 additions & 43 deletions .github/workflows/build-and-publish-container-image.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,65 @@
name: Build and Push Container Image
run-name: "Build and Push Image: Kubectl ${{ inputs.kubectl-version }}, Helm ${{ inputs.helm-version }}, Powershell ${{ inputs.powershell-version }}"

on:
workflow_dispatch:
inputs:
kubectl-version:
required: true
type: string
default: "1.30.5"
helm-version:
required: true
type: string
default: "3.16.1"
powershell-version:
required: true
type: string
default: "7.4.5"
tag-as-latest:
description: "(Main only) Tag the image as latest - kubectl 1.30.x only"
required: true
type: boolean
default: false
pull_request:
paths:
- 'versions.json'
push:
branches:
- main
paths:
- 'versions.json'

env:
ArtifactoryImagePath: "${{ secrets.ARTIFACTORY_DOCKER_REPO_HOSTNAME }}/octopusdeploy/kubernetes-agent-tools-base"
DockerHubImagePath: "octopusdeploy/kubernetes-agent-tools-base"

jobs:
versions:
runs-on: ubuntu-latest

outputs:
toolsVersions: ${{ steps.versions.outputs.tools }}
latestVersion: ${{ steps.versions.outputs.latest }}
revisionHash: ${{ steps.versions.outputs.revisionHash}}

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: "Parse versions.json"
id: versions
run: |
toolsVersions=$(jq -c .tools versions.json)
latestVersion=$(jq -r -c .latest versions.json)
revisionHash=$(jq -r -c .revisionHash versions.json)
echo "tools=$toolsVersions" >> $GITHUB_OUTPUT
echo "tools=$toolsVersions"
echo "latest=$latestVersion" >> $GITHUB_OUTPUT
echo "latest=$latestVersion"
echo "revisionHash=$revisionHash" >> $GITHUB_OUTPUT
echo "revisionHash=$revisionHash"
build:
runs-on: ubuntu-latest
needs: versions
strategy:
matrix: ${{ fromJSON(needs.versions.outputs.toolsVersions) }}

steps:
- name: Log Inputs
run: |
echo "Kubectl Version: ${{ inputs.kubectl-version }}"
echo "Helm Version: ${{ inputs.helm-version }}"
echo "Kubectl Version: ${{ matrix.kubectl }}"
echo "Helm Version: ${{ matrix.helm }}"
echo "Powershell Version: ${{ matrix.powershell }}"
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-depth: 0

- name: Get branch names
id: branch_names
Expand All @@ -58,49 +83,70 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

- name: Create Tag Version
- name: Get Kubernetes Version
id: kubernetes-version
run: |
kubectlVersion="${{ matrix.kubectl }}"
kubeVersion="${kubectlVersion%'.'*}"
echo "kubernetesVersion=$kubeVersion" >> $GITHUB_OUTPUT
echo "kubeVersion=$kubeVersion"
- name: Create tags
run: |
fullVersion="${{ inputs.kubectl-version }}"
kubernetesVersion="${{ steps.kubernetes-version.outputs.kubernetesVersion }}"
revisionHash="-${{ needs.versions.outputs.revisionHash }}"
if [[ "${{steps.branch_names.outputs.branch_name}}" != "main" ]]
then
preRelease="-${{steps.branch_names.outputs.branch_name}}-$(date +'%Y%m%d%H%M%S')"
fi
tagVersion="${fullVersion%'.'*}$preRelease";
echo "tagVersion=$tagVersion" >> $GITHUB_OUTPUT;
echo "tagVersion=$tagVersion";
id: createTagVersion

# The short tag is just `1.30` (if pre-release, contains full pre-release string)
shortTag="$kubernetesVersion$preRelease"
echo "shortTag=$shortTag" >> $GITHUB_OUTPUT;
echo "shortTag=$shortTag";
# Revisioned short tag contains the 6 char revision hash e.g. `1.30-Df8l2d` (plus pre-release, if pre-release)
revisionedShortTag="$kubernetesVersion$revisionHash$preRelease"
echo "revisionedShortTag=$revisionedShortTag" >> $GITHUB_OUTPUT;
echo "revisionedShortTag=$revisionedShortTag";
# The all versions tag contains all the versions of the main tooling, plus revision hash and pre-release
allVersionsTag="kube${{ matrix.kubectl}}-helm${{ matrix.helm}}-pwsh${{matrix.powershell}}$revisionHash$preRelease"
echo "allVersionsTag=$allVersionsTag" >> $GITHUB_OUTPUT;
echo "allVersionsTag=$allVersionsTag";
id: create-tags

- name: Build and push for test
if: ${{ github.ref != 'refs/heads/main' }}
uses: docker/build-push-action@v5
with:
push: true
tags: "${{ secrets.ARTIFACTORY_DOCKER_REPO_HOSTNAME }}/octopusdeploy/kubernetes-agent-tools-base:${{ steps.createTagVersion.outputs.tagVersion }}"
tags: "${{ env.ArtifactoryImagePath }}:${{ steps.create-tags.outputs.shortTag }},${{ env.ArtifactoryImagePath }}:${{ steps.create-tags.outputs.revisionedShortTag}},${{ env.ArtifactoryImagePath }}:${{ steps.create-tags.outputs.allVersionsTag}}"
platforms: linux/amd64,linux/arm64
build-args: |
"KUBECTL_VERSION=${{ inputs.kubectl-version }}"
"HELM_VERSION=${{ inputs.helm-version }}"
"POWERSHELL_VERSION=${{ inputs.powershell-version }}"
"KUBECTL_VERSION=${{ matrix.kubectl }}"
"HELM_VERSION=${{ matrix.helm }}"
"POWERSHELL_VERSION=${{ matrix.powershell }}"
- name: Create production docker tags
if: ${{ github.ref == 'refs/heads/main' }}
run: |
artifactoryTags="${{ secrets.ARTIFACTORY_DOCKER_REPO_HOSTNAME }}/octopusdeploy/kubernetes-agent-tools-base:${{ steps.createTagVersion.outputs.tagVersion }}"
dockerhubTags="octopusdeploy/kubernetes-agent-tools-base:${{ steps.createTagVersion.outputs.tagVersion }}"
artifactoryTags="$ArtifactoryImagePath:${{ steps.create-tags.outputs.shortTag }},$ArtifactoryImagePath:${{ steps.create-tags.outputs.revisionedShortTag}},$ArtifactoryImagePath:${{ steps.create-tags.outputs.allVersionsTag}}"
dockerhubTags="$DockerHubImagePath:${{ steps.create-tags.outputs.shortTag }},$DockerHubImagePath:${{ steps.create-tags.outputs.revisionedShortTag}},$DockerHubImagePath:${{ steps.create-tags.outputs.allVersionsTag}}"
if [[ "${{ inputs.tag-as-latest }}" == "true" ]]
kubernetesVersion="${{ matrix.kubectl }}"
if [[ "${{ needs.versions.outputs.latestVersion }}" == "${{ steps.kubernetes-version.outputs.kubernetesVersion }}" ]]
then
artifactoryTags="$artifactoryTags,${{ secrets.ARTIFACTORY_DOCKER_REPO_HOSTNAME }}/octopusdeploy/kubernetes-agent-tools-base:latest"
dockerhubTags="$dockerhubTags,octopusdeploy/kubernetes-agent-tools-base:latest"
artifactoryTags="$artifactoryTags,$ArtifactoryImagePath:latest"
dockerhubTags="$dockerhubTags,$DockerHubImagePath:latest"
fi
dockerTags="$artifactoryTags,$dockerhubTags"
echo "dockerTags=$dockerTags" >> $GITHUB_OUTPUT;
echo "dockerTags=$dockerTags";
id: createProductionDockerTags


- name: Build and push for production
if: ${{ github.ref == 'refs/heads/main' }}
uses: docker/build-push-action@v5
Expand All @@ -109,6 +155,6 @@ jobs:
tags: ${{ steps.createProductionDockerTags.outputs.dockerTags }}
platforms: linux/amd64,linux/arm64
build-args: |
"KUBECTL_VERSION=${{ inputs.kubectl-version }}"
"HELM_VERSION=${{ inputs.helm-version }}"
"POWERSHELL_VERSION=${{ inputs.powershell-version }}"
"KUBECTL_VERSION=${{ matrix.kubectl }}"
"HELM_VERSION=${{ matrix.helm }}"
"POWERSHELL_VERSION=${{ matrix.powershell }}"
51 changes: 32 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,37 @@ This repo produces a container image that is used by the Kubernetes Agent to exe

Summary: The image packages `kubectl`, `helm`, `powershell` and `curl` on the base image `mcr.microsoft.com/dotnet/runtime-deps`.

# Building and Pushing a image
Currently this is mostly a manual process which involves dispatching `build-and-publish-container-image` github workflow.
The steps are as follows:
1. Navigate to the ["build and publish container image" workflow](https://github.com/OctopusDeploy/kubernetes-agent-tools-base/actions/workflows/build-and-publish-container-image.yml)
2. Click "Run workflow"
3. Configure the workflow as follows
* Branch: main or your desired branch - Only main will be pushed to dockerhub
* kubectl-version: This follows the Kubernetes versioning - values can be found on the [K8s git repo](https://github.com/kubernetes/kubernetes/tags)
* helm-version: This value will depend on the version of kubectl you have chosen, see the [helm compatibility table](https://helm.sh/docs/topics/version_skew/#supported-version-skew) to get the value.
* powershell-version: See the [Powershell github repo](https://github.com/PowerShell/PowerShell/tags) for a value or just use the default.
* tag-as-latest: If running against main and checked this will also push the image with the latest tag as well as the version tag.
4. Click "Run workflow"

# Accessing the image
Mainline builds will be pushed to both dockerhub with the name `octopusdeploy/kubernetes-agent-tools-base:{Kubectll Minor Version}.{Kubectl Minor Version}`
Example Dockerhub: `octopusdeploy/kubernetes-agent-tools-base:1.29`

Branch builds will only be pushed the Octopus' Artifactory instance with a prerelease version `{artifactory-hostname}/octopusdeploy/kubernetes-agent-tools-base:{Kubectll Minor Version}.{Kubectl Minor Version}-{Sanitized Branch Name}-{Date}`
Example: `{artifactory-hostname}/octopusdeploy/kubernetes-agent-tools-base:1.29-tl-push-to-dockerhub-20240424041854`
## Updating versions

In the root of the directory there is a file, `versions.json` which contains information about what versions of Kubectl (and thus Kubernetes), Helm & Powershell are used to generate the images.
Under the `tools` object, there are 3 fields with versions arrays (`kubectl`,`helm`,`powershell`), which are used in a matrix to generate the images.

There is also a `latest` field that represents the kubernetes version that will be tagged with the `latest` tag.

### Tags

There are 4 tags being published

- `latest` - Assigned to the highest version of the Kubernetes supported by the Kubernetes agent.
- `{Kubectl Major Version}.{Kubectl Minor Version}` - For each `kubectl` version, there will be an image with the Kubernetes major & minor version. Example: `1.31`.
- `{Kubectl Major Version}.{Kubectl Minor Version}-{Random6Chars}` - For each `kubectl` version, there will be an image with the Kubernetes major & minor version and random 6 char revision hash. Example: `1.31-X5msD0`.
- `kube{Kubectl Version}-helm{Helm Version}-pwsh{Powershell Version}-{Random6Chars}` - Contains all versions of the tools plus the revision hash. Example `kube1.31.1-helm3.16.1-pwsh7.4.5-X5msD0`.

### What is the `revisionHash`?

The revision hash is a "cache-busting" mechanism to allow the Kubernetes agent to get an updated version of the tools container image without needing to set the `imagePullPolicy` to `Always`. Because Kubernetes will cache the image on the node(s), it's possible that the image does not get re-acquired when there is a tooling update.

#### Generating a new `revisionHash`

As the `revisionHash` is used in the docker tag, which are case-sensitive, the following command generates a unique 6 char hash.

```bash
tr -dc A-Za-z0-9 </dev/urandom | head -c 6; echo
```

### Branch builds

Branch builds will only be pushed the Octopus' Artifactory instance with a prerelease version `{artifactory-hostname}/octopusdeploy/kubernetes-agent-tools-base:{Kubectll Minor Version}.{Kubectl Minor Version}-{Random6Chars}-{Sanitized Branch Name}-{Date}`
Example: `{artifactory-hostname}/octopusdeploy/kubernetes-agent-tools-base:1.29-X5msD0-tl-push-to-dockerhub-20240424041854`

The tags can be found from the logs in the Github action workflow under the step "Create Tag Version`
26 changes: 26 additions & 0 deletions versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"tools": {
"kubectl": [
"1.31.1",
"1.30.5",
"1.29.9",
"1.28.14"
],
"helm": [
"3.16.1"
],
"powershell": [
"7.4.5"
]
},
"latest": "1.30",
"revisionHash": "Juaa5J",
"deprecations": {
"1.26": {
"latestTag": "1.26@sha256:a0892db7be9d668eceba2ce0c56ed82b2a58ff205ffea27a98e40825143b63f"
},
"1.27": {
"latestTag": "1.27@sha256:9d1ce87c37a33582bd3bb0b2e2d54d7a6bc0e71d659a1132acd3893c9645a507"
}
}
}

0 comments on commit 71e4322

Please sign in to comment.