-
Notifications
You must be signed in to change notification settings - Fork 7
/
Earthfile
935 lines (807 loc) · 29 KB
/
Earthfile
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
VERSION 0.8
LOCALLY
# chemins vers les modules front
ARG --global APP_DIR='./app.territoiresentransitions.react'
ARG --global BACKEND_DIR='./backend'
ARG --global SITE_DIR='./packages/site'
ARG --global AUTH_DIR='./packages/auth'
ARG --global PANIER_DIR='./packages/panier'
ARG --global UI_DIR='./packages/ui'
ARG --global API_DIR='./packages/api'
ARG --global BUSINESS_DIR='./business'
# paramètres de la base de registre des images docker générées
ARG --global REGISTRY='ghcr.io'
ARG --global REG_USER='territoiresentransitions'
ARG --global REG_TARGET=$REGISTRY/$REG_USER
# tags appliqués aux images docker générées
ARG --global ENV_NAME="dev"
ARG --global FRONT_DEPS_TAG=$(openssl dgst -sha256 -r ./pnpm-lock.yaml | head -c 7 ; echo)
ARG --global FRONT_DEPS_IMG_NAME=$REG_TARGET/front-deps:$FRONT_DEPS_TAG
ARG --global APP_TAG=$ENV_NAME-$FRONT_DEPS_TAG-$(sh ./subdirs_hash.sh $APP_DIR,$UI_DIR,$API_DIR)
ARG --global APP_IMG_NAME=$REG_TARGET/app:$APP_TAG
ARG --global DEPLOYMENT_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# ARG --global GIT_COMMIT_SHORT_SHA=$(git rev-parse --short HEAD)
# ARG --global GIT_COMMIT_TIMESTAMP=$(git show -s --format=%cI HEAD)
ARG --global APPLICATION_VERSION=$(git describe --tags --always)
# TODO changer le tag
ARG --global BACKEND_IMG_NAME=$REG_TARGET/backend:$ENV_NAME-$(sh ./subdirs_hash.sh $BACKEND_DIR)
ARG --global SITE_IMG_NAME=$REG_TARGET/site:$ENV_NAME-$FRONT_DEPS_TAG-$(sh ./subdirs_hash.sh $SITE_DIR,$UI_DIR,$API_DIR)
ARG --global AUTH_IMG_NAME=$REG_TARGET/auth:$ENV_NAME-$FRONT_DEPS_TAG-$(sh ./subdirs_hash.sh $AUTH_DIR,$UI_DIR,$API_DIR)
ARG --global PANIER_IMG_NAME=$REG_TARGET/panier:$ENV_NAME-$FRONT_DEPS_TAG-$(sh ./subdirs_hash.sh $PANIER_DIR,$UI_DIR,$API_DIR)
ARG --global STORYBOOK_TAG=$ENV_NAME-$FRONT_DEPS_TAG-$(sh ./subdirs_hash.sh $UI_DIR)
ARG --global STORYBOOK_IMG_NAME=$REG_TARGET/storybook:$STORYBOOK_TAG
ARG --global BUSINESS_IMG_NAME=$REG_TARGET/business:$ENV_NAME-$(sh ./subdirs_hash.sh $BUSINESS_DIR)
ARG --global DL_TAG=$ENV_NAME-$(sh ./subdirs_hash.sh data_layer)
ARG --global DB_SAVE_IMG_NAME=$REG_TARGET/db-save:$DL_TAG
ARG --global DB_VOLUME_NAME=supabase_db_tet
ARG --global GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
postgres:
FROM postgres:15
psql-build:
FROM +postgres
ENTRYPOINT ["psql"]
SAVE IMAGE psql:latest
sqitch-build:
FROM +postgres
RUN apt-get update
RUN apt-get install -y curl build-essential cpanminus perl perl-doc libdbd-pg-perl postgresql-client
RUN cpanm --quiet --notest App::Sqitch
ENTRYPOINT ["sqitch"]
CMD ["help"]
SAVE IMAGE --cache-from=$REG_TARGET/sqitch:15 --push $REG_TARGET/sqitch:15
sqitch-builder:
LOCALLY
DO +BUILD_IF_NO_IMG --IMG_NAME=sqitch --IMG_TAG=15 --BUILD_TARGET=sqitch-build
db-deploy-build:
FROM +sqitch-build
COPY sqitch.conf ./sqitch.conf
COPY ./data_layer/sqitch ./data_layer/sqitch
SAVE IMAGE --push $REG_TARGET/db-deploy:$DL_TAG
sqitch-local-build:
# Build sqitch avec postgres 15 et les migrations
#
# Utilisation: se mettre sur la bonne branche puis lancer :
# earthly +sqitch-local-build
# docker run sqitch $sandbox status
FROM +sqitch-build
COPY sqitch.conf ./sqitch.conf
COPY ./data_layer/sqitch ./data_layer/sqitch
SAVE IMAGE sqitch
pg-tap-build:
FROM +postgres
RUN apt-get update
RUN apt-get install cpanminus -y
RUN cpanm TAP::Parser::SourceHandler::pgTAP
ENTRYPOINT ["pg_prove"]
SAVE IMAGE --push $REG_TARGET/pg-tap:15
pg-tap-builder:
LOCALLY
DO +BUILD_IF_NO_IMG --IMG_NAME=pg-tap --IMG_TAG=15 --BUILD_TARGET=pg-tap-build
db-test-build:
FROM +pg-tap-build
CMD ["./tests/collectivite/collectivite_test.sql"]
COPY ./data_layer/tests ./tests
SAVE IMAGE db-test:latest
db-test:
ARG --required DB_URL
ARG network=host
LOCALLY
RUN earthly +db-test-build
RUN docker run --rm \
--network $network \
--env PGHOST=$(echo $DB_URL | cut -d@ -f2 | cut -d: -f1) \
--env PGPORT=$(echo $DB_URL | cut -d: -f4 | cut -d/ -f1) \
--env PGUSER=$(echo $DB_URL | cut -d: -f3 | cut -d@ -f1) \
--env PGPASSWORD=$(echo $DB_URL | cut -d: -f3 | cut -d@ -f1) \
--env PGDATABASE=$(echo $DB_URL | cut -d/ -f4) \
db-test:latest
db-deploy:
ARG --required DB_URL
ARG network=host
ARG to=@HEAD
LOCALLY
DO +BUILD_IF_NO_IMG --IMG_NAME=db-deploy --IMG_TAG=$DL_TAG --BUILD_TARGET=db-deploy-build
RUN docker run --rm \
--network $network \
--env SQITCH_TARGET=db:$DB_URL \
$REG_TARGET/db-deploy:$DL_TAG deploy --to $to --mode change
db-deploy-test:
ARG --required DB_URL
ARG network=host
ARG tag=v2.92.0
LOCALLY
RUN earthly --use-inline-cache +db-deploy-build
RUN docker run --rm \
--network $network \
--env SQITCH_TARGET=db:$DB_URL \
$REG_TARGET/db-deploy:$DL_TAG deploy --mode change
RUN docker run --rm \
--network $network \
--env SQITCH_TARGET=db:$DB_URL \
$REG_TARGET/db-deploy:$DL_TAG revert --to @$tag --y
RUN docker run --rm \
--network $network \
--env SQITCH_TARGET=db:$DB_URL \
$REG_TARGET/db-deploy:$DL_TAG deploy --mode change --verify
seed-build:
FROM +postgres
ENV SKIP_TEST_DOMAIN=0
ENV PG_URL
COPY ./data_layer/seed /seed
ENTRYPOINT sh ./seed/seed.sh
SAVE IMAGE seed:latest
seed:
ARG --required DB_URL
ARG network=host
LOCALLY
RUN earthly +seed-build
RUN docker run --rm \
--network $network \
--env PG_URL=$DB_URL \
seed:latest
seed-geojson:
ARG --required DB_URL
ARG network=host
LOCALLY
RUN earthly +seed-build
RUN docker run --rm \
--network $network \
--env PG_URL=$DB_URL \
--entrypoint sh \
seed:latest ./seed/geojson.sh
load-json-build:
FROM curlimages/curl:8.1.0
ENV SERVICE_ROLE_KEY
ENV API_URL
COPY ./data_layer/content /content
COPY ./data_layer/scripts/load_json_content.sh /content/load.sh
ENTRYPOINT sh /content/load.sh
SAVE IMAGE load-json:latest
load-json:
ARG --required SERVICE_ROLE_KEY
ARG --required API_URL
ARG network=host
LOCALLY
RUN earthly +load-json-build
RUN docker run --rm \
--network $network \
--env API_URL=$API_URL \
--env SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY \
load-json:latest db-deploy --mode change
update-scores:
ARG --required DB_URL
ARG count=20
ARG network=host
LOCALLY
RUN earthly +psql-build
RUN docker run --rm \
--network $network \
psql:latest $DB_URL -v ON_ERROR_STOP=1 \
-c "select evaluation.update_late_collectivite_scores($count);"
refresh-views:
ARG --required DB_URL
ARG network=host
LOCALLY
RUN earthly +psql-build
RUN docker run --rm \
--network $network \
psql:latest $DB_URL -v ON_ERROR_STOP=1 \
-c "refresh materialized view stats.collectivite; refresh materialized view site_labellisation;"
business-build:
FROM python:3.10.10
ENV SUPABASE_URL
ENV SUPABASE_KEY
WORKDIR /business
COPY $BUSINESS_DIR .
RUN pip install pipenv
RUN PIPENV_VENV_IN_PROJECT=1 pipenv install
EXPOSE 8888
CMD pipenv run python ./evaluation_server.py
SAVE IMAGE --cache-from=$BUSINESS_IMG_NAME --push $BUSINESS_IMG_NAME
business:
ARG --required SERVICE_ROLE_KEY
ARG url=http://supabase_kong_tet:8000
ARG network=supabase_network_tet
LOCALLY
RUN earthly +business-build
RUN docker run -d --rm \
--name business_tet \
--network $network \
--publish 8888:8888 \
--env SUPABASE_URL=$url \
--env SUPABASE_KEY=$SERVICE_ROLE_KEY \
$BUSINESS_IMG_NAME
business-test-build:
FROM +business-build
COPY ./markdown /markdown
RUN pip install pytest
CMD pipenv run pytest tests
SAVE IMAGE business-test:latest
business-test:
ARG --required SERVICE_ROLE_KEY
ARG url=http://supabase_kong_tet:8000
ARG network=supabase_network_tet
LOCALLY
RUN earthly +business-test-build
RUN docker run --rm \
--name business-test_tet \
--network $network \
--env SUPABASE_URL=$url \
--env SUPABASE_KEY=$SERVICE_ROLE_KEY \
business-test:latest
business-parse:
FROM +business-build
COPY ./markdown /markdown
RUN mkdir /content
RUN sh ./referentiel_parse_all.sh
SAVE ARTIFACT /content AS LOCAL ./data_layer/content
SAVE ARTIFACT /content AS LOCAL $BUSINESS_DIR/tests/data/dl_content
node-alpine:
# Pinning the docker image version to node:20.15.1-alpine
# because of existing memory leaks from using the fetch() API in node 20.16.0
# https://www.reddit.com/r/node/comments/1ejzn64/sudden_inexplicable_memory_leak_on_new_builds/
FROM node:20.15.1-alpine
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
node-alpine-with-prod-deps:
FROM +node-alpine
COPY pnpm-lock.yaml ./
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable pnpm
RUN pnpm fetch --prod
COPY package.json ./
RUN pnpm install -r --offline --prod
node-alpine-with-all-deps:
FROM +node-alpine-with-prod-deps
RUN pnpm install --frozen-lockfile
COPY *.json ./
COPY vitest.* ./
# Copy shared libraries
COPY $API_DIR $API_DIR
COPY $UI_DIR $UI_DIR
# Temporarily consider the Backend as a shared library.
# The app build needs it to resolve the import of the trpc AppRouter.
COPY $BACKEND_DIR $BACKEND_DIR
# construit l'image de base pour les images utilisant node
node-fr:
ARG TARGETPLATFORM
# `--PLATFORM=<platform>` pour forcer la plateforme cible, sinon ce sera la
# même que celle sur laquelle le build est fait
ARG PLATFORM=$TARGETPLATFORM
FROM --platform=$PLATFORM node:20-slim
# locale FR pour que les tests e2e relatifs au formatage localisés des dates et des valeurs numériques puissent passer
ENV LANG fr_FR.UTF-8
RUN apt-get update && apt-get install -y locales dumb-init && rm -rf /var/lib/apt/lists/* && locale-gen "fr_FR.UTF-8"
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable pnpm
WORKDIR /app
prod-deps:
FROM +node-fr
# See https://pnpm.io/cli/fetch
COPY pnpm-lock.yaml ./
RUN pnpm fetch --prod
COPY package.json ./
RUN pnpm install -r --offline --prod
# construit l'image contenant les dépendances des modules front
front-deps:
FROM +prod-deps
RUN pnpm install --frozen-lockfile
COPY *.json ./
COPY vitest.* ./
# Copy only shared libraries
COPY $API_DIR $API_DIR
COPY $UI_DIR $UI_DIR
front-deps-builder:
LOCALLY
DO +BUILD_IF_NO_IMG --IMG_NAME=front-deps --IMG_TAG=$FRONT_DEPS_TAG --BUILD_TARGET=front-deps
# APP ENTRYPOINTS
# ---------------
app-docker:
BUILD --pass-args ./app.territoiresentransitions.react+docker
app-deploy:
ARG --required KOYEB_API_KEY
BUILD --pass-args ./app.territoiresentransitions.react+deploy
# BACKEND ENTRYPOINTS
# -------------------
backend-docker:
BUILD --pass-args ./backend+docker
backend-deploy:
ARG --required KOYEB_API_KEY
ARG --required TRAJECTOIRE_SNBC_SHEET_ID
ARG --required TRAJECTOIRE_SNBC_XLSX_ID
ARG --required TRAJECTOIRE_SNBC_RESULT_FOLDER_ID
BUILD --pass-args ./backend+deploy
backend-test:
ARG --required TRAJECTOIRE_SNBC_SHEET_ID
ARG --required TRAJECTOIRE_SNBC_XLSX_ID
ARG --required TRAJECTOIRE_SNBC_RESULT_FOLDER_ID
ARG --required REFERENTIEL_TE_SHEET_ID
ARG --required GCLOUD_SERVICE_ACCOUNT_KEY
ARG --required SUPABASE_DATABASE_URL
ARG --required SUPABASE_URL
ARG --required SUPABASE_ANON_KEY
ARG --required SUPABASE_SERVICE_ROLE_KEY
ARG --required SUPABASE_JWT_SECRET
ARG --required BREVO_API_KEY
ARG --required DIRECTUS_API_KEY
BUILD --pass-args ./backend+test
# PANIER ENTRYPOINTS
# ------------------
panier-docker:
BUILD --pass-args ./packages/panier+docker
panier-deploy:
ARG --required KOYEB_API_KEY
BUILD --pass-args ./packages/panier+deploy
# lance l'image du panier en local
panier-run:
ARG network=supabase_network_tet
LOCALLY
RUN docker run -d --rm \
--name panier_tet \
--network $network \
--publish 3002:3000 \
$PANIER_IMG_NAME
# SITE ENTRYPOINTS
# ----------------
site-docker:
BUILD --pass-args ./packages/site+docker
site-deploy:
ARG --required KOYEB_API_KEY
BUILD --pass-args ./packages/site+deploy
site-run: ## construit et lance l'image du site en local
ARG network=supabase_network_tet
LOCALLY
RUN docker run -d --rm \
--name site_tet \
--network $network \
--publish 3001:80 \
$SITE_IMG_NAME
app-run: ## construit et lance l'image de l'app en local
ARG --required ANON_KEY
ARG --required API_URL
ARG network=supabase_network_tet
LOCALLY
# DO +BUILD_IF_NO_IMG --IMG_NAME=front-deps --IMG_TAG=$FRONT_DEPS_TAG --BUILD_TARGET=front-deps
DO +BUILD_IF_NO_IMG --IMG_NAME=app --IMG_TAG=$APP_TAG --BUILD_TARGET=app-docker
ARG kong_url=http://supabase_kong_tet:8000
RUN docker run -d --rm \
--name app_tet \
--network $network \
--publish 3000:3000 \
$APP_IMG_NAME
app-test-build: ## construit une image pour exécuter les tests unitaires de l'app
FROM +front-deps
ENV NEXT_PUBLIC_SUPABASE_URL
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY
# copie les sources du module à tester
COPY $APP_DIR $APP_DIR
COPY $API_DIR $API_DIR
COPY $UI_DIR $UI_DIR
COPY ./vitest.workspace.ts ./
# la commande utilisée pour lancer les tests
CMD pnpm run test:app
SAVE IMAGE app-test:latest
app-test: ## lance les tests unitaires de l'app
LOCALLY
RUN earthly +app-test-build
RUN docker run --rm \
--name app-test_tet \
--env CI=true \ # désactive le mode watch quand on lance la commande en local
--env NEXT_PUBLIC_SUPABASE_URL='http://fake' \
--env NEXT_PUBLIC_SUPABASE_ANON_KEY='fake' \
app-test:latest
package-api-test-build: ## construit une image pour exécuter les tests d'intégration de l'api
FROM +front-deps
ENV SUPABASE_URL
ENV SUPABASE_ANON_KEY
ENV SUPABASE_SERVICE_ROLE_KEY
# copie les sources du module à tester
COPY $API_DIR $API_DIR
# la commande utilisée pour lancer les tests
CMD pnpm run test:api
SAVE IMAGE package-api-test:latest
package-api-test: ## lance les tests d'intégration de l'api
ARG --required API_URL
ARG --required ANON_KEY
ARG --required SERVICE_ROLE_KEY
ARG network=host
LOCALLY
RUN earthly +package-api-test-build
RUN docker run --rm \
--name package-api-test_tet \
--network $network \
--env SUPABASE_URL=$API_URL \
--env SUPABASE_KEY=$ANON_KEY \
--env SUPABASE_SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY \
package-api-test:latest
auth-build: ## construit l'image du module d'authentification
ARG PLATFORM
ARG --required ANON_KEY
ARG --required API_URL
ARG POSTHOG_HOST
ARG POSTHOG_KEY
ARG vars
FROM +front-deps
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$ANON_KEY
ENV NEXT_PUBLIC_SUPABASE_URL=$API_URL
ENV NEXT_PUBLIC_POSTHOG_HOST=$POSTHOG_HOST
ENV NEXT_PUBLIC_POSTHOG_KEY=$POSTHOG_KEY
ENV NEXT_TELEMETRY_DISABLED=1
ENV PUBLIC_PATH="/app/packages/auth/public"
ENV PORT=80
EXPOSE $PORT
# copie les sources des modules à construire
COPY $AUTH_DIR $AUTH_DIR
COPY $UI_DIR $UI_DIR
COPY $API_DIR $API_DIR
RUN pnpm run build:auth
CMD ["dumb-init", "./node_modules/.bin/next", "start", "./packages/auth/"]
SAVE IMAGE --cache-from=$AUTH_IMG_NAME --push $AUTH_IMG_NAME
auth-run: ## construit et lance l'image du module d'authentification en local
ARG network=supabase_network_tet
LOCALLY
RUN docker run -d --rm \
--name auth_tet \
--network $network \
--publish 3003:80 \
$AUTH_IMG_NAME
package-ui-storybook-test:
ARG PLATFORM
ARG PORT=6007
FROM +front-deps
RUN pnpm exec playwright install --with-deps chromium
RUN pnpm nx build-storybook @tet/ui --quiet
EXPOSE $PORT
RUN pnpx concurrently -k -s first -n "SB,TEST" \
"pnpx http-server $UI_DIR/storybook-static --port $PORT --silent" \
"pnpx wait-on tcp:127.0.0.1:$PORT && pnpm nx test-storybook @tet/ui --url http://127.0.0.1:$PORT" || true
curl-test-build:
FROM curlimages/curl:8.1.0
USER root
RUN apk --update add jq
COPY ./data_layer/scripts/curl_test.sh /curl_test.sh
ENTRYPOINT sh ./curl_test.sh
SAVE IMAGE curl-test:latest
curl-test:
ARG --required SERVICE_ROLE_KEY
ARG --required API_URL
ARG network=supabase_network_tet
ARG internal_url=http://supabase_kong_tet:8000
LOCALLY
RUN earthly +curl-test-build
RUN docker run --rm \
--name curl_test_tet \
--network $network \
--env API_KEY=$SERVICE_ROLE_KEY \
--env URL=$internal_url \
curl-test:latest
RUN docker run --rm \
--name curl_test_tet \
--network host \
--env API_KEY=$SERVICE_ROLE_KEY \
--env URL=$API_URL \
curl-test:latest
api-test-build:
FROM denoland/deno
ENV SUPABASE_URL
ENV SUPABASE_KEY
ENV SERVICE_ROLE_KEY
WORKDIR tests
COPY ./api_tests .
RUN deno cache tests/base/smoke.test.ts
RUN deno cache tests/base/utilisateur.test.ts
CMD deno
SAVE IMAGE api-test:latest
api-test:
ARG --required SERVICE_ROLE_KEY
ARG --required API_URL
ARG network=host
ARG tests='base droit historique plan_action scoring indicateurs labellisation utilisateur'
LOCALLY
RUN earthly +api-test-build
FOR test IN $tests
RUN echo "Running tests for tests/$test'"
RUN docker run --rm \
--name api_test_tet \
--network $network \
--env SUPABASE_URL=$API_URL \
--env SUPABASE_KEY=$SERVICE_ROLE_KEY \
--env SUPABASE_SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY \
api-test:latest test -A tests/$test/*.test.ts --location 'http://localhost'
END
api-crud-test:
ARG --required ANON_KEY
ARG --required API_URL
ARG network=host
LOCALLY
RUN earthly +api-test-build
RUN echo "Running tests crud'"
RUN docker run --rm \
--name api_crud_test_tet \
--network $network \
--env SUPABASE_URL=$API_URL \
--env SUPABASE_KEY=$ANON_KEY \
api-test:latest test -A tests/crud/crud.test.ts --location 'http://localhost' -- elements:axe
cypress-wip:
FROM cypress/included:12.3.0
ENV ELECTRON_EXTRA_LAUNCH_ARGS="--disable-gpu"
WORKDIR /e2e
COPY ./e2e/package.json /e2e/package.json
RUN npm install
COPY ./e2e/ /e2e
RUN npm test
gen-types: ## génère le typage à partir de la base de données
LOCALLY
IF [ "$CI" = "true" ]
RUN supabase gen types typescript --local --schema public --schema labellisation > $API_DIR/src/database.types.ts
ELSE
RUN pnpx supabase gen types typescript --local --schema public --schema labellisation > $API_DIR/src/database.types.ts
END
RUN cp $API_DIR/src/database.types.ts ./api_tests/lib/database.types.ts
RUN cp $API_DIR/src/database.types.ts ./supabase/functions/_shared/database.types.ts
setup-env:
LOCALLY
RUN earthly +stop
IF [ "$CI" = "true" ]
RUN supabase start
RUN supabase status -o env > .arg
ELSE
RUN pnpm install
RUN pnpx supabase start
RUN pnpx supabase status -o env > .arg
END
RUN export $(cat .arg | xargs) && sh ./make_dot_env.sh
RUN earthly +stop
dev:
LOCALLY
ARG --required DB_URL
ARG --required API_URL
ARG --required ANON_KEY
ARG --required SERVICE_ROLE_KEY
ARG network=host
ARG stop=yes
ARG datalayer=yes
ARG business=yes
ARG app=no
ARG auth=no
ARG eco=no
ARG fast=no
ARG faster=no
ARG version=HEAD # version du plan
IF [ "$fast" = "yes" -a "$faster" = "yes" ]
RUN echo "Les options fast et faster sont mutuellement exclusives"
RUN exit 1
END
IF [ "$stop" = "yes" ]
RUN earthly +stop --npx=$npx
END
IF [ "$datalayer" = "yes" ]
IF [ "$fast" = "yes" ]
RUN earthly +restore-state
END
IF [ "$faster" = "yes" ]
RUN earthly +restore-db --pull=yes
END
IF [ "$CI" = "true" ]
RUN supabase start
RUN docker stop supabase_studio_tet
RUN docker stop supabase_pg_meta_tet
ELSE
RUN pnpx supabase start
END
IF [ "$eco" = "yes" ]
RUN docker stop supabase_imgproxy_tet
RUN docker stop supabase_studio_tet
RUN docker stop supabase_pg_meta_tet
END
IF [ "$faster" = "no" ]
RUN earthly +db-deploy --to @$version --DB_URL=$DB_URL
RUN earthly +load-json --SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY --API_URL=$API_URL
# Seed si aucune collectivité en base
RUN docker run --rm \
--network $network \
psql:latest $DB_URL -v ON_ERROR_STOP=1 \
-c "select 1 / count(*) from collectivite;" \
|| earthly +seed --DB_URL=$DB_URL
END
END
IF [ "$business" = "yes" ]
RUN earthly +business --SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY
RUN earthly +update-scores --DB_URL=$DB_URL
END
IF [ "$app" = "yes" ]
RUN earthly +app-run --API_URL=$API_URL --ANON_KEY=$ANON_KEY
END
IF [ "$auth" = "yes" ]
RUN earthly +auth-run --API_URL=$API_URL --ANON_KEY=$ANON_KEY
END
RUN earthly +refresh-views --DB_URL=$DB_URL
BUILD_IF_NO_IMG:
FUNCTION
ARG --required IMG_NAME
ARG --required IMG_TAG
ARG --required BUILD_TARGET
ARG pull=yes
RUN echo "Searching for image $IMG_NAME:$IMG_TAG ..."
IF [ "docker image ls | grep $IMG_NAME | grep $IMG_TAG" ]
RUN echo "Image found, skipping"
ELSE
IF [ "$pull" = "yes" ]
RUN echo "Image not found, trying to pull $REG_TARGET/$IMG_NAME:$IMG_TAG"
IF [ "$CI" = "true" ]
RUN docker pull $REG_TARGET/$IMG_NAME:$IMG_TAG || earthly --push +$BUILD_TARGET
ELSE
RUN docker pull $REG_TARGET/$IMG_NAME:$IMG_TAG || earthly +$BUILD_TARGET
END
ELSE
RUN echo "Image not found, building +$BUILD_TARGET"
IF [ "$CI" = "true" ]
RUN earthly --push +$BUILD_TARGET
ELSE
RUN earthly +$BUILD_TARGET
END
END
END
stop:
LOCALLY
IF [ "$CI" = "true" ]
RUN supabase stop
ELSE
RUN pnpx supabase stop
END
RUN docker ps --filter name=_tet --filter status=running -aq | xargs docker stop | xargs docker rm || exit 0
RUN earthly +clear-state
copy-volume: ## Copie un volume
ARG --required from
ARG --required to
LOCALLY
RUN docker volume rm $to || echo "volume $to not found"
RUN docker volume create --name $to
RUN docker run --rm \
-v $from:/from \
-v $to:/to \
alpine ash -c "cd /from ; cp -av . /to"
save-db: ## Sauvegarde la db dans une image en vue de la publier
ARG push=no
LOCALLY
RUN docker run \
-v $DB_VOLUME_NAME:/volume \
alpine ash -c "mkdir /save ; cd /volume ; cp -av . /save"
RUN docker commit \
$(docker ps -lq) \
$DB_SAVE_IMG_NAME
RUN docker container rm $(docker ps -lq)
IF [ "$push" = "yes" ]
RUN docker push $DB_SAVE_IMG_NAME
END
restore-db: ## Restaure la db depuis une image
ARG pull=no
LOCALLY
IF [ "$pull" = "yes" ]
RUN docker pull $DB_SAVE_IMG_NAME || echo "Image $DB_SAVE_IMG_NAME not found in registry"
END
IF [ "docker image ls | grep db-save | grep $DL_TAG" ]
RUN echo "Image $DB_SAVE_IMG_NAME found, restoring..."
RUN docker volume rm $DB_VOLUME_NAME || echo "Volume $DB_VOLUME_NAME not found"
RUN docker volume create --name $DB_VOLUME_NAME
RUN docker run --rm \
-v $DB_VOLUME_NAME:/volume \
$DB_SAVE_IMG_NAME ash -c "cd /save ; cp -av . /volume"
ELSE
RUN echo "Image $DB_SAVE_IMG_NAME not found, cannot restore"
RUN exit 1
END
prepare-faster:
ARG push=no
ARG stop=yes
ARG --required DB_URL
ARG --required SERVICE_ROLE_KEY
ARG --required API_URL
ARG --required ANON_KEY
LOCALLY
IF [ "$push" = "yes" ]
RUN docker pull $DB_SAVE_IMG_NAME || echo "Image $DB_SAVE_IMG_NAME not found in registry"
END
IF [ "docker image ls | grep db-save | grep $DL_TAG" ]
RUN echo "Image $DB_SAVE_IMG_NAME found, skipping..."
ELSE
RUN echo "Image $DB_SAVE_IMG_NAME not found, start datalayer"
RUN earthly +dev \
--stop=$stop --business=no --app=no --fast=no \
--DB_URL=$DB_URL --ANON_KEY=$ANON_KEY --SERVICE_ROLE_KEY=$SERVICE_ROLE_KEY --API_URL=$API_URL
RUN earthly +save-db --push=$push
END
prepare-fast:
ARG version # version du plan
LOCALLY
# si la version du plan n'est pas spécifiée on utilise le tag courant
ARG v=$(if [ -z $version ]; then sqitch status | grep @v | sed -E 's/.*@(v[0-9.]*)/\1/'; else echo $version; fi)
RUN earthly +dev --stop=yes --business=no --app=no --fast=no --version=$v
RUN earthly +save-state
clear-state:
ARG saved=no
LOCALLY
RUN docker volume rm supabase_db_tet || echo "could not clear current state: not found"
RUN docker volume rm supabase_storage_tet || echo "could not clear current state: not found"
IF [ "$saved" = "yes" ]
RUN docker volume rm supabase_db_tet_save || echo "could not clear saved state: not found"
RUN docker volume rm supabase_storage_tet_save || echo "could not clear saved state: not found"
END
save-state:
LOCALLY
RUN earthly +copy-volume --from supabase_db_tet --to supabase_db_tet_save
RUN earthly +copy-volume --from supabase_storage_tet --to supabase_storage_tet_save
restore-state:
LOCALLY
RUN earthly +copy-volume --from supabase_db_tet_save --to supabase_db_tet || echo "could not restore state"
RUN earthly +copy-volume --from supabase_storage_tet_save --to supabase_storage_tet || echo "could not restore state"
test:
LOCALLY
RUN earthly +curl-test
RUN earthly +db-test
RUN earthly +business-test
RUN earthly +api-test
RUN earthly +db-deploy-test
RUN earthly +app-test
docker-dev-login: ## permet de s'identifier sur la registry
ARG --required GH_USER
ARG --required GH_TOKEN
LOCALLY
RUN docker login $REGISTRY -u $GH_USER -p $GH_TOKEN
koyeb-bin: ## extrait le binaire koyeb de l'image officielle
FROM koyeb/koyeb-cli:latest
SAVE ARTIFACT ./koyeb
koyeb:
ARG --required KOYEB_API_KEY
FROM alpine
COPY +koyeb-bin/koyeb ./
RUN echo "token: $KOYEB_API_KEY" > ~/.koyeb.yaml
auth-deploy:
ARG --required KOYEB_API_KEY
FROM +koyeb
RUN ./koyeb services update $ENV_NAME-auth/front --docker $AUTH_IMG_NAME
app-deploy-test: ## Déploie une app de test et crée une app Koyeb si nécessaire
ARG --required KOYEB_API_KEY
ARG --required AUTH_URL
ARG --required BACKEND_URL
ARG --required PANIER_URL
LOCALLY
# Limite des noms dans Koyeb : 23 caractères.
# Comme on prefixe avec `test-app-`, on garde 14 caractères max dans le nom de la branche.
# En octobre 2024, Koyeb applique cette règle sur les noms des apps déployées :
# ^[a-z0-9]+([.-][a-z0-9]+)*$ and from 3 to 23 chars
# (info récupérée auprès du service support)
ARG name=$(git rev-parse --abbrev-ref HEAD | sed 's/[^a-zA-Z1-9]//g' | head -c 14 | tr '[:upper:]' '[:lower:]')
FROM +koyeb --KOYEB_API_KEY=$KOYEB_API_KEY
IF [ "./koyeb apps list | grep test-app-$name" ]
RUN echo "Test app already deployed on Koyeb at test-app-$name, updating..."
RUN /koyeb services update test-app-$name/test-app-$name --docker $APP_IMG_NAME \
--env NEXT_PUBLIC_AUTH_URL=$AUTH_URL \
--env NEXT_PUBLIC_BACKEND_URL=$BACKEND_URL \
--env NEXT_PUBLIC_PANIER_URL=$PANIER_URL
ELSE
RUN echo "Test app not found on Koyeb at test-app-$name, creating with $APP_IMG_NAME..."
RUN /koyeb apps init "test-app-$name" \
--docker "$APP_IMG_NAME" --docker-private-registry-secret ghcr \
--type web --port 3000:http --route /:3000 --env PORT=3000 \
--env NEXT_PUBLIC_AUTH_URL=$AUTH_URL \
--env NEXT_PUBLIC_BACKEND_URL=$BACKEND_URL \
--env NEXT_PUBLIC_PANIER_URL=$PANIER_URL \
--regions par
END
app-destroy-test: ## Supprime l'app de test
ARG --required KOYEB_API_KEY
LOCALLY
ARG name=$(git rev-parse --abbrev-ref HEAD | sed 's/[^a-zA-Z1-9]//g' | head -c 14 | tr '[:upper:]' '[:lower:]')
FROM +koyeb
RUN ./koyeb apps list # Le IF suivant ne fonctionne pas sans lister avant.
IF [ "./koyeb apps list | grep test-app-$name" ]
RUN echo "Test app already deployed on Koyeb at test-app-$name, deleting..."
RUN /koyeb apps delete test-app-$name
END
help: ## affiche ce message d'aide
LOCALLY
RUN grep -h "##" ./Earthfile | grep -v grep | sed -e 's/##//'