@@ -15,7 +15,7 @@ concurrency:
1515 cancel-in-progress : true
1616
1717env :
18- CI_IMAGE : ghcr.io/simonblanke /hyperactive-ci
18+ CI_IMAGE : ghcr.io/hyperactive-project /hyperactive-ci
1919
2020jobs :
2121 # ===========================================================================
3333 docs : ${{ steps.filter.outputs.docs }}
3434 examples : ${{ steps.filter.outputs.examples }}
3535 any_src : ${{ steps.filter.outputs.any_src }}
36+ deps_changed : ${{ steps.filter.outputs.deps_changed }}
3637 steps :
3738 - uses : actions/checkout@v4
3839 with :
@@ -111,14 +112,84 @@ jobs:
111112 echo "any_src=false" >> $GITHUB_OUTPUT
112113 fi
113114
115+ # dependencies changed (triggers CI image rebuild)
116+ if echo "$CHANGED_FILES" | grep -qE "^pyproject.toml$|^docs/requirements.txt$|^.github/docker/Dockerfile$"; then
117+ echo "deps_changed=true" >> $GITHUB_OUTPUT
118+ echo "Dependencies changed - CI images will be rebuilt"
119+ else
120+ echo "deps_changed=false" >> $GITHUB_OUTPUT
121+ fi
122+
123+ # ===========================================================================
124+ # STAGE 0.5: Rebuild CI images if dependencies changed
125+ # ===========================================================================
126+ rebuild-ci-images :
127+ name : rebuild-ci-images
128+ needs : [detect-changes]
129+ if : needs.detect-changes.outputs.deps_changed == 'true'
130+ runs-on : ubuntu-latest
131+ strategy :
132+ fail-fast : false
133+ matrix :
134+ python-version : ["3.10", "3.11", "3.12", "3.13", "3.14"]
135+ permissions :
136+ contents : read
137+ packages : write
138+
139+ steps :
140+ - name : Checkout repository
141+ uses : actions/checkout@v4
142+
143+ - name : Set up Docker Buildx
144+ uses : docker/setup-buildx-action@v3
145+
146+ - name : Log in to Container Registry
147+ uses : docker/login-action@v3
148+ with :
149+ registry : ghcr.io
150+ username : ${{ github.actor }}
151+ password : ${{ secrets.GITHUB_TOKEN }}
152+
153+ - name : Build and push Docker image
154+ uses : docker/build-push-action@v5
155+ with :
156+ context : .
157+ file : .github/docker/Dockerfile
158+ push : true
159+ tags : ghcr.io/hyperactive-project/hyperactive-ci:py${{ matrix.python-version }}
160+ build-args : |
161+ PYTHON_VERSION=${{ matrix.python-version }}
162+ cache-from : type=gha
163+ cache-to : type=gha,mode=max
164+
165+ # Gate job: ensures images are ready before tests run
166+ images-ready :
167+ name : images-ready
168+ needs : [detect-changes, rebuild-ci-images]
169+ if : always()
170+ runs-on : ubuntu-latest
171+ steps :
172+ - name : Check image status
173+ run : |
174+ if [[ "${{ needs.detect-changes.outputs.deps_changed }}" == "true" ]]; then
175+ if [[ "${{ needs.rebuild-ci-images.result }}" != "success" ]]; then
176+ echo "CI image rebuild failed"
177+ exit 1
178+ fi
179+ echo "CI images rebuilt successfully"
180+ else
181+ echo "No dependency changes - using existing CI images"
182+ fi
183+
114184 # ===========================================================================
115- # STAGE 1: Fast checks (code-quality + doctest )
185+ # STAGE 1: Fast checks (code-quality)
116186 # ===========================================================================
117187 code-quality :
118188 name : code-quality
189+ needs : [images-ready]
119190 runs-on : ubuntu-latest
120191 container :
121- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
192+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
122193 steps :
123194 - name : Checkout code
124195 uses : actions/checkout@v4
@@ -158,7 +229,7 @@ jobs:
158229 fail-fast : false
159230
160231 runs-on : ${{ matrix.os }}
161- container : ${{ matrix.os == 'ubuntu-latest' && format('{0}:py{1}', 'ghcr.io/simonblanke /hyperactive-ci', matrix.python-version) || '' }}
232+ container : ${{ matrix.os == 'ubuntu-latest' && format('{0}:py{1}', 'ghcr.io/hyperactive-project /hyperactive-ci', matrix.python-version) || '' }}
162233 timeout-minutes : 30
163234
164235 steps :
@@ -203,7 +274,7 @@ jobs:
203274 fail-fast : false
204275
205276 runs-on : ${{ matrix.os }}
206- container : ${{ matrix.os == 'ubuntu-latest' && format('{0}:py{1}', 'ghcr.io/simonblanke /hyperactive-ci', matrix.python-version) || '' }}
277+ container : ${{ matrix.os == 'ubuntu-latest' && format('{0}:py{1}', 'ghcr.io/hyperactive-project /hyperactive-ci', matrix.python-version) || '' }}
207278 timeout-minutes : 30
208279
209280 steps :
@@ -239,7 +310,7 @@ jobs:
239310 needs : [targeted-tests-gate]
240311 runs-on : ubuntu-latest
241312 container :
242- image : ghcr.io/simonblanke /hyperactive-ci:py${{ matrix.python-version }}
313+ image : ghcr.io/hyperactive-project /hyperactive-ci:py${{ matrix.python-version }}
243314
244315 strategy :
245316 fail-fast : false
@@ -271,7 +342,7 @@ jobs:
271342 if : needs.detect-changes.outputs.core == 'true' || needs.detect-changes.outputs.any_src == 'false'
272343 runs-on : ubuntu-latest
273344 container :
274- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
345+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
275346 timeout-minutes : 10
276347
277348 steps :
@@ -291,7 +362,7 @@ jobs:
291362 if : needs.detect-changes.outputs.sklearn == 'true'
292363 runs-on : ubuntu-latest
293364 container :
294- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
365+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
295366 timeout-minutes : 10
296367
297368 steps :
@@ -311,7 +382,7 @@ jobs:
311382 if : needs.detect-changes.outputs.sktime == 'true'
312383 runs-on : ubuntu-latest
313384 container :
314- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
385+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
315386 timeout-minutes : 10
316387
317388 steps :
@@ -331,7 +402,7 @@ jobs:
331402 if : needs.detect-changes.outputs.skpro == 'true'
332403 runs-on : ubuntu-latest
333404 container :
334- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
405+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
335406 timeout-minutes : 10
336407
337408 steps :
@@ -351,7 +422,7 @@ jobs:
351422 if : needs.detect-changes.outputs.utils == 'true'
352423 runs-on : ubuntu-latest
353424 container :
354- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
425+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
355426 timeout-minutes : 10
356427
357428 steps :
@@ -399,7 +470,7 @@ jobs:
399470 needs : [targeted-tests-gate]
400471 runs-on : ubuntu-latest
401472 container :
402- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
473+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
403474 timeout-minutes : 15
404475
405476 steps :
@@ -425,7 +496,7 @@ jobs:
425496 needs : [targeted-tests-gate]
426497 runs-on : ubuntu-latest
427498 container :
428- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
499+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
429500 timeout-minutes : 20
430501
431502 steps :
@@ -444,7 +515,7 @@ jobs:
444515 needs : [targeted-tests-gate]
445516 runs-on : ubuntu-latest
446517 container :
447- image : ghcr.io/simonblanke /hyperactive-ci:py3.11
518+ image : ghcr.io/hyperactive-project /hyperactive-ci:py3.11
448519 timeout-minutes : 15
449520
450521 steps :
0 commit comments