fix ci
Some checks failed
Dev CI / Backend — Lint (push) Failing after 1m5s
Dev CI / Backend — Unit Tests (push) Has been skipped
Dev CI / Security gate (push) Failing after 1m20s
Dev CI / Frontend — Lint & Type-check (push) Successful in 1m46s
Dev CI / Frontend — Unit Tests (push) Successful in 1m21s
Dev CI / Notify Failure (push) Has been skipped

This commit is contained in:
David 2026-09-23 22:46:50 +02:00
parent b745f14445
commit e055af9afe
12 changed files with 219 additions and 99 deletions

View File

@ -3,20 +3,13 @@ description: Dependency, secrets, infrastructure and workflow checks for Gitea 1
runs:
using: composite
steps:
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '22'
- uses: ./.gitea/actions/setup-node
- uses: ./.gitea/actions/setup-trivy
- name: Validate workflows and deployment checks
shell: bash
run: |
archive="$RUNNER_TEMP/actionlint.tar.gz"
curl --fail --silent --show-error --location --retry 3 --max-time 120 \
https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz \
--output "$archive"
echo "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 $archive" | sha256sum --check --strict
tar -xzf "$archive" -C "$RUNNER_TEMP" actionlint
ACTIONLINT_BIN="$RUNNER_TEMP/actionlint" bash scripts/ci/validate-workflows.sh
actionlint_bin=$(bash scripts/ci/install-tool.sh actionlint)
ACTIONLINT_BIN="$actionlint_bin" bash scripts/ci/validate-workflows.sh
- name: Audit dependencies, secrets and infrastructure
shell: bash
run: bash scripts/ci/security-audit.sh

View File

@ -0,0 +1,11 @@
name: Install and activate Node 22
description: Set up Node and verify the executable selected by the Gitea runner.
runs:
using: composite
steps:
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '22'
- name: Activate and verify Node 22
shell: bash
run: bash scripts/ci/activate-node.sh

View File

@ -1,16 +1,9 @@
name: Install verified Trivy
description: Install a pinned scanner with a checked SHA256, without elevated privileges.
description: Install a pinned native scanner with a checked SHA256.
runs:
using: composite
steps:
- shell: bash
run: |
set -euo pipefail
install_dir="$RUNNER_TEMP/trivy-bin"
mkdir -p "$install_dir"
curl --fail --silent --show-error --location --retry 3 --max-time 120 \
https://github.com/aquasecurity/trivy/releases/download/v0.74.0/trivy_0.74.0_Linux-64bit.tar.gz \
--output "$install_dir/trivy.tar.gz"
echo "2ae6fe3ee734b7fdf11335663e18c75ea12dccc76062f09f164a3b0f8be4371a $install_dir/trivy.tar.gz" | sha256sum --check --strict
tar -xzf "$install_dir/trivy.tar.gz" -C "$install_dir" trivy
echo "$install_dir" >> "$GITHUB_PATH"
trivy_bin=$(bash scripts/ci/install-tool.sh trivy)
"$trivy_bin" --version

View File

