front: add etcs reticle info #38015
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| pull_request: | |
| workflow_dispatch: | |
| merge_group: | |
| types: [checks_requested] | |
| push: | |
| branches: | |
| - dev | |
| - staging | |
| - prod | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| name: Build | |
| permissions: | |
| packages: write | |
| outputs: | |
| stable_tags: ${{ steps.bake-metadata.outputs.stable_tags }} | |
| stable_version: ${{ steps.bake-metadata.outputs.stable_version }} | |
| output_method: ${{ steps.bake-metadata.outputs.output_method }} | |
| strategy: | |
| matrix: | |
| targets: | |
| - [core-build, core] | |
| - [editoast, editoast-test] | |
| - [gateway-test, gateway-standalone, gateway-front] | |
| - [front-tests] | |
| - [osrdyne, osrdyne-test] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Make bake metadata | |
| id: bake-metadata | |
| env: | |
| GITHUB_CONTEXT: ${{ toJson(github) }} | |
| run: | | |
| set -euo pipefail | |
| echo ::group::Github context | |
| python3 -m json.tool <<< "${GITHUB_CONTEXT}" | |
| echo ::endgroup:: | |
| echo ::group::Bake metadata | |
| .github/scripts/bake-metadata.py | tee bake-metadata.json | |
| echo ::endgroup:: | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| version: v0.12.0 | |
| driver-opts: image=moby/buildkit:v0.12.3 | |
| buildkitd-flags: --debug | |
| - name: Login to ghcr.io | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: "$" # special user for authenticating as a gh actions worker | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # This action happens to randomly fail, so we retry it 3 times. | |
| # Whitelisted messages are: | |
| # | |
| # - `failed to solve: failed to compute cache key` | |
| # full message: `failed to solve: failed to compute cache key: failed to get state for index 0 on XXXXXX` | |
| # | |
| # - `httpReadSeeker: failed open:` | |
| # full message: `ERROR: failed to solve: DeadlineExceeded: failed to compute cache key: failed to copy: httpReadSeeker: failed open: no active session for XXXXX: context deadline exceeded` | |
| - name: Build and push | |
| run: | | |
| set -euo pipefail | |
| # disable cache mounts as github cache is slow | |
| find \( -name Dockerfile -o -name "Dockerfile.*" \) -print0 | xargs -0 sed -Ei 's/--mount=type=cache,target=[^[:blank:]]+//g' | |
| TRANSIENT_FAILURES=( | |
| "failed to solve: failed to compute cache key" | |
| "httpReadSeeker: failed open:" | |
| ) | |
| BAKEFILE="--file=docker/docker-bake.hcl" | |
| METADATA="--file=bake-metadata.json" | |
| TARGETS="${{ join(matrix.targets, ' ') }}" | |
| for i in $(seq 1 3); do | |
| echo "::group::Try $i" | |
| if docker buildx bake $BAKEFILE $METADATA $TARGETS 2>&1 | tee docker-build.log; then | |
| echo "::endgroup::" | |
| exit 0 | |
| fi | |
| echo "::endgroup::" | |
| for failure_msg in "${TRANSIENT_FAILURES[@]}"; do | |
| if grep -q "$failure_msg" docker-build.log; then | |
| echo "Transient failure detected, retrying..." | |
| continue 2 | |
| fi | |
| done | |
| echo "Build failed for non-transient cause, exiting." | |
| exit 1 | |
| done | |
| echo "All retries failed, exiting." | |
| exit 1 | |
| - name: Upload core artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'core') | |
| with: | |
| name: core | |
| path: osrd-core.tar | |
| - name: Upload core-build artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'core-build') | |
| with: | |
| name: core-build | |
| path: osrd-core-build.tar | |
| - name: Upload editoast artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'editoast') | |
| with: | |
| name: editoast | |
| path: osrd-editoast.tar | |
| - name: Upload editoast-test artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'editoast-test') | |
| with: | |
| name: editoast-test | |
| path: osrd-editoast-test.tar | |
| - name: Upload front artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'front-devel') | |
| with: | |
| name: front | |
| path: osrd-front.tar | |
| - name: Upload front-tests artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'front-tests') | |
| with: | |
| name: front-tests | |
| path: osrd-front-tests.tar | |
| - name: Upload gateway-front artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'gateway-front') | |
| with: | |
| name: gateway-front | |
| path: osrd-gateway-front.tar | |
| - name: Upload gateway-standalone artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'gateway-standalone') | |
| with: | |
| name: gateway-standalone | |
| path: osrd-gateway-standalone.tar | |
| - name: Upload gateway-test artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'gateway-test') | |
| with: | |
| name: gateway-test | |
| path: osrd-gateway-test.tar | |
| - name: Upload osrdyne artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'osrdyne') | |
| with: | |
| name: osrdyne | |
| path: osrd-osrdyne.tar | |
| - name: Upload osrdyne-test artifact | |
| uses: actions/upload-artifact@v5 | |
| if: steps.bake-metadata.outputs.output_method == 'artifact' && contains(matrix.targets, 'osrdyne-test') | |
| with: | |
| name: osrdyne-test | |
| path: osrd-osrdyne-test.tar | |
| check_dockerfiles: | |
| runs-on: ubuntu-latest | |
| name: Check dockerfiles | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Build dummy test_data and static_assets images | |
| run: | | |
| echo -e "FROM scratch" > Dockerfile.empty | |
| docker build -t test_data - <Dockerfile.empty | |
| docker build -t static_assets - <Dockerfile.empty | |
| docker build -t front_tests:latest - <Dockerfile.empty | |
| docker build -t front_build:latest - <Dockerfile.empty | |
| docker build -t front_src:latest - <Dockerfile.empty | |
| - name: Find and check all Dockerfiles using docker build --check | |
| run: | | |
| set -euo pipefail | |
| find . -name 'Dockerfile*' -print0 | xargs -0 -I {} docker build --file {} --check . | |
| check_models_sync: | |
| runs-on: ubuntu-latest | |
| name: Check models.py sync | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.12" | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: | | |
| uv --directory railway_manager_interface/ sync | |
| - name: Generate models.py | |
| run: | | |
| cd railway_manager_interface | |
| ./generate-types.sh > /tmp/generated_models.py | |
| - name: Ensure models.py is up to date | |
| run: diff -u railway_manager_interface/osrd_railway_manager_interface/models.py /tmp/generated_models.py | |
| check_scripts: | |
| runs-on: ubuntu-latest | |
| name: Check scripts | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Find and check all scripts using ShellCheck | |
| uses: ludeeus/action-shellcheck@master | |
| with: | |
| ignore_names: gradlew | |
| check_generated_railjson_sync: | |
| runs-on: ubuntu-latest | |
| name: Check generated railjson sync | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.11" | |
| enable-cache: true | |
| - name: Install railjson_generator dependencies | |
| run: | | |
| uv --directory python/railjson_generator/ sync | |
| - name: Generate railjson | |
| run: | | |
| mkdir /tmp/generated_infras | |
| uv --directory python/railjson_generator/ run -m railjson_generator /tmp/generated_infras $(pwd)/tests/infra-scripts/*.py | |
| - name: Ensure generated infrastructures are up to date | |
| run: diff -r -u tests/data/infras /tmp/generated_infras | |
| check_railjson_generator: | |
| runs-on: ubuntu-latest | |
| name: Check railjson generator | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.11" | |
| enable-cache: true | |
| - name: Install railjson_generator dependencies | |
| run: | | |
| uv --directory python/railjson_generator/ sync --extra check | |
| - name: Ruff | |
| run: | | |
| uv --directory python/railjson_generator/ run ruff check --output-format github | |
| uv --directory python/railjson_generator/ run ruff format --check | |
| - name: Pyright | |
| run: | | |
| uv --directory python/railjson_generator/ run pyright | |
| - name: Pytest | |
| run: | | |
| uv --directory python/railjson_generator/ run pytest | |
| check_commits: | |
| runs-on: ubuntu-latest | |
| name: Check commits | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 # Fetch all history for all branches and tags | |
| - name: Check commit names | |
| run: | | |
| # We don't have a base ref to check against if we aren't in a | |
| # pull_request workflow. | |
| BASE=${{ github.base_ref }} | |
| if [[ -z "$BASE" ]]; then | |
| exit 0 | |
| fi | |
| commit_titles() { | |
| git log --format=%s origin/"$BASE"..HEAD --skip=1 | |
| } | |
| commit_titles | TERM=xterm-color .github/scripts/check-commit-titles.sh | |
| - name: Check DCO | |
| uses: christophebedard/[email protected] | |
| with: | |
| args: --exclude-emails '49699333+dependabot[bot]@users.noreply.github.com,github-actions[bot]@users.noreply.github.com' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| check_final_newline: | |
| runs-on: ubuntu-latest | |
| name: Check final newline | |
| steps: | |
| - name: Install ripgrep | |
| run: sudo apt-get install -y ripgrep | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Check final newline is present | |
| run: | | |
| # search missing final newline | |
| if rg -Ul '[^\n]\z' -g '!*.svg' .; then | |
| echo "Found missing final newline on listed file(s)" | |
| exit 1 | |
| fi | |
| # search multiple final newlines | |
| if rg -Ul '\n\n\z' .; then | |
| echo "Found multiple final newlines on listed file(s)" | |
| exit 1 | |
| fi | |
| check_integration_tests: | |
| runs-on: ubuntu-latest | |
| name: Check integration tests | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.11" | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: | | |
| uv --directory tests/ sync --extra check | |
| - name: Ruff | |
| run: | | |
| uv --directory tests/ run ruff check | |
| uv --directory tests/ run ruff format --check | |
| - name: Pyright | |
| run: | | |
| uv --directory tests/ run pyright | |
| check_osrd_schema: | |
| runs-on: ubuntu-latest | |
| name: Check osrd schema | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.11" | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: | | |
| uv --directory python/osrd_schemas/ sync --extra check | |
| - name: Ruff | |
| run: | | |
| uv --directory python/osrd_schemas/ run ruff check --output-format github | |
| uv --directory python/osrd_schemas/ run ruff format --check | |
| - name: Pyright | |
| run: | | |
| uv --directory python/osrd_schemas/ run pyright | |
| check_toml: | |
| runs-on: ubuntu-latest | |
| name: Check toml | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Install taplo | |
| uses: baptiste0928/cargo-install@v3 | |
| with: | |
| crate: taplo-cli | |
| locked: true | |
| - name: Check TOML format | |
| run: taplo fmt --check --diff | |
| check_infra_schema_sync: | |
| runs-on: ubuntu-latest | |
| name: Check infra schema sync | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.11" | |
| enable-cache: true | |
| - name: Check infra_schema.json sync | |
| run: | | |
| cp front/src/reducers/osrdconf/infra_schema.json current_infra_schema.json | |
| cp front/public/locales/en/infraEditor.json current_infra_en_translations.json | |
| ./scripts/sync-infra-schema.sh | |
| diff current_infra_schema.json front/src/reducers/osrdconf/infra_schema.json | |
| - name: Check locales/en/infraEditor.json sync | |
| run: diff current_infra_en_translations.json front/public/locales/en/infraEditor.json | |
| check_front_rtk_sync: | |
| runs-on: ubuntu-latest | |
| name: Check front rtk sync | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: front-tests | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-front-tests.tar | |
| docker image ls -a | |
| - name: Generate rtk bindings | |
| run: > | |
| docker run --rm --net=host -v $PWD/output:/app/tests/unit | |
| -v $PWD/editoast:/editoast | |
| -v $PWD/gateway:/gateway | |
| -v $PWD/railway_manager_interface:/railway_manager_interface | |
| -v $PWD/front/src/common/api:/app/src/common/api | |
| ${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} | |
| npm run generate-types | |
| - name: Check for unexpected changes | |
| run: | | |
| git diff --exit-code front | |
| check_core: | |
| runs-on: ubuntu-latest | |
| name: Check core | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: core-build | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-core-build.tar | |
| - name: Execute tests within container | |
| run: | | |
| docker run --name core-test \ | |
| -v $PWD/core/build:/output ${{ fromJSON(needs.build.outputs.stable_tags).core-build }} \ | |
| /bin/bash -c 'gradle -Pspotbugs_report_xml --continue check; status=$?; cp -r build/* /output/; exit $status' | |
| exit $(docker wait core-test) | |
| - name: Report JUnit failures | |
| uses: mikepenz/action-junit-report@v6 | |
| if: failure() | |
| with: | |
| report_paths: "./core/build/test-results/test/TEST-*.xml" | |
| require_tests: true | |
| - name: Report spotbugs lints | |
| if: failure() | |
| uses: jwgmeligmeyling/[email protected] | |
| with: | |
| path: "./output/reports/spotbugs/*.xml" | |
| check_editoast_tests: | |
| runs-on: ubuntu-latest | |
| name: Check editoast tests | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built editoast-test image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: editoast-test | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-editoast-test.tar | |
| - name: Startup the test infrastructure | |
| id: start_editoast_tests_infra | |
| run: | | |
| set -euo pipefail | |
| services='openfga' | |
| composes='-f docker-compose.yml' | |
| docker compose $composes pull --policy missing $services | |
| docker compose $composes up --no-build -d $services | |
| env: | |
| DOCKER_BUILDKIT: 1 | |
| COMPOSE_DOCKER_CLI_BUILD: 1 | |
| - name: Execute tests within container | |
| run: | | |
| # snapshot testing library `insta` requires CI=true | |
| docker run --name=editoast-test --net=host -v $PWD/output:/output \ | |
| -e DATABASE_URL="postgres://osrd:password@localhost:5432/osrd" \ | |
| -e CI="true" \ | |
| -e FGA_API_URL="http://localhost:8091" \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).editoast-test }} \ | |
| /bin/sh -c "diesel migration run --locked-schema && RUST_LOG=error RUST_BACKTRACE=1 cargo test --workspace -- --test-threads=4" | |
| exit $(docker wait editoast-test) | |
| check_editoast_lints: | |
| # lints runs in a separate job, as it takes about 1m30 for the documentation | |
| # check to complete. As editoast tests take while to run, we don't want this to | |
| # be on the hot path | |
| runs-on: ubuntu-latest | |
| name: Check editoast lints | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: editoast-test | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-editoast-test.tar | |
| - name: Documentation check | |
| run: | | |
| docker run --name=editoast-doc --net=host -v $PWD/output:/output \ | |
| -e RUSTDOCFLAGS="-D warnings" \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).editoast-test }} \ | |
| cargo doc --manifest-path ./Cargo.toml --no-deps | |
| exit $(docker wait editoast-doc) | |
| - name: Format check | |
| run: | | |
| docker run --name=editoast-format --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).editoast-test }} \ | |
| cargo fmt --check | |
| exit $(docker wait editoast-format) | |
| - name: Clippy check | |
| run: | | |
| docker run --name=editoast-clippy --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).editoast-test }} \ | |
| cargo clippy --workspace --all-features --all-targets -- -D warnings | |
| exit $(docker wait editoast-clippy) | |
| check_editoast_openapi: | |
| # for the same reason as check_editoast_lints, we run this in a separate job | |
| runs-on: ubuntu-latest | |
| name: Check editoast openapi | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built editoast image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: editoast | |
| path: . | |
| - name: Download built front-tests image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: front-tests | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-editoast.tar | |
| docker load --input ./osrd-front-tests.tar | |
| - name: Generate OpenAPI | |
| run: | | |
| docker run --name=editoast-test --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).editoast }} \ | |
| /bin/sh -c 'editoast openapi > /output/openapi.yaml' | |
| - name: Check for unexpected changes | |
| run: | | |
| diff $PWD/editoast/openapi.yaml $PWD/output/openapi.yaml | |
| - name: Check for i18n API errors | |
| run: | | |
| docker run --name=front-i18n-api-error --net=host -v $PWD/output/openapi.yaml:/editoast/openapi.yaml \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} \ | |
| npm run i18n-api-errors | |
| exit $(docker wait front-i18n-api-error) | |
| check_gateway: | |
| runs-on: ubuntu-latest | |
| name: Check gateway | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: gateway-test | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-gateway-test.tar | |
| - name: Execute tests within container | |
| run: | | |
| docker run --name=gateway-test --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).gateway-test }} \ | |
| /bin/sh -c "cargo test --verbose" | |
| exit $(docker wait gateway-test) | |
| - name: Documentation check | |
| run: | | |
| docker run --name=gateway-doc --net=host -v $PWD/output:/output \ | |
| -e RUSTDOCFLAGS="-D warnings" \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).gateway-test }} \ | |
| cargo doc --manifest-path ./Cargo.toml --no-deps | |
| exit $(docker wait gateway-doc) | |
| - name: Format check | |
| run: | | |
| docker run --name=gateway-format --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).gateway-test }} \ | |
| cargo fmt --check | |
| exit $(docker wait gateway-format) | |
| - name: Clippy check | |
| run: | | |
| docker run --name=gateway-clippy --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).gateway-test }} \ | |
| cargo clippy --workspace --all-features --all-targets -- -D warnings | |
| exit $(docker wait gateway-clippy) | |
| check_osrdyne: | |
| runs-on: ubuntu-latest | |
| name: Check osrdyne | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: osrdyne-test | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-osrdyne-test.tar | |
| - name: Execute tests within container | |
| run: | | |
| docker run --name=osrdyne-test --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).osrdyne-test }} \ | |
| /bin/sh -c "cargo test --verbose" | |
| exit $(docker wait osrdyne-test) | |
| - name: Documentation check | |
| run: | | |
| docker run --name=osrdyne-doc --net=host -v $PWD/output:/output \ | |
| -e RUSTDOCFLAGS="-D warnings" \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).osrdyne-test }} \ | |
| cargo doc --manifest-path ./Cargo.toml --no-deps | |
| exit $(docker wait osrdyne-doc) | |
| - name: Format check | |
| run: | | |
| docker run --name=osrdyne-format --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).osrdyne-test }} \ | |
| cargo fmt --check | |
| exit $(docker wait osrdyne-format) | |
| - name: Clippy check | |
| run: | | |
| docker run --name=osrdyne-clippy --net=host -v $PWD/output:/output \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).osrdyne-test }} \ | |
| cargo clippy --all-features --all-targets -- -D warnings | |
| exit $(docker wait osrdyne-clippy) | |
| check_front: | |
| runs-on: ubuntu-latest | |
| name: Check front | |
| needs: | |
| - build | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: front-tests | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-front-tests.tar | |
| - name: Check code formatting | |
| # TODO: Once we migrate to eslint v9 and add support for json and css this can be dropped | |
| run: | | |
| docker run --name=front-format --net=host \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} \ | |
| sh -c "npx prettier . --check && cd ui && npx prettier . --check" | |
| exit $(docker wait front-format) | |
| - name: Check lints | |
| run: | | |
| docker run --name=front-lint --net=host \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} \ | |
| sh -c "npm run lint" | |
| exit $(docker wait front-lint) | |
| - name: Check for i18n missing keys | |
| run: | | |
| docker run --name=front-i18n-checker --net=host \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} \ | |
| npm run i18n-checker | |
| exit $(docker wait front-i18n-checker) | |
| - name: Check for i18n keys order | |
| run: ./front/scripts/i18n-order-checker.sh | |
| - name: Execute tests within container | |
| run: | | |
| docker run --name=front-test --net=host \ | |
| ${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} \ | |
| sh -c "npm run test" | |
| exit $(docker wait front-test) | |
| integration_tests: | |
| runs-on: ubuntu-latest | |
| name: Integration tests | |
| needs: | |
| - build | |
| steps: | |
| # TODO: check if we can deduplicate the base steps from integration_tests_quality | |
| # https://www.jameskerr.blog/posts/sharing-steps-in-github-action-workflows/ | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built editoast image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: editoast | |
| path: . | |
| - name: Download built core image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: core | |
| path: . | |
| - name: Download built osrdyne image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: osrdyne | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-editoast.tar | |
| docker load --input ./osrd-core.tar | |
| docker load --input ./osrd-osrdyne.tar | |
| - name: Set up 'uv' | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.11" | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: | | |
| uv --directory tests/ sync | |
| - name: Startup the test infrastructure | |
| id: start_integration_worker | |
| run: | | |
| set -euo pipefail | |
| export TAG='${{ needs.build.outputs.stable_version }}' | |
| # Inside /docker/osrdyne.yml, replace core_image "osrd-core:dev" with "osrd-core:$TAG" | |
| # to match the version of the core image we just built inside osrdyne | |
| sed -i "s/osrd-core:dev/osrd-core:$TAG/" docker/osrdyne.yml | |
| services='editoast osrdyne core' | |
| composes='-f docker-compose.yml' | |
| docker compose $composes pull --policy missing $services | |
| docker compose $composes up --no-build -d $services jaeger openfga wait-healthy | |
| env: | |
| DOCKER_BUILDKIT: 1 | |
| COMPOSE_DOCKER_CLI_BUILD: 1 | |
| - name: Run pytest | |
| run: | | |
| uv --directory tests/ run pytest | |
| - name: Save container logs | |
| run: docker compose logs > container-logs | |
| if: always() | |
| - uses: actions/upload-artifact@v5 | |
| if: always() | |
| with: | |
| name: integration-container-logs | |
| path: container-logs | |
| retention-days: 30 | |
| end_to_end_tests: | |
| runs-on: ubuntu-latest | |
| name: End to end tests | |
| needs: | |
| - build | |
| steps: | |
| # TODO: check if we can deduplicate the base steps from integration_tests_quality | |
| # https://www.jameskerr.blog/posts/sharing-steps-in-github-action-workflows/ | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download built front-tests image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: front-tests | |
| path: . | |
| - name: Download built editoast image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: editoast | |
| path: . | |
| - name: Download built core image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: core | |
| path: . | |
| - name: Download built gateway-front image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: gateway-front | |
| path: . | |
| - name: Download built osrdyne image | |
| if: needs.build.outputs.output_method == 'artifact' | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: osrdyne | |
| path: . | |
| - name: Load built images | |
| if: needs.build.outputs.output_method == 'artifact' | |
| run: | | |
| docker load --input ./osrd-front-tests.tar | |
| docker load --input ./osrd-editoast.tar | |
| docker load --input ./osrd-core.tar | |
| docker load --input ./osrd-gateway-front.tar | |
| docker load --input ./osrd-osrdyne.tar | |
| - name: Detect Playwright version | |
| id: detect_playwright_version | |
| run: | | |
| PLAYWRIGHT_VERSION=$(cd front && npm list --package-lock-only --pattern playwright --json | jq -r '.dependencies["@playwright/test"].version' | sort -u) | |
| if [ "$(echo "$PLAYWRIGHT_VERSION" | wc -l)" -ne 1 ]; then | |
| echo "Error: Zero or multiple playwright versions found: $PLAYWRIGHT_VERSION" >&2 | |
| exit 1 | |
| fi | |
| echo "Detected Playwright version: $PLAYWRIGHT_VERSION" | |
| echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV | |
| - name: Build Playwright container | |
| run: | | |
| docker build --build-arg PLAYWRIGHT_VERSION=v$PLAYWRIGHT_VERSION \ | |
| --build-arg FRONT_TESTS_IMAGE=${{ fromJSON(needs.build.outputs.stable_tags).front-tests }} \ | |
| -t osrd-playwright:latest \ | |
| - <docker/Dockerfile.playwright-ci | |
| - name: Startup the test infrastructure | |
| id: start_playwright_worker | |
| run: | | |
| set -euo pipefail | |
| export TAG='${{ needs.build.outputs.stable_version }}' | |
| export GATEWAY_FLAVOR='front' | |
| # Inside /docker/osrdyne.yml, replace core_image "osrd-core:dev" with "osrd-core:$TAG" | |
| # to match the version of the core image we just built inside osrdyne | |
| sed -i "s/osrd-core:dev/osrd-core:$TAG/" docker/osrdyne.yml | |
| services='editoast osrdyne core gateway' | |
| composes='-f docker-compose.yml' | |
| docker compose $composes pull --policy missing $services | |
| docker compose $composes up --no-build -d $services jaeger openfga | |
| env: | |
| DOCKER_BUILDKIT: 1 | |
| COMPOSE_DOCKER_CLI_BUILD: 1 | |
| - name: Run Playwright tests | |
| run: | | |
| # Determine the Playwright projects to run | |
| if [[ "${{ github.event_name }}" == "merge_group" || | |
| "${{ github.ref }}" == "refs/heads/dev" || | |
| "${{ github.ref }}" == "refs/heads/staging" ]]; then | |
| TEST_PROJECT="" # Run all browsers | |
| echo "Running Playwright tests on both Chromium and Firefox" | |
| else | |
| TEST_PROJECT="--project=chromium" | |
| echo "Running Playwright tests on Chromium only" | |
| fi | |
| # Run Playwright tests | |
| docker run --init --name=playwright-test --net=host \ | |
| -e CI=true \ | |
| -e PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \ | |
| --ipc=host \ | |
| -v "$PWD/front/test-results:/app/front/test-results" \ | |
| osrd-playwright:latest npx playwright test $TEST_PROJECT | |
| exit $(docker wait playwright-test) | |
| - name: Upload media artifact | |
| if: always() | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: playwright-media | |
| path: | | |
| front/test-results/**/video.webm | |
| front/test-results/**/*.png | |
| retention-days: 30 | |
| - name: Upload trace artifact | |
| if: always() | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: playwright-traces | |
| path: front/test-results/**/trace.zip | |
| retention-days: 30 | |
| - name: Generate GitHub Summary | |
| if: always() | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| GITHUB_RUN_ID: ${{ github.run_id }} | |
| run: | | |
| set -eo pipefail | |
| docker run --init --name=build-report --net=host \ | |
| --ipc=host \ | |
| -e GITHUB_TOKEN="$GITHUB_TOKEN" \ | |
| -e GITHUB_REPOSITORY="$GITHUB_REPOSITORY" \ | |
| -e GITHUB_RUN_ID="$GITHUB_RUN_ID" \ | |
| -v "$PWD/front/test-results:/app/front/test-results" \ | |
| osrd-playwright:latest npx tsx /app/front/tests/reporter/generate-github-summary.ts /app/front/test-results/personalized-report.json /app/front/test-results/summary.md | |
| cat front/test-results/summary.md >> $GITHUB_STEP_SUMMARY | |
| - name: Save container logs | |
| run: docker compose logs > container-logs | |
| if: always() | |
| - uses: actions/upload-artifact@v5 | |
| if: always() | |
| with: | |
| name: e2e-container-logs | |
| path: container-logs | |
| retention-days: 30 | |
| check_reuse_compliance: | |
| runs-on: ubuntu-latest | |
| name: Check reuse compliance | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: REUSE Compliance Check | |
| uses: fsfe/reuse-action@v6 |