ci: docker_tag=ext-0.1.2 build(front): image ext, env vars, doc+tests, v0.1.2

This commit is contained in:
Debian Dev4 2025-09-17 04:46:15 +00:00
parent 24698b0b64
commit 2361e184f8
9 changed files with 181 additions and 38 deletions

9
CHANGELOG.md Normal file
View File

@ -0,0 +1,9 @@
## v0.1.1
- Ajout d'une image Docker de production "ext" (Next.js `next start`) lisant les URLs d'API via variables d'environnement, évitant toute référence à `localhost`.
- Remplacement d'URLs codées en dur dans l'écran de connexion email par l'utilisation de `FrontendVariables` et des `NEXT_PUBLIC_*`.
- Documentation `docs/ext.md` ajoutée (build, run, push, variables supportées).
## v0.1.2
- LoginCallback (`index.tsx`) ajusté: suppression de la redirection spéciale `local.4nkweb.com` au profit d'un flux standard basé sur variables d'environnement.

View File

@ -3,6 +3,7 @@ FROM node:19-alpine AS deps
WORKDIR /leCoffre-front WORKDIR /leCoffre-front
COPY package.json ./ COPY package.json ./
COPY package-lock.json ./
RUN apk update && apk add --no-cache openssh-client git RUN apk update && apk add --no-cache openssh-client git
@ -10,7 +11,7 @@ RUN apk update && apk add --no-cache openssh-client git
RUN --mount=type=ssh \ RUN --mount=type=ssh \
mkdir -p /root/.ssh && \ mkdir -p /root/.ssh && \
ssh-keyscan git.4nkweb.com >> /root/.ssh/known_hosts && \ ssh-keyscan git.4nkweb.com >> /root/.ssh/known_hosts && \
npm install --frozen-lockfile npm install --no-audit --no-fund
# Configuration pour le développement # Configuration pour le développement
FROM node:19-alpine AS development FROM node:19-alpine AS development
@ -27,3 +28,70 @@ USER lecoffreuser
CMD ["npm", "run", "dev"] CMD ["npm", "run", "dev"]
EXPOSE 3000 EXPOSE 3000
# --- Build de production
FROM node:19-alpine AS builder
WORKDIR /leCoffre-front
COPY --from=deps /leCoffre-front/node_modules ./node_modules
COPY --from=deps /leCoffre-front/package.json ./package.json
COPY . .
# Arguments/variables d'environnement publics pour le build Next
ARG NEXT_PUBLIC_BACK_API_PROTOCOL
ARG NEXT_PUBLIC_BACK_API_HOST
ARG NEXT_PUBLIC_BACK_API_PORT
ARG NEXT_PUBLIC_BACK_API_ROOT_URL
ARG NEXT_PUBLIC_BACK_API_VERSION
ARG NEXT_PUBLIC_FRONT_APP_HOST
ARG NEXT_PUBLIC_FRONT_APP_PORT
ARG NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT
ARG NEXT_PUBLIC_IDNOT_CLIENT_ID
ARG NEXT_PUBLIC_IDNOT_BASE_URL
ARG NEXT_PUBLIC_DOCAPOSTE_API_URL
ARG NEXT_PUBLIC_HOTJAR_SITE_ID
ARG NEXT_PUBLIC_HOTJAR_VERSION
ARG NEXT_PUBLIC_4NK_URL
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_DEFAULT_VALIDATOR_ID
ARG NEXT_PUBLIC_DEFAULT_STORAGE_URLS
ENV NEXT_PUBLIC_BACK_API_PROTOCOL=${NEXT_PUBLIC_BACK_API_PROTOCOL} \
NEXT_PUBLIC_BACK_API_HOST=${NEXT_PUBLIC_BACK_API_HOST} \
NEXT_PUBLIC_BACK_API_PORT=${NEXT_PUBLIC_BACK_API_PORT} \
NEXT_PUBLIC_BACK_API_ROOT_URL=${NEXT_PUBLIC_BACK_API_ROOT_URL} \
NEXT_PUBLIC_BACK_API_VERSION=${NEXT_PUBLIC_BACK_API_VERSION} \
NEXT_PUBLIC_FRONT_APP_HOST=${NEXT_PUBLIC_FRONT_APP_HOST} \
NEXT_PUBLIC_FRONT_APP_PORT=${NEXT_PUBLIC_FRONT_APP_PORT} \
NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT=${NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT} \
NEXT_PUBLIC_IDNOT_CLIENT_ID=${NEXT_PUBLIC_IDNOT_CLIENT_ID} \
NEXT_PUBLIC_IDNOT_BASE_URL=${NEXT_PUBLIC_IDNOT_BASE_URL} \
NEXT_PUBLIC_DOCAPOSTE_API_URL=${NEXT_PUBLIC_DOCAPOSTE_API_URL} \
NEXT_PUBLIC_HOTJAR_SITE_ID=${NEXT_PUBLIC_HOTJAR_SITE_ID} \
NEXT_PUBLIC_HOTJAR_VERSION=${NEXT_PUBLIC_HOTJAR_VERSION} \
NEXT_PUBLIC_4NK_URL=${NEXT_PUBLIC_4NK_URL} \
NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} \
NEXT_PUBLIC_DEFAULT_VALIDATOR_ID=${NEXT_PUBLIC_DEFAULT_VALIDATOR_ID} \
NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS}
RUN npm run build
# --- Image d'exécution "ext"
FROM node:19-alpine AS ext
WORKDIR /leCoffre-front
ENV NODE_ENV=production \
PORT=3000
COPY --from=builder /leCoffre-front/.next ./.next
COPY --from=builder /leCoffre-front/public ./public
COPY --from=deps /leCoffre-front/node_modules ./node_modules
COPY --from=builder /leCoffre-front/package.json ./package.json
COPY --from=builder /leCoffre-front/next.config.js ./next.config.js
# Création de l'utilisateur non-root
RUN adduser -D lecoffreuser --uid 10000 && chown -R lecoffreuser .
USER lecoffreuser
EXPOSE 3000
CMD ["npm", "run", "start"]

