Skip to content

Commit f39e476

Browse files
committed
fix last details
1 parent 2e00a49 commit f39e476

35 files changed

+798
-341
lines changed

.github/workflows/docker-workflow.yml

Lines changed: 125 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: Docker Build & Push All Services
22

33
on:
4+
delete:
45
push:
56
tags:
67
- "v*.*.*"
@@ -20,22 +21,6 @@ jobs:
2021
- name: 🧠 Discover components and services
2122
id: set-matrix
2223
run: |
23-
# Customize these lists as needed
24-
EXCLUDED_COMPONENTS=(core validator)
25-
EXCLUDED_SERVICES=()
26-
27-
should_exclude() {
28-
local item=$1
29-
shift
30-
local list=("$@")
31-
for ex in "${list[@]}"; do
32-
if [[ "$item" == "$ex" ]]; then
33-
return 0
34-
fi
35-
done
36-
return 1
37-
}
38-
3924
mkdir -p .build/tmp_matrix
4025
echo '{ "include": [' > .build/tmp_matrix/matrix.json
4126
FIRST=true
@@ -44,32 +29,15 @@ jobs:
4429
[ -d "$comp" ] || continue
4530
comp_name=$(basename "$comp")
4631
47-
# 🔥 Skip excluded components
48-
if should_exclude "$comp_name" "${EXCLUDED_COMPONENTS[@]}"; then
49-
echo "⏭️ Skipping excluded component: $comp_name"
50-
continue
51-
fi
52-
53-
for service in "$comp"/*; do
54-
[ -d "$service" ] || continue
55-
service_name=$(basename "$service")
56-
57-
# 🔥 Skip excluded services
58-
if should_exclude "$service_name" "${EXCLUDED_SERVICES[@]}"; then
59-
echo "⏭️ Skipping excluded service: $service_name"
60-
continue
61-
fi
62-
63-
# ✅ Include only if it has a pyproject or version.py
64-
if [[ -f "$service/pyproject.toml" || -f "$service/version.py" ]]; then
65-
if [ "$FIRST" = true ]; then
66-
FIRST=false
67-
else
68-
echo "," >> .build/tmp_matrix/matrix.json
69-
fi
70-
echo " { \"component\": \"$comp_name\", \"service\": \"$service_name\" }" >> .build/tmp_matrix/matrix.json
32+
# ✅ Include only if it has a pyproject or version.py
33+
if [[ -f "$comp/pyproject.toml" || -f "$comp/version.py" ]]; then
34+
if [ "$FIRST" = true ]; then
35+
FIRST=false
36+
else
37+
echo "," >> .build/tmp_matrix/matrix.json
7138
fi
72-
done
39+
echo " { \"component\": \"$comp_name\" }" >> .build/tmp_matrix/matrix.json
40+
fi
7341
done
7442
7543
echo "] }" >> .build/tmp_matrix/matrix.json
@@ -80,22 +48,26 @@ jobs:
8048
8149
echo "🔍 Final matrix ready."
8250
83-
wheel-builder:
84-
if: github.event_name == 'push'
51+
build:
52+
if: github.event_name == 'push' || github.event_name == 'delete'
53+
needs: [discover]
8554
runs-on: ubuntu-latest
86-
outputs:
87-
tag: ${{ steps.meta.outputs.tag }}
55+
permissions:
56+
contents: read
57+
packages: write
58+
strategy:
59+
matrix:
60+
include: ${{ fromJson(needs.discover.outputs.matrix).include }}
61+
8862
steps:
89-
- name: 🧾 Checkout
63+
- name: 🧾 Checkout repository
9064
uses: actions/checkout@v3
9165

9266
- name: 🛠 Set up QEMU
9367
uses: docker/setup-qemu-action@v2
9468

95-
- name: 🛠 Set up Docker Buildx
69+
- name: 🧱 Set up Docker Buildx
9670
uses: docker/setup-buildx-action@v2
97-
with:
98-
driver-opts: network=host
9971

10072
- name: 🔐 Docker Login
10173
uses: docker/login-action@v2
@@ -110,44 +82,25 @@ jobs:
11082
echo "tag=subvortex/subvortex-wheel-builder:3.11-$HASH" >> $GITHUB_OUTPUT
11183
11284
- name: 🐋 Build & push wheel-builder (only if not exists)
85+
id: wheelbuilder
11386
run: |
114-
if docker pull ${{ steps.meta.outputs.tag }} >/dev/null 2>&1; then
115-
echo "✅ Image already exists: ${{ steps.meta.outputs.tag }}"
87+
TAG="${{ steps.meta.outputs.tag }}"
88+
LATEST_TAG="subvortex/subvortex-wheel-builder:latest"
89+
90+
if docker pull "$TAG" >/dev/null 2>&1; then
91+
echo "✅ Image already exists: $TAG"
11692
else
11793
echo "🚀 Building wheel-builder image"
11894
docker buildx build \
119-
--platform linux/amd64,linux/arm64 \
120-
--tag ${{ steps.meta.outputs.tag }} \
95+
--platform linux/amd64 \
96+
--tag "$TAG" \
97+
--tag "$LATEST_TAG" \
12198
--file subvortex/core/Dockerfile.builder \
12299
--push \
123100
.
124101
fi
125102
126-
build:
127-
needs: [discover, wheel-builder]
128-
runs-on: ubuntu-latest
129-
permissions:
130-
contents: read
131-
packages: write
132-
strategy:
133-
matrix:
134-
include: ${{ fromJson(needs.discover.outputs.matrix).include }}
135-
136-
steps:
137-
- name: 🧾 Checkout repository
138-
uses: actions/checkout@v3
139-
140-
- name: 🛠 Set up QEMU
141-
uses: docker/setup-qemu-action@v2
142-
143-
- name: 🧱 Set up Docker Buildx
144-
uses: docker/setup-buildx-action@v2
145-
146-
- name: 🔐 Docker Login
147-
uses: docker/login-action@v2
148-
with:
149-
username: ${{ secrets.DOCKER_USERNAME }}
150-
password: ${{ secrets.DOCKER_PASSWORD }}
103+
echo "tag=$TAG" >> $GITHUB_OUTPUT
151104
152105
- name: 🧠 Determine tag and floating tags
153106
id: taginfo
@@ -166,30 +119,48 @@ jobs:
166119
- name: 🚀 Build and push version-tagged image (on tag push only)
167120
if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'push'
168121
run: |
169-
COMP=${{ matrix.component }}
170-
SERVICE=${{ matrix.service }}
171-
IMAGE="subvortex/subvortex-$COMP-$SERVICE"
172-
WHEEL_IMAGE="${{ needs.wheel-builder.outputs.tag }}"
173-
RAW_VERSION_TAG="${{ steps.taginfo.outputs.version_tag }}"
174-
VERSION_TAG="${RAW_VERSION_TAG#v}"
175-
DOCKERFILE="subvortex/$COMP/$SERVICE/Dockerfile"
122+
COMP="${{ matrix.component }}"
123+
REPO_NAME="subvortex-${COMP//_/-}" && echo "$COMP"
124+
IMAGE="subvortex/$REPO_NAME"
125+
WHEEL_IMAGE="${{ steps.meta.outputs.tag }}"
126+
VERSION_TAG="${{ steps.taginfo.outputs.version_tag }}"
127+
VERSION="${VERSION_TAG#v}"
128+
DOCKERFILE="subvortex/$COMP/Dockerfile"
129+
130+
echo "🔍 Searching for component version... $COMP / $IMAGE"
131+
COMPONENT_PATH="subvortex/$COMP"
132+
if [ -f "$COMPONENT_PATH/pyproject.toml" ]; then
133+
echo "✅ Found pyproject.toml"
134+
COMPONENT_VERSION=$(grep -E '^version\s*=' "$COMPONENT_PATH/pyproject.toml" | head -1 | sed -E 's/version\s*=\s*"([^"]+)"/\1/')
135+
elif [ -f "$COMPONENT_PATH/version.py" ]; then
136+
echo "✅ Found version.py"
137+
COMPONENT_VERSION=$(python -c "import ast; f=open('$COMPONENT_PATH/version.py'); print([n.value.s for n in ast.walk(ast.parse(f.read())) if isinstance(n, ast.Assign) and n.targets[0].id == '__version__'][0])")
138+
else
139+
echo "❌ No version file found for component"
140+
exit 1
141+
fi
142+
143+
echo "🧾 Final versions:"
144+
echo "VERSION=$VERSION"
145+
echo "COMPONENT_VERSION=$COMPONENT_VERSION"
176146
177-
echo "🚀 Building image $IMAGE:$VERSION_TAG"
147+
echo "🚀 Building image $IMAGE:$VERSION"
178148
179149
docker buildx build \
180150
--squash \
181-
--platform linux/amd64,linux/arm64 \
151+
--platform linux/amd64 \
182152
--build-context wheelbuilder=docker-image://$WHEEL_IMAGE \
183-
--build-arg VERSION=$VERSION_TAG \
184-
--build-arg COMPONENT_VERSION=$VERSION_TAG \
185-
--cache-from=type=gha,scope=wheels_${COMP}_${SERVICE}_${ARCH} \
186-
--cache-to=type=gha,mode=max,scope=wheels_${COMP}_${SERVICE}_${ARCH} \
187-
--tag $IMAGE:$VERSION_TAG \
153+
--build-arg VERSION=$VERSION \
154+
--build-arg COMPONENT_VERSION=$COMPONENT_VERSION \
155+
--cache-from=type=gha,scope=wheels_${COMP}_${ARCH} \
156+
--cache-to=type=gha,mode=max,scope=wheels_${COMP}_${ARCH} \
157+
--tag $IMAGE:$VERSION \
188158
--file $DOCKERFILE \
189159
--push \
190160
.
191161
192162
release:
163+
if: github.event_name == 'release'
193164
needs: [discover]
194165
runs-on: ubuntu-latest
195166
permissions:
@@ -232,54 +203,53 @@ jobs:
232203
- name: 🚀 Retag and push floating tags (on release or prerelease)
233204
if: github.event_name == 'release' && github.event.action != 'deleted'
234205
run: |
235-
COMP=${{ matrix.component }}
236-
SERVICE=${{ matrix.service }}
237-
IMAGE="subvortex/subvortex-$COMP-$SERVICE"
206+
COMP="${{ matrix.component }}"
207+
REPO_NAME="subvortex-${COMP//_/-}" && echo "$COMP"
208+
IMAGE="subvortex/$REPO_NAME"
238209
RAW_VERSION_TAG="${{ steps.taginfo.outputs.version_tag }}"
239-
VERSION_TAG="${RAW_VERSION_TAG#v}"
210+
VERSION="${RAW_VERSION_TAG#v}"
240211
FLOATING_TAGS="${{ steps.taginfo.outputs.floating_tags }}"
241212
IS_PRERELEASE=${{ github.event.release.prerelease }}
242213
IS_DRAFT=${{ github.event.release.draft }}
243-
214+
244215
echo "📦 Release type: prerelease=$IS_PRERELEASE, draft=$IS_DRAFT"
245216
echo "🏷️ Floating tags requested: $FLOATING_TAGS"
246-
217+
247218
if [ "$IS_DRAFT" = "true" ]; then
248219
echo "⏭️ Skipping draft release"
249220
exit 0
250221
fi
251-
252-
echo "🔍 Getting manifest for $IMAGE:$VERSION_TAG"
253-
docker buildx imagetools inspect $IMAGE:$VERSION_TAG
254-
222+
223+
echo "🔍 Getting manifest for $IMAGE:$VERSION"
224+
docker buildx imagetools inspect $IMAGE:$VERSION
225+
255226
for TAG in $FLOATING_TAGS; do
256227
# Skip "latest" for prereleases
257228
if [ "$IS_PRERELEASE" = "true" ] && [ "$TAG" = "latest" ]; then
258229
echo "⏭️ Skipping 'latest' tag for prerelease"
259230
continue
260231
fi
261-
262-
echo "🔁 Creating manifest for $IMAGE:$TAG from $IMAGE:$VERSION_TAG"
232+
233+
echo "🔁 Creating manifest for $IMAGE:$TAG from $IMAGE:$VERSION"
263234
docker buildx imagetools create \
264235
--tag $IMAGE:$TAG \
265-
$IMAGE:$VERSION_TAG
236+
$IMAGE:$VERSION
266237
done
267238
268239
- name: 🧹 Remove floating tags (on release or prerelease delete)
269240
if: github.event_name == 'release' && github.event.action == 'deleted'
270241
run: |
271-
COMP=${{ matrix.component }}
272-
SERVICE=${{ matrix.service }}
273-
IMAGE="subvortex/subvortex-$COMP-$SERVICE"
242+
COMP="${{ matrix.component }}"
243+
REPO_NAME="subvortex-${COMP//_/-}" && echo "$COMP"
244+
IMAGE="subvortex/$REPO_NAME"
274245
RAW_VERSION_TAG="${{ github.event.release.tag_name }}"
275-
VERSION_TAG="${RAW_VERSION_TAG#v}"
246+
VERSION="${RAW_VERSION_TAG#v}"
276247
FLOATING_TAGS="${{ steps.taginfo.outputs.floating_tags }}"
277248
USERNAME="${{ secrets.DOCKER_USERNAME }}"
278249
PASSWORD="${{ secrets.DOCKER_PASSWORD }}"
279-
REPO_NAME="subvortex-$COMP-$SERVICE"
280250
281-
echo "🗑️ Release deleted: $RAW_VERSION_TAG"
282-
echo "🔍 Attempting to delete floating tags: $FLOATING_TAGS"
251+
echo "🗑️ Release deleted: $VERSION"
252+
echo "🔍 Handling floating tags: $FLOATING_TAGS"
283253
284254
echo "🔐 Requesting Docker Hub JWT token..."
285255
TOKEN=$(curl -s -X POST https://hub.docker.com/v2/users/login/ \
@@ -291,18 +261,50 @@ jobs:
291261
exit 1
292262
fi
293263
264+
echo "📦 Fetching all tags from Docker Hub (excluding deleted tag: $VERSION)..."
265+
ALL_TAGS=$(curl -s -H "Authorization: JWT $TOKEN" \
266+
"https://hub.docker.com/v2/repositories/$USERNAME/$REPO_NAME/tags?page_size=100" | jq -r '.results[].name' | grep -v "^$VERSION$")
267+
268+
RELEASE_TAGS=$(echo "$ALL_TAGS" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' || true)
269+
PRERELEASE_TAGS=$(echo "$ALL_TAGS" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+-(alpha|rc)\.[0-9]+$' || true)
270+
294271
for TAG in $FLOATING_TAGS; do
295-
echo "❌ Deleting tag: $IMAGE:$TAG"
296-
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
297-
"https://hub.docker.com/v2/repositories/$USERNAME/$REPO_NAME/tags/$TAG/" \
298-
-H "Authorization: JWT $TOKEN")
299-
300-
if [ "$RESPONSE" = "204" ]; then
301-
echo "✅ Successfully deleted $IMAGE:$TAG"
302-
elif [ "$RESPONSE" = "404" ]; then
303-
echo "⚠️ Tag $TAG not found (already deleted or never pushed)"
272+
echo "🔁 Handling floating tag: $TAG"
273+
274+
case "$TAG" in
275+
dev)
276+
TARGET=$(echo "$PRERELEASE_TAGS" | grep 'alpha' | sort -Vr | head -n1)
277+
;;
278+
stage)
279+
TARGET=$(echo "$PRERELEASE_TAGS" | grep 'rc' | sort -Vr | head -n1)
280+
;;
281+
latest)
282+
TARGET=$(echo "$RELEASE_TAGS" | sort -Vr | head -n1)
283+
;;
284+
*)
285+
echo "⚠️ Unknown floating tag: $TAG"
286+
continue
287+
;;
288+
esac
289+
290+
if [ -n "$TARGET" ]; then
291+
echo "🔄 Re-pointing $TAG to $TARGET as multi-platform manifest"
292+
echo "$PASSWORD" | docker login -u "$USERNAME" --password-stdin
293+
docker buildx imagetools create \
294+
--tag "$IMAGE:$TAG" \
295+
"$IMAGE:$TARGET"
296+
docker logout
304297
else
305-
echo "❌ Failed to delete tag $TAG (HTTP $RESPONSE)"
298+
echo "🗑️ No matching version for $TAG. Deleting..."
299+
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
300+
"https://hub.docker.com/v2/repositories/$USERNAME/$REPO_NAME/tags/$TAG/" \
301+
-H "Authorization: JWT $TOKEN")
302+
if [ "$RESPONSE" = "204" ]; then
303+
echo "✅ Deleted $IMAGE:$TAG"
304+
elif [ "$RESPONSE" = "404" ]; then
305+
echo "⚠️ Tag $TAG not found"
306+
else
307+
echo "❌ Failed to delete $TAG (HTTP $RESPONSE)"
308+
fi
306309
fi
307310
done
308-

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,7 @@ ips_blocked.json
171171

172172
firewall-events.json
173173
.DS_Store
174-
DS_Store
174+
DS_Store
175+
176+
.build
177+
.secrets

0 commit comments

Comments
 (0)