-
Notifications
You must be signed in to change notification settings - Fork 0
175 lines (146 loc) · 7.29 KB
/
build-and-push.yml
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
name: Build and Push Docker Images to GHCR (User-Specified or Auto-Increment Version)
on:
workflow_dispatch:
inputs:
version:
description: "Specify a custom version (e.g., 1.5). Leave empty for auto-increment."
required: false
default: ""
push:
branches:
- main
paths:
- "**/**" # Detect changes at any path
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
env:
DOCKER_CONFIG: /tmp/docker-config # ephemeral Docker config folder
steps:
##################################################################
# 1) CHECK OUT CODE
##################################################################
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 2 # Ensure we have a previous commit if it exists
##################################################################
# 2) PREPARE EPHEMERAL DOCKER CONFIG
##################################################################
- name: Prepare Ephemeral Docker Config
run: mkdir -p /tmp/docker-config
##################################################################
# 3) CONVERT REPO OWNER TO LOWERCASE
##################################################################
- name: Convert Repository Owner to Lowercase
run: echo "OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
##################################################################
# 4) DETECT CHANGED DIRECTORIES
##################################################################
- name: Detect Changed Directories
id: detect
run: |
echo "=== Detecting changed top-level directories ==="
# If there's a previous commit, find changed directories
if git rev-parse HEAD^ >/dev/null 2>&1; then
CHANGED_DIRS=$(git diff --name-only HEAD^ HEAD -- | awk -F/ '{print $1}' | sort -u | grep -v '^\.' || true)
else
# If first commit, consider all top-level directories
CHANGED_DIRS=$(ls -d */ | cut -f1 -d'/' | grep -v '^\.' || true)
fi
echo "Raw changed directories: $CHANGED_DIRS"
# Convert to space-separated for looping
echo "CHANGED_DIRS=$(echo "$CHANGED_DIRS" | tr '\n' ' ')" >> $GITHUB_ENV
##################################################################
# 5) LOG IN TO GHCR (SECURELY, WITH EPHEMERAL CONFIG)
##################################################################
- name: Log in to GitHub Container Registry
run: |
echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
echo "Successfully logged in using ephemeral Docker config at $DOCKER_CONFIG"
##################################################################
# 6) BUILD AND PUSH DOCKER IMAGES
##################################################################
- name: Build and Push Docker Images
run: |
# If no directories changed, skip
if [ -z "${{ env.CHANGED_DIRS }}" ]; then
echo "No top-level directories changed. Skipping build."
exit 0
fi
echo "Directories to process: ${{ env.CHANGED_DIRS }}"
# Check if user provided a custom version
USER_SPECIFIED_VERSION="${{ github.event.inputs.version }}"
echo "User-specified version: $USER_SPECIFIED_VERSION (empty = auto)"
for dir in ${{ env.CHANGED_DIRS }}; do
if [ ! -d "$dir" ]; then
echo "Skipping '$dir' (not a directory)."
continue
fi
echo "=== Processing directory: $dir ==="
# If user specified a version, use it; otherwise auto-detect
if [ -n "$USER_SPECIFIED_VERSION" ]; then
NEW_VERSION="$USER_SPECIFIED_VERSION"
echo "Using user-specified version: $NEW_VERSION"
else
##################################################################
# AUTO-INCREMENT LOGIC
##################################################################
PACKAGE_URL="https://api.github.com/orgs/${{ env.OWNER }}/packages/container/$dir/versions"
echo "Fetching GHCR versions from: $PACKAGE_URL"
API_RESPONSE=$(curl -s \
-H "Authorization: Bearer ${{ secrets.GHCR_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"$PACKAGE_URL")
echo "GHCR API Response: $API_RESPONSE"
# If package not found => start at 1.0
if echo "$API_RESPONSE" | grep -q '"message": "Package not found."'; then
NEW_VERSION="1.0"
echo "Package '$dir' not found. Starting at version 1.0."
else
# Check if GHCR returned a valid array
IS_ARRAY=$(echo "$API_RESPONSE" | jq -r 'type' 2>/dev/null || true)
if [ "$IS_ARRAY" != "array" ]; then
NEW_VERSION="1.0"
echo "GHCR response not an array. Starting at 1.0."
else
# Regex allows optional 'v' prefix: ^v?[0-9]+\.[0-9]+$
VERSION_TAGS=$(echo "$API_RESPONSE" | jq -r '
[.[].metadata.container.tags? // [] | .[]]
| map(select(test("^v?[0-9]+\\.[0-9]+$") and . != "latest"))
| sort
| last
')
if [ -z "$VERSION_TAGS" ] || [ "$VERSION_TAGS" = "null" ]; then
NEW_VERSION="1.0"
echo "No valid versions found for '$dir'. Starting at 1.0."
else
# Strip leading 'v' if present, then increment minor
CLEAN_VERSION=$(echo "$VERSION_TAGS" | sed 's/^v//')
NEW_VERSION=$(awk -F. '{print $1 "." $2+1}' <<< "$CLEAN_VERSION")
echo "Latest version: $CLEAN_VERSION => Incremented to: $NEW_VERSION"
fi
fi
fi
fi
echo "Final version for '$dir': $NEW_VERSION"
IMAGE_NAME="ghcr.io/${{ env.OWNER }}/$dir"
echo "Docker Image Name: $IMAGE_NAME"
echo "=== Building Docker image: $IMAGE_NAME:v$NEW_VERSION ==="
docker build -t "$IMAGE_NAME:v$NEW_VERSION" -t "$IMAGE_NAME:latest" "$dir/"
docker push "$IMAGE_NAME:v$NEW_VERSION"
docker push "$IMAGE_NAME:latest"
##############################################################################
# AFTER PUSH: MAKE THE PACKAGE PUBLIC
##############################################################################
echo "Making the GHCR package '$dir' public..."
curl -X PATCH "https://api.github.com/orgs/${{ env.OWNER }}/packages/container/$dir/visibility" \
-H "Authorization: Bearer ${{ secrets.GHCR_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
-d '{"visibility":"public"}'
echo "=== Done with $dir (version $NEW_VERSION) ==="
done
echo "=== All directories processed ==="