View File

@ -5,7 +5,7 @@ Cette documentation décrit le pipeline CI/CD tel quil peut être déduit des
### Portée ### Portée
- **Build applicatif**: Next.js (Node 19-alpine) avec dépendance privée `le-coffre-resources` via SSH. - **Build applicatif**: Next.js (Node 19-alpine) avec dépendance privée `le-coffre-resources` via SSH.
- **Image Docker**: construction multi-étapes, publication attendue vers un registre Scaleway Container Registry. - **Image Docker**: construction multi-étapes, publication vers le registre Docker hébergé sur `git.4nkweb.com` (accès via clés SSH).
- **Déploiement Kubernetes**: namespace `lecoffre`, intégration Vault Agent pour linjection dENV, `ExternalSecret` pour le secret de pull Docker, `Ingress` TLS via cert-manager, ressources de `Deployment`/`Service`. - **Déploiement Kubernetes**: namespace `lecoffre`, intégration Vault Agent pour linjection dENV, `ExternalSecret` pour le secret de pull Docker, `Ingress` TLS via cert-manager, ressources de `Deployment`/`Service`.
### Chaîne de build ### Chaîne de build
@ -25,9 +25,8 @@ Cette documentation décrit le pipeline CI/CD tel quil peut être déduit des
### Image, registre et version ### Image, registre et version
- **Image utilisée en cluster**: `rg.fr-par.scw.cloud/lecoffre/front:v0.1.9` (cf. `temp.yaml`). - **Registre**: Docker registry interne sur `git.4nkweb.com`.
- **Registre**: Scaleway Container Registry (région `fr-par`). - **Tagging**: contrôlé par la CI via le message de commit (préfixe `ci: docker_tag=<valeur>`), sinon fallback `dev-test`. La branche peut être utilisée comme tag par défaut selon la CI.
- **Tagging**: la version dexemple observée est `v0.1.9`. Lorigine du tag (automatique via CI, ou manuel) nest pas dans le dépôt.
### Déploiement Kubernetes (extrait de `temp.yaml`) ### Déploiement Kubernetes (extrait de `temp.yaml`)
@ -57,11 +56,11 @@ Cette documentation décrit le pipeline CI/CD tel quil peut être déduit des
- `npm run build` (désactive la télémétrie et le lint bloquant). - `npm run build` (désactive la télémétrie et le lint bloquant).
4. **Construction de limage** 4. **Construction de limage**
- `docker build` avec BuildKit et forward dagent SSH. - Réalisée par la CI (BuildKit + forward dagent SSH) après un `git push` sur `git.4nkweb.com`.
- Taggage semver (ex. `v0.1.9`) et éventuellement `latest`/environnement (non constaté ici). - Taggage déterminé par le message de commit et/ou la branche.
5. **Push au registre** 5. **Push au registre**
- `docker push rg.fr-par.scw.cloud/lecoffre/front:<tag>`. - Réalisé par la CI vers le registre `git.4nkweb.com`.
6. **Déploiement Kubernetes** 6. **Déploiement Kubernetes**
- Application des manifestes (ou rendu Helm) dans le namespace `lecoffre`. - Application des manifestes (ou rendu Helm) dans le namespace `lecoffre`.

