Skip to content

Commit e419da4

Browse files
authored
publish docker images on PR (#101)
* publish docker images on PR * add PR cleanup * deduplicate metadata step id * add tag computation * init fix for helm * fix workflow type * streamline versions * fix docker cache * fix helm versions * fix bash expansion * always log in to quay * fix chart cleanup
1 parent edfc85a commit e419da4

5 files changed

Lines changed: 208 additions & 43 deletions

File tree

.github/actions/compute-versions/action.yml

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: workflow-metadata
2+
description: "Compute workflow metadata"
3+
4+
outputs:
5+
workflow-type:
6+
description: Workflow type. One of 'PR', 'main', or 'release'
7+
value: ${{ steps.workflow.outputs.workflow-type }}
8+
app-version-raw:
9+
description: Raw app version
10+
value: ${{ steps.versions.outputs.app-version-raw }}
11+
app-version-tag:
12+
description: Tag app version
13+
value: ${{ steps.versions.outputs.app-version-tag }}
14+
app-version-latest:
15+
description: Latest app version
16+
value: ${{ steps.versions.outputs.app-version-latest }}
17+
chart-version-latest:
18+
description: Latest chart version
19+
value: ${{ steps.versions.outputs.chart-version-latest }}
20+
21+
runs:
22+
using: composite
23+
24+
steps:
25+
- id: workflow
26+
shell: bash
27+
run: |
28+
# Compute workflow type
29+
case '${{ github.event_name }}' in
30+
pull_request)
31+
WORKFLOW_TYPE=PR
32+
;;
33+
push)
34+
case '${{ github.ref }}' in
35+
refs/heads/main)
36+
WORKFLOW_TYPE=main
37+
;;
38+
refs/tags/*)
39+
WORKFLOW_TYPE=release
40+
;;
41+
*)
42+
echo "unknown push ref '${{ github.ref }}'" >&2
43+
exit 1
44+
;;
45+
esac
46+
;;
47+
*)
48+
echo "unknown event name '${{ github.event_name }}'" >&2
49+
exit 1
50+
;;
51+
esac
52+
53+
echo "workflow-type=${WORKFLOW_TYPE}" | tee --append "${GITHUB_OUTPUT}"
54+
55+
- name: Install uv and set the python version
56+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
57+
with:
58+
working-directory: ./backend
59+
enable-cache: true
60+
61+
- shell: bash
62+
working-directory: ./backend
63+
run: uv sync --link-mode copy --locked
64+
65+
- id: versions
66+
shell: bash
67+
run: |
68+
APP_VERSION_RAW=$(cd ./backend && uv run hatch version)
69+
echo "app-version-raw=${APP_VERSION_RAW}" | tee --append "${GITHUB_OUTPUT}"
70+
71+
APP_VERSION_TAG=$(echo "${APP_VERSION_RAW}" | sed 's/+/-/g')
72+
echo "app-version-tag=${APP_VERSION_TAG}" | tee --append "${GITHUB_OUTPUT}"
73+
74+
APP_VERSION_LATEST=$(git describe --tags --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=0 | sed 's|^v||')
75+
echo "app-version-latest=${APP_VERSION_LATEST}" | tee --append "${GITHUB_OUTPUT}"
76+
77+
CHART_VERSION_LATEST=$(git describe --tags --match "chart/v[0-9]*.[0-9]*.[0-9]*" --abbrev=0 | sed 's|^chart/v||')
78+
echo "chart-version-latest=${CHART_VERSION_LATEST}" | tee --append "${GITHUB_OUTPUT}"

.github/workflows/docker.yml

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: docker
33
on:
44
pull_request:
55
push:
6+
branches: ["main"]
67
tags: ['v[0-9]+\.[0-9]+\.[0-9]+']
78

89
concurrency:
@@ -29,9 +30,9 @@ jobs:
2930
ref: ${{ github.event.pull_request.head.sha }}
3031
fetch-depth: 0
3132

32-
- name: Compute versions
33-
id: versions
34-
uses: ./.github/actions/compute-versions
33+
- name: Compute workflow metadata
34+
id: workflow-metadata
35+
uses: ./.github/actions/workflow-metadata
3536

3637
- name: Set up QEMU
3738
uses: docker/setup-qemu-action@v4
@@ -40,21 +41,67 @@ jobs:
4041
uses: docker/setup-buildx-action@v4
4142

4243
- name: Setup image metadata
43-
id: metadata
44+
id: image-metadata
4445
uses: docker/metadata-action@v6
4546
with:
4647
images: ${{ matrix.image }}
4748
tags: |
48-
type=raw,value=latest
49-
type=raw,value=${{ steps.versions.outputs.app-version }}
49+
type=raw,value=pr-${{ github.event.number }},enable=${{ steps.workflow-metadata.outputs.workflow-type == 'PR' }}
50+
type=raw,value=pr-${{ github.event.number }}-${{ steps.workflow-metadata.outputs.app-version-tag }},enable=${{ steps.workflow-metadata.outputs.workflow-type == 'PR' }}
51+
type=raw,value=main,enable=${{ steps.workflow-metadata.outputs.workflow-type == 'main' }}
52+
type=raw,value=latest,enable=${{ steps.workflow-metadata.outputs.workflow-type == 'release' }}
53+
type=raw,value=${{ steps.workflow-metadata.outputs.app-version-tag }},enable=${{ steps.workflow-metadata.outputs.workflow-type == 'release' }}
5054
labels: |
5155
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
5256
org.opencontainers.image.revision=${{ github.sha }}
5357
io.github.event.name=${{ github.event_name }}
5458
io.github.event.pull-request.number=${{ github.event.number }}
59+
60+
- name: Generate cache entries
61+
id: cache
62+
shell: bash
63+
run: |
64+
MAIN_TAG="main-buildcache"
65+
66+
case '${{ steps.workflow-metadata.outputs.workflow-type }}' in
67+
PR)
68+
PR_TAG="pr-${{ github.event.number }}-buildcache"
69+
70+
FROM_TAGS=("${PR_TAG}" "${MAIN_TAG}")
71+
TO_TAGS=("${PR_TAG}")
72+
;;
73+
main)
74+
FROM_TAGS=("${MAIN_TAG}")
75+
TO_TAGS=("${MAIN_TAG}")
76+
;;
77+
release)
78+
FROM_TAGS=("${MAIN_TAG}")
79+
TO_TAGS=()
80+
;;
81+
*)
82+
echo "unknown workflow type '${{ steps.workflow-metadata.outputs.workflow-type }}'" >&2
83+
exit 1
84+
;;
85+
esac
86+
87+
FROM_JSON=$(jq --null-input --compact-output \
88+
--arg prefix 'type=registry,ref=${{ matrix.image }}:' \
89+
--args \
90+
'$ARGS.positional | map($prefix + .)' \
91+
-- "${FROM_TAGS[@]}" \
92+
)
93+
echo "from-json=${FROM_JSON}" | tee --append "${GITHUB_OUTPUT}"
94+
95+
TO_JSON=$(jq --null-input --compact-output \
96+
--arg prefix 'type=registry,ref=${{ matrix.image }}:' \
97+
--arg postfix ',mode=max' \
98+
--args \
99+
'$ARGS.positional | map($prefix + . + $postfix)' \
100+
-- "${TO_TAGS[@]}" \
101+
)
102+
echo "to-json=${TO_JSON}" | tee --append "${GITHUB_OUTPUT}"
55103
56104
- name: Login to Quay.io
57-
if: ${{ github.event_name != 'pull_request' }}
58105
uses: docker/login-action@v4
59106
with:
60107
registry: quay.io
@@ -66,8 +113,10 @@ jobs:
66113
with:
67114
context: ${{ matrix.context }}
68115
build-args: |
69-
VERSION=${{ steps.versions.outputs.app-version }}
116+
VERSION=${{ steps.workflow-metadata.outputs.app-version-raw }}
70117
platforms: "linux/amd64,linux/arm64"
71-
tags: ${{ steps.metadata.outputs.tags }}
72-
labels: ${{ steps.metadata.outputs.labels }}
73-
push: ${{ github.event_name != 'pull_request' }}
118+
tags: ${{ steps.image-metadata.outputs.tags }}
119+
labels: ${{ steps.image-metadata.outputs.labels }}
120+
push: true
121+
cache-from: ${{ join(fromJson(steps.cache.outputs.from-json), '\n') }}
122+
cache-to: ${{ join(fromJson(steps.cache.outputs.to-json), '\n') }}

.github/workflows/helm.yml

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ jobs:
2020
ref: ${{ github.event.pull_request.head.sha }}
2121
fetch-depth: 0
2222

23-
- name: Compute versions
24-
id: versions
25-
uses: ./.github/actions/compute-versions
23+
- name: Compute workflow metadata
24+
id: workflow-metadata
25+
uses: ./.github/actions/workflow-metadata
2626

2727
- name: Install mise and setup helm
2828
uses: jdx/mise-action@v4
@@ -31,6 +31,31 @@ jobs:
3131
[tools]
3232
helm = "latest"
3333
34+
- name: Set versions
35+
id: versions
36+
run: |
37+
case '${{ steps.workflow-metadata.outputs.workflow-type }}' in
38+
PR)
39+
CHART_VERSION_SUFFIX='-pr.${{ github.event.number }}'
40+
;;
41+
main)
42+
CHART_VERSION_SUFFIX='-main'
43+
;;
44+
release)
45+
CHART_VERSION_SUFFIX=''
46+
;;
47+
*)
48+
echo "unknown workflow type '${{ steps.workflow-metadata.outputs.workflow-type }}'" >&2
49+
exit 1
50+
;;
51+
esac
52+
53+
CHART_VERSION="${{ steps.workflow-metadata.outputs.chart-version-latest }}${CHART_VERSION_SUFFIX}"
54+
APP_VERSION='${{ steps.workflow-metadata.outputs.app-version-tag }}'
55+
56+
echo "app-version=${APP_VERSION}" | tee --append "${GITHUB_OUTPUT}"
57+
echo "chart-version=${CHART_VERSION}" | tee --append "${GITHUB_OUTPUT}"
58+
3459
- name: Patch helm chart
3560
uses: ./.github/actions/patch-helm-chart
3661
with:
@@ -44,13 +69,12 @@ jobs:
4469
run: helm package ./helm/nebari-chat
4570

4671
- name: Login to Quay.io
47-
if: ${{ github.event_name != 'pull_request' }}
4872
uses: docker/login-action@v4
4973
with:
5074
registry: quay.io
5175
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
5276
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
5377

5478
- name: Push helm chart
55-
if: ${{ github.event_name != 'pull_request' }}
56-
run: helm push 'nebari-chat-${{ steps.versions.outputs.chart-version }}.tgz' oci://quay.io/nebari/charts
79+
shell: bash
80+
run: helm push nebari-chat-*.tgz oci://quay.io/nebari/charts

.github/workflows/pr-cleanup.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: PR cleanup
2+
3+
on:
4+
pull_request:
5+
types:
6+
- closed
7+
8+
9+
jobs:
10+
cleanup:
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
image:
16+
- quay.io/nebari/nebari-chat-backend
17+
- quay.io/nebari/nebari-chat-frontend
18+
- quay.io/nebari/charts/nebari-chat
19+
20+
steps:
21+
- name: Install Skopeo and jq
22+
run: |
23+
sudo apt-get update
24+
sudo apt-get install --yes skopeo jq
25+
26+
- name: Login to Quay.io
27+
run: |
28+
echo "${{ secrets.DOCKER_REGISTRY_PASSWORD }}" | skopeo login --username "${{ secrets.DOCKER_REGISTRY_USERNAME }}" --password-stdin quay.io
29+
30+
- name: Delete PR tags
31+
run: |
32+
PR_NUMBER=${{ github.event.number }}
33+
TAGS=$(skopeo list-tags docker://${{ matrix.image }} | jq --raw-output ".Tags[] | select(test(\"(^pr-${PR_NUMBER}-)|(-pr\\.${PR_NUMBER}$)\"))" || true)
34+
35+
if [[ -z "${TAGS}" ]]; then
36+
echo "No tags found for PR #${PR_NUMBER}"
37+
exit 0
38+
fi
39+
40+
echo "${TAGS}" | xargs -t -I '{tag}' skopeo delete 'docker://${{ matrix.image }}:{tag}'

0 commit comments

Comments
 (0)