@ -30,7 +30,6 @@ on:
env:
REGISTRY: rg.fr-par.scw.cloud/weworkstudio
NODE_VERSION: '22'
K8S_NAMESPACE: xpeditis-prod
jobs:
@ -54,9 +53,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint -- --no-fix
@ -70,9 +67,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint
- run: npm run type-check
@ -88,9 +83,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -105,9 +98,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -149,6 +140,10 @@ jobs:
persist-credentials: false
# Cet arbre Git est identique à celui de la release preprod vérifiée.
ref: ${{ github.sha }}
- uses: https://github.com/docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
with:
platforms: amd64,arm64
cache-image: false
- uses: https://github.com/docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- uses: https://github.com/docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
@ -173,7 +168,7 @@ jobs:
- name: Contrôle — l'URL de preprod ne doit pas figurer dans le bundle
run: |
IMAGE="${{ env.REGISTRY }}/xpeditis-frontend@${{ steps.build.outputs.digest }}"
CID=$(docker create "$IMAGE")
CID=$(docker create --platform linux/amd64 "$IMAGE")
trap 'docker rm "$CID" >/dev/null' EXIT
docker cp "$CID:/app/.next" /tmp/next-check
test -d /tmp/next-check
@ -260,14 +255,8 @@ jobs:
- name: Installer le client Hetzner
run: |
mkdir -p "$RUNNER_TEMP/hcloud-bin"
curl --fail --silent --show-error --location --retry 3 --max-time 120 \
https://github.com/hetznercloud/cli/releases/download/v1.49.0/hcloud-linux-amd64.tar.gz \
--output "$RUNNER_TEMP/hcloud.tar.gz"
echo "dc6e5b0e6eaf9ef2baa5473a3eb49a11e80e72cdf2a01fdf7b0af975410e79cc $RUNNER_TEMP/hcloud.tar.gz" | sha256sum --check --strict
tar -xzf "$RUNNER_TEMP/hcloud.tar.gz" -C "$RUNNER_TEMP/hcloud-bin" hcloud
echo "$RUNNER_TEMP/hcloud-bin" >> "$GITHUB_PATH"
"$RUNNER_TEMP/hcloud-bin/hcloud" version
hcloud_bin=$(bash scripts/ci/install-tool.sh hcloud)
"$hcloud_bin" version
- name: Ouvrir le port 22 pour l'IP de ce runner
env:

View File

@ -19,7 +19,6 @@ on:
env:
REGISTRY: rg.fr-par.scw.cloud/weworkstudio
NODE_VERSION: '22'
jobs:
security:
@ -42,9 +41,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint -- --no-fix
@ -58,9 +55,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint
- run: npm run type-check
@ -77,9 +72,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -94,9 +87,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -133,9 +124,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- name: Run integration tests
env:
@ -178,7 +167,8 @@ jobs:
run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- uses: https://github.com/docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
with:
platforms: arm64
platforms: amd64,arm64
cache-image: false
- uses: https://github.com/docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- uses: https://github.com/docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
@ -213,7 +203,8 @@ jobs:
run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- uses: https://github.com/docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
with:
platforms: arm64
platforms: amd64,arm64
cache-image: false
- uses: https://github.com/docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- uses: https://github.com/docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
@ -251,7 +242,8 @@ jobs:
run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
- uses: https://github.com/docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
with:
platforms: arm64
platforms: amd64,arm64
cache-image: false
- uses: https://github.com/docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- uses: https://github.com/docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:

View File

@ -6,9 +6,6 @@ on:
pull_request:
branches: [dev]
env:
NODE_VERSION: '22'
jobs:
security:
name: Security gate
@ -29,9 +26,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint -- --no-fix
@ -45,9 +40,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint
- run: npm run type-check
@ -63,9 +56,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -80,9 +71,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand

View File

@ -8,9 +8,6 @@ on:
pull_request:
branches: [preprod, main]
env:
NODE_VERSION: '22'
jobs:
security:
name: Security gate
@ -31,9 +28,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint -- --no-fix
@ -47,9 +42,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm run lint
- run: npm run type-check
@ -65,9 +58,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -82,9 +73,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- run: npm test -- --ci --runInBand
@ -121,9 +110,7 @@ jobs:
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: https://github.com/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: ./.gitea/actions/setup-node
- run: npm ci --legacy-peer-deps
- name: Run integration tests
env:

View File