58
docs/ext.md Normal file
View File

@ -0,0 +1,58 @@
### Image Docker "ext" (Next.js) variables d'environnement et publication
Cette image exécute l'app Next.js en mode production via `next start` et lit la configuration via les variables d'environnement exposées (préfixe `NEXT_PUBLIC_`). L'objectif est d'éviter toute dépendance à `localhost` dans les appels API : les URLs sont construites dynamiquement côté front à partir de ces variables.
#### Variables d'environnement supportées
- **NEXT_PUBLIC_BACK_API_PROTOCOL**: protocole de l'API (ex: `https://`)
- **NEXT_PUBLIC_BACK_API_HOST**: hôte de l'API (ex: `api.example.com`)
- **NEXT_PUBLIC_BACK_API_PORT**: port de l'API (ex: `443`)
- **NEXT_PUBLIC_BACK_API_ROOT_URL**: racine (ex: `/` ou `/api`)
- **NEXT_PUBLIC_BACK_API_VERSION**: version (ex: `v1`)
- **NEXT_PUBLIC_FRONT_APP_HOST**: base publique du front (ex: `https://app.example.com`)
- **NEXT_PUBLIC_FRONT_APP_PORT**: port front si nécessaire (ex: `443`)
- **NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT**
- **NEXT_PUBLIC_IDNOT_CLIENT_ID**
- **NEXT_PUBLIC_IDNOT_BASE_URL**
- **NEXT_PUBLIC_DOCAPOSTE_API_URL**
- **NEXT_PUBLIC_HOTJAR_SITE_ID**
- **NEXT_PUBLIC_HOTJAR_VERSION**
- **NEXT_PUBLIC_4NK_URL**
- **NEXT_PUBLIC_API_URL**
- **NEXT_PUBLIC_DEFAULT_VALIDATOR_ID**
- **NEXT_PUBLIC_DEFAULT_STORAGE_URLS** (liste séparée par des virgules)
Notes:
- Le front initialise ses variables via `next.config.js` et `_app.tsx`, ce qui alimente `FrontendVariables`. Les appels API utilisent ces valeurs et n'emploient pas `localhost`.
- Les valeurs doivent être passées au conteneur au runtime (`docker run -e ...` ou manifest K8s via `env:`/`secretRef`).
#### Construction de l'image (cible "ext")
Prérequis: Docker BuildKit activé et agent SSH opérationnel pour cloner `le-coffre-resources` depuis `git.4nkweb.com`.
1. `cd /home/debian/lecoffre-front`
2. `export DOCKER_BUILDKIT=1`
3. `docker build --target ext --ssh default -t lecoffre/front:ext-0.1.2 -f /home/debian/lecoffre-front/Dockerfile /home/debian/lecoffre-front`
#### Exécution locale (validation)
Exemple minimal (adapter les valeurs):
```bash
docker run --rm -p 3000:3000 \
-e NEXT_PUBLIC_BACK_API_PROTOCOL=https:// \
-e NEXT_PUBLIC_BACK_API_HOST=api.example.com \
-e NEXT_PUBLIC_BACK_API_PORT=443 \
-e NEXT_PUBLIC_BACK_API_ROOT_URL=/ \
-e NEXT_PUBLIC_BACK_API_VERSION=v1 \
-e NEXT_PUBLIC_FRONT_APP_HOST=https://app.example.com \
-e NEXT_PUBLIC_4NK_URL=https://app.example.com \
lecoffre/front:ext-0.1.2
```
#### Publication via CI (git.4nkweb.com)
- Le push d'image est effectué par la CI de `git.4nkweb.com` suite à un `git push`.
- Définir le tag Docker dans le message de commit: `ci: docker_tag=ext-0.1.2` (fallback CI: `dev-test`).
- La branche peut être utilisée par la CI comme tag en labsence doverride.

