Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 27 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6294795
Add new versions.json and update build and release workflow to use it
APErebus Sep 30, 2024
c15ecf1
Debug logging
APErebus Sep 30, 2024
3089173
Correct function name
APErebus Sep 30, 2024
86812ad
Change to pass matrix json
APErebus Sep 30, 2024
5585b64
Remove raw for tools object
APErebus Sep 30, 2024
aad779a
Escape tools json
APErebus Sep 30, 2024
c31393b
Remove escaping
APErebus Sep 30, 2024
22ab6c8
Fix quoting
APErebus Sep 30, 2024
f53e073
confirmation step
APErebus Sep 30, 2024
7c6b5de
Stop quoting the
APErebus Sep 30, 2024
30836e8
Use double quotes
APErebus Sep 30, 2024
55caff1
add r to revision number and fix all versions tag
APErebus Sep 30, 2024
1903f6a
Add deprecations and add naming to all versions tag
APErebus Sep 30, 2024
09ed3cf
Clean up some logic for getting the k8s version
APErebus Sep 30, 2024
460f6b3
Use env vars for image paths
APErebus Sep 30, 2024
efb8500
fix env vars
APErebus Sep 30, 2024
3187dd7
Use correct variable
APErebus Sep 30, 2024
90a2eb5
Update Readme
APErebus Oct 1, 2024
0959eff
Only run on versions.json change
APErebus Oct 1, 2024
5fe0af8
Change revision to be random 4 char string
APErebus Oct 1, 2024
522a67c
Only apply revision to main builds
APErebus Oct 1, 2024
776166b
change to 6 char random revision
APErebus Oct 1, 2024
750e2c5
Update readme
APErebus Oct 1, 2024
2fc764e
Change to revision hash driven from versions.json
APErebus Oct 1, 2024
ed661f9
Update readme
APErebus Oct 1, 2024
f5d697b
Update deprecations node
APErebus Oct 1, 2024
8a8959c
Fix revision hash not being passed through
APErebus Oct 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
APErebus marked this conversation as resolved.
Show resolved Hide resolved
"revisionHash": "Juaa5J",
"deprecations": {
"1.26": {
"latestTag": "1.26@sha256:a0892db7be9d668eceba2ce0c56ed82b2a58ff205ffea27a98e40825143b63f"
},
"1.27": {
"latestTag": "1.27@sha256:9d1ce87c37a33582bd3bb0b2e2d54d7a6bc0e71d659a1132acd3893c9645a507"
}
}
}
Loading