@ -2,7 +2,7 @@
La version du serveur `https://gitea.ops.xpeditis.com` a été vérifiée via
`/api/v1/version` : **1.22.6**. Les pipelines ciblent Gitea Actions / act_runner,
avec des jobs exécutés dans des conteneurs Linux AMD64.
avec des jobs exécutés dans des conteneurs Linux AMD64 ou ARM64.
## Workflows et contrôles
@ -32,7 +32,7 @@ lorsqu'aucun correctif n'est disponible. Les erreurs de scanner ou de registre
échouent aussi : aucune exclusion générale ni échec masqué n'est ajouté.
Les installations applicatives utilisent `npm ci`, le runtime est Node 22 et les
actions sont épinglées par SHA. Trivy, Actionlint et Hetzner CLI sont téléchargés
avec vérification SHA256. Le lint backend ne réécrit plus les fichiers.
avec détection native AMD64/ARM64 et vérification SHA256. Le lint backend ne réécrit plus les fichiers.
Les rapports sont joints aux exécutions **Gitea Actions** avec
`actions/upload-artifact` **v3**, compatible avec le protocole de cette version
@ -74,7 +74,7 @@ Gitea 1.22 ignore notamment `concurrency`, `permissions`, `environment`, les dé
YAML de jobs et `workflow_dispatch`. Ces paramètres ne sont donc pas présentés
comme des protections effectives dans les workflows adaptés.
1. Activer Actions dans le dépôt et disposer d'un runner Docker Linux AMD64 avec
1. Activer Actions dans le dépôt et disposer d'un runner Docker Linux AMD64 ou ARM64 avec
le label `ubuntu-latest`, Git, Bash, Python 3, curl, tar, timeout et les outils
Docker. Les builds multiarchitecture ont besoin du support QEMU/binfmt.
Les services d'intégration sont joints via `postgres` et `redis`, sans ports
@ -142,7 +142,7 @@ ces configurations ne signale plus ce secret après modification.
## Validation
Les 19 tests offline de promotion et santé passent : arbre différent, marqueurs
Les 25 tests offline de promotion et santé passent : arbre différent, marqueurs
manquants, panne du registre, digest invalide, mauvaise branche, saisie hostile et
échec HTTP sont refusés. Les tests vérifient aussi que les échecs et délais des
audits restent bloquants et que le rapport masque les valeurs de secrets. Actionlint valide la syntaxe après normalisation des URLs
@ -152,6 +152,19 @@ d'actions Gitea ; ce contrôle ne remplace pas une exécution avec act_runner.
ACTIONLINT_BIN=/chemin/vers/actionlint bash scripts/ci/validate-workflows.sh
```
La correction du 23 septembre 2026 a aussi été exécutée dans un conteneur Linux
ARM64 : Trivy 0.74.0, Actionlint 1.7.12 et Hetzner CLI 1.49.0 démarrent avec leurs
archives officielles vérifiées. `activate-node.sh` place le Node 22 natif du cache
en tête du PATH et vérifie son exécution ; un Node 18 préinstallé ne peut plus
être sélectionné silencieusement. Node 22.23.2 a été vérifié dans l'étape suivante.
Le téléchargement/affichage de version dans `setup-node` ne suffit pas à confirmer
le runtime utilisé par les étapes shell ; la nouvelle étape affiche le chemin
absolu et la version réellement activés.
L'installateur commun est `scripts/ci/install-tool.sh`. Chaque architecture a sa
propre archive et son empreinte. QEMU couvre AMD64 et ARM64 dans les builds préprod
et frontend prod, dont la cible reste AMD64 même si le runner est ARM64.
Les installations ont été vérifiées avec `npm ci --dry-run --offline
--ignore-scripts --legacy-peer-deps`. Les builds Docker, les tests applicatifs sous
Node 22, le transport réel des artefacts et les déploiements sont encore à valider

View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
case "$(uname -m)" in
aarch64|arm64) arch=arm64 ;;
x86_64|amd64) arch=x64 ;;
*) echo 'Unsupported Node architecture' >&2; exit 1 ;;
esac
cache="${RUNNER_TOOL_CACHE:-${AGENT_TOOLSDIRECTORY:-/opt/hostedtoolcache}}"
# Select the newest installed Node 22 for this architecture, independent of the
# container's preinstalled Node 18 and setup-node's misleading version output.
node_bin=$(printf '%s\n' "$cache"/node/22.*/"$arch"/bin | sort -Vr | head -n 1)
if [[ ! -x "$node_bin/node" ]]; then
echo "Node 22 is missing from the tool cache: $cache/node (architecture $arch)" >&2
exit 1
fi
export PATH="$node_bin:$PATH"
hash -r
node -e 'if (process.versions.node.split(".")[0] !== "22") process.exit(1)'
printf '%s\n' "$node_bin" >> "${GITHUB_PATH:?}"
printf 'PATH=%s\n' "$PATH" >> "${GITHUB_ENV:?}"
printf 'Active Node executable: %s\n' "$(command -v node)"
node --version
npm --version

View File

@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Pinned Linux tools for either native architecture; never execute a foreign binary.
set -euo pipefail
tool="${1:?Usage: install-tool.sh trivy|actionlint|hcloud [--print-source]}"
[[ "$(uname -s)" == Linux ]] || { echo 'CI tools require Linux' >&2; exit 1; }
case "$(uname -m)" in
x86_64|amd64) arch=amd64 ;;
aarch64|arm64) arch=arm64 ;;
*) echo 'Unsupported runner architecture' >&2; exit 1 ;;
esac
case "$tool:$arch" in
trivy:amd64)
url=https://github.com/aquasecurity/trivy/releases/download/v0.74.0/trivy_0.74.0_Linux-64bit.tar.gz
sha=2ae6fe3ee734b7fdf11335663e18c75ea12dccc76062f09f164a3b0f8be4371a ;;
trivy:arm64)
url=https://github.com/aquasecurity/trivy/releases/download/v0.74.0/trivy_0.74.0_Linux-ARM64.tar.gz
sha=b94ce1976bbf3c15b514b605ee88be7c6d94a29be2302847ff01cb794d47aad5 ;;
actionlint:amd64)
url=https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz
sha=8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 ;;
actionlint:arm64)
url=https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_arm64.tar.gz
sha=325e971b6ba9bfa504672e29be93c24981eeb1c07576d730e9f7c8805afff0c6 ;;
hcloud:amd64)
url=https://github.com/hetznercloud/cli/releases/download/v1.49.0/hcloud-linux-amd64.tar.gz
sha=dc6e5b0e6eaf9ef2baa5473a3eb49a11e80e72cdf2a01fdf7b0af975410e79cc ;;
hcloud:arm64)
url=https://github.com/hetznercloud/cli/releases/download/v1.49.0/hcloud-linux-arm64.tar.gz
sha=183dabe0a03b3eb7b93f8d2f2cf91c478de57f9412f189866eda0fdde7baf88c ;;
*) echo "Unsupported tool: $tool" >&2; exit 1 ;;
esac
if [[ "${2:-}" == --print-source ]]; then
printf '%s\n%s\n' "$url" "$sha"
exit 0
fi
install_dir="${RUNNER_TEMP:?}/ci-tools/$tool"
mkdir -p "$install_dir"
echo "Installing $tool for Linux/$arch" >&2
curl --fail --silent --show-error --location --retry 3 --max-time 120 \
"$url" --output "$install_dir/archive.tar.gz"
echo "$sha $install_dir/archive.tar.gz" | sha256sum --check --strict >&2
tar -xzf "$install_dir/archive.tar.gz" -C "$install_dir" "$tool"
chmod +x "$install_dir/$tool"
printf '%s\n' "$install_dir" >> "${GITHUB_PATH:?}"
# Older act_runner releases can keep the container PATH ahead of add-path entries.
printf 'PATH=%s:%s\n' "$install_dir" "$PATH" >> "${GITHUB_ENV:?}"
printf '%s\n' "$install_dir/$tool"

View File

@ -0,0 +1,83 @@
"""Offline architecture/PATH regressions for Gitea Linux runners."""
import os
from pathlib import Path
import subprocess
import tempfile
import unittest
SCRIPTS = Path(__file__).resolve().parent
class ToolSetup(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.bin = self.root / 'bin'
self.bin.mkdir()
self.env = dict(os.environ, PATH=f'{self.bin}:{os.environ["PATH"]}',
FAKE_ARCH='aarch64', FAKE_OS='Linux',
RUNNER_TEMP=str(self.root), RUNNER_TOOL_CACHE=str(self.root / 'cache'),
GITHUB_PATH=str(self.root / 'path'), GITHUB_ENV=str(self.root / 'env'))
self.mock(self.bin / 'uname', 'if [ "$1" = -s ]; then echo "$FAKE_OS"; else echo "$FAKE_ARCH"; fi\n')
def mock(self, path, body):
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('#!/bin/sh\n' + body)
path.chmod(0o755)
def run_script(self, script, *args):
return subprocess.run(['bash', str(SCRIPTS / script), *args], env=self.env,
capture_output=True, text=True)
def test_all_native_tool_urls_and_checksums(self):
for arch, suffix in [('aarch64', 'arm64'), ('x86_64', 'amd64')]:
self.env['FAKE_ARCH'] = arch
for tool in ['trivy', 'actionlint', 'hcloud']:
with self.subTest(arch=arch, tool=tool):
result = self.run_script('install-tool.sh', tool, '--print-source')
self.assertEqual(result.returncode, 0, result.stderr)
url, checksum = result.stdout.splitlines()
expected = 'Linux-ARM64' if tool == 'trivy' and suffix == 'arm64' else (
'Linux-64bit' if tool == 'trivy' else suffix)
self.assertIn(expected, url)
self.assertRegex(checksum, r'^[0-9a-f]{64}$')
def test_unsupported_architecture_rejected_before_download(self):
self.env['FAKE_ARCH'] = 'armv7l'
self.assertNotEqual(self.run_script('install-tool.sh', 'trivy', '--print-source').returncode, 0)
def test_non_linux_rejected(self):
self.env['FAKE_OS'] = 'Darwin'
self.assertNotEqual(self.run_script('install-tool.sh', 'trivy', '--print-source').returncode, 0)
def test_wrong_checksum_cannot_install_or_activate_binary(self):
self.mock(self.bin / 'curl', 'exit 0\n')
self.mock(self.bin / 'sha256sum', 'exit 1\n')
self.mock(self.bin / 'tar', f'touch "{self.root}/extracted"\n')
self.assertNotEqual(self.run_script('install-tool.sh', 'trivy').returncode, 0)
self.assertFalse((self.root / 'extracted').exists())
self.assertFalse((self.root / 'path').exists())
def test_node22_takes_precedence_over_preinstalled_node18(self):
self.mock(self.bin / 'node', 'echo v18.20.8\nexit 1\n')
self.mock(self.bin / 'npm', 'echo old-npm\nexit 1\n')
for version in ['22.9.0', '22.23.2']:
node_bin = self.root / 'cache' / 'node' / version / 'arm64' / 'bin'
self.mock(node_bin / 'node', f'if [ "$1" = -e ]; then exit 0; fi\necho v{version}\n')
self.mock(node_bin / 'npm', 'echo 10.9.0\n')
result = self.run_script('activate-node.sh')
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn('v22.23.2', result.stdout)
self.assertNotIn('v18.', result.stdout)
self.assertIn('/22.23.2/arm64/bin', (self.root / 'path').read_text())
self.assertTrue((self.root / 'env').read_text().startswith('PATH='))
def test_missing_native_node22_fails(self):
wrong_arch = self.root / 'cache' / 'node' / '22.23.2' / 'x64' / 'bin'
self.mock(wrong_arch / 'node', 'exit 0\n')
self.assertNotEqual(self.run_script('activate-node.sh').returncode, 0)
if __name__ == '__main__':
unittest.main()

View File

@ -8,4 +8,4 @@ for workflow in .gitea/workflows/*.yml; do
"$validator" -config-file .gitea/actionlint.yaml -shellcheck='' -stdin-filename "$workflow" -
done
bash -n scripts/ci/*.sh
python3 scripts/ci/test_release_checks.py
python3 -B -m unittest discover -s scripts/ci -p 'test_*.py'