Repository navigation
144 lines (119 loc) · 4.84 KB
/
Copy pathdocker-prod.yml
File metadata and controls
144 lines (119 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# .github/workflows/docker-prod.yml
name: 🐋 Docker Production Image
run-name: 🐋 Production Docker Build • ${{ inputs.tag || github.ref_name }}
# Production images are release artifacts. They are built only from existing,
# non-empty annotated SemVer tags. Stable tags update the matching major,
# minor, and `latest` aliases; prerelease tags publish only their exact version.
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: Existing annotated release tag, such as v1.0.0 or v1.0.0-rc.1
required: true
type: string
permissions:
contents: read
packages: write
jobs:
docker-prod:
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.tag || github.ref }}
- name: 🐍 Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: 🔖 Resolve and validate Path Header Scanner build version
id: version
shell: bash
env:
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
run: |
python -m pip install --disable-pip-version-check packaging
TAG_REGEX='^v[0-9]+\.[0-9]+\.[0-9]+([.-](alpha|beta|rc|dev|post)\.[0-9]+)?(\+[0-9A-Za-z.]+)?$'
STABLE_TAG_REGEX='^v[0-9]+\.[0-9]+\.[0-9]+$'
TAG="$RELEASE_TAG"
PUBLISH_ALIASES=false
PUBLISH_LATEST=false
if [[ ! "$TAG" =~ $TAG_REGEX ]]; then
echo "Invalid Path Header Scanner release tag: $TAG" >&2
exit 1
fi
if ! git show-ref --verify --quiet "refs/tags/$TAG"; then
echo "Release tag does not exist in the repository: $TAG" >&2
exit 1
fi
if [[ "$(git cat-file -t "refs/tags/$TAG")" != "tag" ]]; then
echo "Production images require an annotated Git tag: $TAG" >&2
exit 1
fi
TAG_MESSAGE="$(git tag -l --format='%(contents)' "$TAG")"
if [[ -z "${TAG_MESSAGE//[[:space:]]/}" ]]; then
echo "Annotated release tag has an empty message: $TAG" >&2
exit 1
fi
VERSION="$(python -m app.core.build.version)"
EXPECTED_VERSION="$(python -c 'from packaging.version import Version; import sys; print(Version(sys.argv[1].removeprefix("v")).public)' "$TAG")"
if [[ -z "$VERSION" || "$VERSION" != "$EXPECTED_VERSION" ]]; then
echo "Resolved build version '$VERSION' does not match release tag '$TAG' ('$EXPECTED_VERSION')." >&2
exit 1
fi
if [[ "$TAG" =~ $STABLE_TAG_REGEX ]]; then
PUBLISH_ALIASES=true
PUBLISH_LATEST=true
fi
IMAGE_TAG="${TAG//+/-}"
VERSION_CORE="${TAG#v}"
VERSION_CORE="${VERSION_CORE%%+*}"
IFS='.' read -r MAJOR MINOR _ <<< "$VERSION_CORE"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "image_tag=$IMAGE_TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
echo "publish_aliases=$PUBLISH_ALIASES" >> "$GITHUB_OUTPUT"
echo "publish_latest=$PUBLISH_LATEST" >> "$GITHUB_OUTPUT"
- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 🔐 Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🔤 Normalize image name
id: vars
shell: bash
run: |
echo "image_name=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
- name: 🏷️ Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ steps.vars.outputs.image_name }}
tags: |
type=raw,value=${{ steps.version.outputs.image_tag }}
type=raw,value=v${{ steps.version.outputs.major }}.${{ steps.version.outputs.minor }},enable=${{ steps.version.outputs.publish_aliases }}
type=raw,value=v${{ steps.version.outputs.major }},enable=${{ steps.version.outputs.publish_aliases }}
type=raw,value=latest,enable=${{ steps.version.outputs.publish_latest }}
- name: 🏗️ Build and push production image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
target: production
build-args: |
PHS_BUILD_VERSION=${{ steps.version.outputs.version }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max