View File

@ -1,6 +1,6 @@
{ {
"name": "lecoffre-front", "name": "lecoffre-front",
"version": "0.1.0", "version": "0.1.2",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",

View File

@ -42,17 +42,11 @@ export default function StepEmail(props: IProps) {
const router = useRouter(); const router = useRouter();
const error = router.query["error"]; const error = router.query["error"];
const redirectUserOnConnection = useCallback(() => { const redirectUserOnConnection = useCallback(() => {
/* TODO: review
const variables = FrontendVariables.getInstance(); const variables = FrontendVariables.getInstance();
const redirectUri = `${variables.FRONT_APP_HOST}/authorized-client`;
const authorizeBase = `${variables.IDNOT_BASE_URL}${variables.IDNOT_AUTHORIZE_ENDPOINT}`;
router.push( router.push(
`${variables.IDNOT_BASE_URL + variables.IDNOT_AUTHORIZE_ENDPOINT}?client_id=${variables.IDNOT_CLIENT_ID}&redirect_uri=${ `${authorizeBase}?client_id=${variables.IDNOT_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=openid,profile&response_type=code`,
variables.FRONT_APP_HOST
}/authorized-client&scope=openid,profile&response_type=code`,
);
*/
const redirectUri = 'http://local.4nkweb.com:3000/authorized-client';
router.push(
`https://qual-connexion.idnot.fr/user/IdPOAuth2/authorize/idnot_idp_v1?client_id=B3CE56353EDB15A9&redirect_uri=${redirectUri}&scope=openid,profile&response_type=code`,
); );
}, [router]); }, [router]);

View File

@ -68,10 +68,9 @@ export default function LoginCallBack() {
// TODO: review // TODO: review
// HACK: If start with http://local.lecoffreio.4nkweb:3000/authorized-client // HACK: If start with http://local.lecoffreio.4nkweb:3000/authorized-client
// Replace with http://localhost:3000/authorized-client // Replace with http://localhost:3000/authorized-client
if (window.location.href.startsWith('http://local.4nkweb.com')) { // if (window.location.href.startsWith('http://local.4nkweb.com')) {
window.location.href = window.location.href.replace('http://local.4nkweb.com:3000/authorized-client', 'http://localhost:3000/authorized-client'); // return;
return; // }
}
const code = router.query["code"]; const code = router.query["code"];
if (code) { if (code) {

16
tests/ext.md Normal file
View File

@ -0,0 +1,16 @@
### Tests image "ext"
Objectif: vérifier que l'image démarre et que les URLs d'API proviennent des variables d'environnement.
Plan de test manuel:
1. Construire l'image `--target ext` avec BuildKit et SSH forward.
2. Démarrer un conteneur en exposant le port 3000 et en définissant des `NEXT_PUBLIC_*` non-localhost.
3. Vérifier que le service répond en HTTP 200 sur `/`.
4. Arrêter et supprimer le conteneur.
Critères de réussite:
- Le build aboutit sans erreur et produit une image étiquetée `ext-<version>`.
- Le conteneur écoute sur 3000 et renvoie un code HTTP 200.
- Aucune référence à `localhost` n'est nécessaire pour les appels API (validation via configuration d'ENV uniquement).