From 08b206c132c0ffb1a5ec446b647df684c2beb332 Mon Sep 17 00:00:00 2001 From: Toma <847775+redfish4ktc@users.noreply.github.com> Date: Sun, 4 Oct 2026 06:00:22 +0200 Subject: [PATCH] ci: build the projects with the build all examples script The CI build job used a matrix listing every project by hand, so adding or removing an example also required updating the workflow. The projects are now built by `build-all-examples.bash --fail-at-end`, which discovers them from the `projects` directory, so the matrix only keeps the maxGraph package variants (release and development). This reduces the number of jobs from 14 to 2, each running `npm ci` once instead of once per project. The script previously built everything with `npm run build --workspaces`, which gives no control on failures: npm always keeps going after a failing workspace, reports the error inline and only exposes the exit code of the last failure. The script then stopped because of `set -e`, so the bundle sizes were never displayed and there was no summary of the failed examples. npm provides no option to change this. The examples are now built one by one with `npm run build -w`, like in the maxGraph repository script. By default, the script stops at the first failure. With `--fail-at-end`, all examples are built, the sizes are displayed, then the failed examples are listed and the script exits non-zero. The shared project is still built first and outside the loop, and its failure always stops the script. npm does not order workspaces by dependency (the examples do not even declare it in their package.json, they resolve it through the workspace symlink), so relying on the alphabetical order would be fragile. It was also built twice before, as `projects/*` matches it. The `dist` directories of the release build are now uploaded as a single artifact keeping the `/dist` layout, and the job assembling the GitHub Pages site restructures it into one directory per project. The workflow now also runs when the script changes, and the runners are bumped from ubuntu-22.04 to ubuntu-24.04. Co-Authored-By: Claude Opus 5.5 --- .../workflows/check-typescript-projects.yml | 42 +++--- build-all-examples.bash | 129 ++++++++++++------ 2 files changed, 110 insertions(+), 61 deletions(-) diff --git a/.github/workflows/check-typescript-projects.yml b/.github/workflows/check-typescript-projects.yml index ebd5c47..a4c0d83 100644 --- a/.github/workflows/check-typescript-projects.yml +++ b/.github/workflows/check-typescript-projects.yml @@ -8,6 +8,7 @@ on: - main paths: - '.github/workflows/check-typescript-projects.yml' + - 'build-all-examples.bash' - 'projects/**/*' - '.nvmrc' - 'package.json' @@ -17,6 +18,7 @@ on: - main paths: - '.github/workflows/check-typescript-projects.yml' + - 'build-all-examples.bash' - 'projects/**/*' - '.nvmrc' - 'package.json' @@ -24,7 +26,7 @@ on: jobs: build_maxgraph_dev_package: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 with: @@ -47,20 +49,12 @@ jobs: packages/core/maxgraph-core-*.tgz build_projects: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: [build_maxgraph_dev_package] strategy: # don't cancel running jobs even if one fails fail-fast: false matrix: - project: - - farm-ts - - lit-ts - - parcel-ts - - rollup-ts - - rsbuild-ts - - sveltekit-ts - - vitejs-ts npm-package: ['release', 'development'] steps: - name: Download the maxgraph npm package @@ -83,33 +77,35 @@ jobs: if: ${{ matrix.npm-package == 'development' }} # use wildcard as the file contains the version, and we don't know it run: npm install ${{steps.download.outputs.download-path}}/maxgraph-core*.tgz - - name: Build project - run: npm run build -w projects/_shared -w projects/${{matrix.project}} - - name: Upload project archive + - name: Build projects + run: ./build-all-examples.bash --fail-at-end + - name: Upload projects archive if: ${{ matrix.npm-package == 'release' }} uses: actions/upload-artifact@v7 with: - name: ${{matrix.project}} - path: ${{github.workspace}}/projects/${{matrix.project}}/dist + name: all-projects-dist + # the layout /dist is kept, as the paths are relative to the 'projects' directory + path: ${{github.workspace}}/projects/*/dist # bundle everything in a single bundle + create home page create_all-in-one_artifact: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: 'build_projects' steps: - - name: Download all artifacts + - name: Download projects artifact uses: actions/download-artifact@v8 with: + name: all-projects-dist path: tmp - - name: Display structure of downloaded files after removing maxgraph-npm-package - run: | - rm -rf maxgraph-npm-package - ls -lhR + - name: Display structure of downloaded files + run: ls -lhR working-directory: tmp - name: Build the final directories layout run: | mkdir -p build - cp -R tmp/* build + for project_dist_dir in tmp/*/dist; do + cp -R "$project_dist_dir" "build/$(basename "$(dirname "$project_dist_dir")")" + done - name: List projects that will be referenced in the home page id: list_projects run: | @@ -172,7 +168,7 @@ jobs: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Deploy to GitHub Pages id: deployment diff --git a/build-all-examples.bash b/build-all-examples.bash index 0bf4d00..762a3f8 100755 --- a/build-all-examples.bash +++ b/build-all-examples.bash @@ -1,57 +1,110 @@ #!/usr/bin/env bash set -euo pipefail -# This script builds all examples in the packages directory. -# From the root of the repository, run " ./build-all-examples.bash" +# This script builds all examples in the projects directory. +# From the root of the repository, run "./build-all-examples.bash" +usage() { + echo "Usage: $0 [OPTIONS]" + echo + echo "Build all examples and display bundle sizes." + echo + echo "Options:" + echo " --fail-at-end Keep building the remaining examples after a failure, and report all the failures at the" + echo " very end, after the size sections. Exit non-zero if any build failed. Without this option," + echo " the script stops at the first failing build. A failure of the shared project always stops" + echo " the script, as all examples depend on it. No effect with --list-size-only, which builds" + echo " nothing." + echo " --list-size-only Skip building, only display bundle sizes from existing dist/ directories" + echo " --help Show this help message" + return 0 +} -# Check for command line arguments LIST_SIZE_ONLY=false -if [[ $# -gt 0 && "$1" == "--list-size-only" ]]; then - LIST_SIZE_ONLY=true -fi +FAIL_AT_END=false +while [[ $# -gt 0 ]]; do + case "$1" in + --help) usage; exit 0 ;; + --fail-at-end) FAIL_AT_END=true ;; + --list-size-only) LIST_SIZE_ONLY=true ;; + *) echo "Unknown option: $1"; usage; exit 1 ;; + esac + shift +done + +SHARED_PROJECT_DIR="projects/_shared" + +EXAMPLE_DIRS=() +for dir in projects/*; do + if [[ -d "$dir" && "$dir" != "$SHARED_PROJECT_DIR" ]]; then + EXAMPLE_DIRS+=("$dir") + fi +done + +print_section_title() { + echo + echo "##################################################" + echo "$1" + echo "##################################################" +} + +FAILED_EXAMPLES=() -if [ "$LIST_SIZE_ONLY" = true ]; then +if [[ "$LIST_SIZE_ONLY" = true ]]; then echo "Skip building examples." else echo "Building all examples..." - npm run build -w projects/_shared - npm run build --workspaces + # Built first and outside the loop: npm does not order workspaces by dependency, and building the examples against + # a stale or missing shared library would give misleading results. + print_section_title "Building $SHARED_PROJECT_DIR" + npm run build -w "$SHARED_PROJECT_DIR" + for dir in "${EXAMPLE_DIRS[@]}"; do + print_section_title "Building $dir" + if [[ "$FAIL_AT_END" = true ]]; then + build_exit_code=0 + npm run build -w "$dir" || build_exit_code=$? + if [[ "$build_exit_code" -ne 0 ]]; then + echo "Build of $dir FAILED with exit code $build_exit_code" + FAILED_EXAMPLES+=("$(basename "$dir") (exit code $build_exit_code)") + fi + else + npm run build -w "$dir" + fi + done -# for dir in packages/ts-example* packages/js-example*; do -# if [ -d "$dir" ]; then -# echo -# echo "##################################################" -# echo "Building $dir" -# echo "##################################################" -# (cd "$dir" && npm run build) -# fi -# done - - echo "All examples built successfully." + if [[ ${#FAILED_EXAMPLES[@]} -eq 0 ]]; then + echo "All examples built successfully." + else + echo "${#FAILED_EXAMPLES[@]} example(s) failed to build, see the summary at the end." + fi fi -for dir in projects/*; do - if [ -d "$dir" ]; then - echo - echo "##################################################" - echo "Files in $dir/dist directory:" - echo "##################################################" - - if [ -d "$dir/dist" ]; then - # Find all JS files and display sizes with 2 decimal places - # Use 1000 to match Vite's size display - find "$dir/dist" -name "*.js" -type f -exec ls -l {} \; | LC_NUMERIC=C awk '{ - # Convert bytes to KB with 2 decimal places - size_kb = $5 / 1000 - printf "%.2f kB %s\n", size_kb, $9 - }' - else - echo "No dist directory found in $dir" - fi +for dir in "${EXAMPLE_DIRS[@]}"; do + print_section_title "Files in $dir/dist directory:" + + if [[ -d "$dir/dist" ]]; then + # Find all JS files and display sizes with 2 decimal places + # Use 1000 to match Vite's size display + find "$dir/dist" -name "*.js" -type f -exec ls -l {} \; | LC_NUMERIC=C awk '{ + # Convert bytes to KB with 2 decimal places + size_kb = $5 / 1000 + printf "%.2f kB %s\n", size_kb, $9 + }' + else + echo "No dist directory found in $dir" fi done +if [[ ${#FAILED_EXAMPLES[@]} -gt 0 ]]; then + print_section_title "Failed builds" + echo + for failed_example in "${FAILED_EXAMPLES[@]}"; do + echo "- $failed_example" + done + echo + echo "${#FAILED_EXAMPLES[@]} example(s) failed to build." + exit 1 +fi