Repository navigation
Use d2x 2026.10.21.1 and verify real first-use versions #31
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: Fresh install and first use | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "src/**" | |
| - "solutions/**" | |
| - "d2x/**" | |
| - "mcpp.toml" | |
| - ".d2x.json" | |
| - ".xlings.json" | |
| - ".github/workflows/**" | |
| - ".github/actions/**" | |
| - ".devcontainer/**" | |
| - ".vscode/tasks.json" | |
| - "scripts/**" | |
| - "README*.md" | |
| - "docs/**" | |
| - "book/src/base/chapter_1.md" | |
| - "book/en/src/base/chapter_1.md" | |
| - "book/src/changelog.md" | |
| - "book/en/src/changelog.md" | |
| pull_request: | |
| paths: | |
| - "src/**" | |
| - "solutions/**" | |
| - "d2x/**" | |
| - "mcpp.toml" | |
| - ".d2x.json" | |
| - ".xlings.json" | |
| - ".github/workflows/**" | |
| - ".github/actions/**" | |
| - ".devcontainer/**" | |
| - ".vscode/tasks.json" | |
| - "scripts/**" | |
| - "README*.md" | |
| - "docs/**" | |
| - "book/src/base/chapter_1.md" | |
| - "book/en/src/base/chapter_1.md" | |
| - "book/src/changelog.md" | |
| - "book/en/src/changelog.md" | |
| workflow_dispatch: | |
| inputs: | |
| candidate_run: | |
| description: 'Optional successful d2learn/d2x CI run ID (explicit prerelease override)' | |
| type: string | |
| default: '' | |
| candidate_sha: | |
| description: 'Exact checkout SHA recorded in that candidate provenance' | |
| type: string | |
| default: '' | |
| diagnose: | |
| description: 'Also compare standalone build and checker in separate cold Windows environments' | |
| type: boolean | |
| default: false | |
| schedule: | |
| - cron: '23 4 * * 1' | |
| permissions: | |
| contents: read | |
| actions: read | |
| env: | |
| XLINGS_NON_INTERACTIVE: '1' | |
| D2X_CANDIDATE_SHA: ${{ inputs.candidate_sha }} | |
| D2X_CANDIDATE_DIR: .d2x/candidate | |
| jobs: | |
| native: | |
| if: ${{ !inputs.diagnose }} | |
| name: fresh (${{ matrix.os }}, ${{ matrix.route }}, MSVC=${{ !matrix.mask_msvc }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [macos-14, windows-2022, windows-2025] | |
| route: [readme, cold] | |
| mask_msvc: [false] | |
| include: | |
| - {os: windows-2025, route: readme, mask_msvc: true} | |
| - {os: windows-2025, route: cold, mask_msvc: true} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| if: inputs.candidate_run != '' | |
| with: | |
| repository: d2learn/d2x | |
| run-id: ${{ inputs.candidate_run }} | |
| github-token: ${{ github.token }} | |
| name: ${{ runner.os == 'Linux' && 'candidate-linux-x86_64' || format('candidate-{0}', matrix.os) }} | |
| path: ${{ env.D2X_CANDIDATE_DIR }} | |
| - name: Verify explicit candidate provenance | |
| if: inputs.candidate_run != '' | |
| shell: bash | |
| run: ${{ runner.os == 'Windows' && 'python' || 'python3' }} scripts/ci/candidate.py | |
| - name: Select an empty toolchain home | |
| shell: bash | |
| run: echo "MCPP_HOME=$RUNNER_TEMP/d2mcpp-fresh" >> "$GITHUB_ENV" | |
| - name: Assert host architecture | |
| shell: bash | |
| run: | | |
| uname -a | |
| if [[ "$RUNNER_OS" == macOS ]]; then test "$(uname -m)" = arm64; fi | |
| test ! -e target | |
| test ! -e .d2x/state.json | |
| - name: Mask MSVC | |
| if: matrix.mask_msvc | |
| shell: powershell | |
| run: ./scripts/ci/mask-msvc.ps1 | |
| - name: Follow the README install and practice commands (Unix) | |
| if: runner.os != 'Windows' && matrix.route == 'readme' | |
| run: python3 scripts/ci/readme.py | |
| - name: Follow the README install and practice commands (PowerShell 5.1) | |
| if: runner.os == 'Windows' && matrix.route == 'readme' | |
| shell: powershell | |
| run: python scripts/ci/readme.py | |
| - name: Cold install only (Unix) | |
| if: runner.os != 'Windows' && matrix.route == 'cold' | |
| run: python3 scripts/ci/prepare.py --install-only | |
| - name: Cold install only (PowerShell 5.1) | |
| if: runner.os == 'Windows' && matrix.route == 'cold' | |
| shell: powershell | |
| run: python scripts/ci/prepare.py --install-only | |
| - name: First check, save, advance and resume | |
| if: matrix.route == 'cold' | |
| shell: bash | |
| run: python scripts/ci/first-run.py --allow-source-edit --cold | |
| - name: Cold route also verifies all reference answers | |
| if: matrix.route == 'cold' | |
| run: python scripts/ci/solutions.py | |
| - name: Assert GNU target without MSVC | |
| if: matrix.mask_msvc | |
| shell: bash | |
| env: | |
| ROUTE: ${{ matrix.route }} | |
| run: | | |
| logs="$(pwd)/.d2x/ci-logs" | |
| if [[ "$ROUTE" == readme ]]; then cd "$(cat "$logs/readme-course-path.txt")"; fi | |
| # doctor returns nonzero for warnings too (missing MSVC is expected). | |
| mcpp self doctor > "$logs/doctor.txt" 2>&1 || true | |
| cat "$logs/doctor.txt" | |
| grep -q 'gcc.*what a build here uses' "$logs/doctor.txt" | |
| grep -q 'payload mingw-gcc' "$logs/doctor.txt" | |
| grep -q 'x86_64.*windows-gnu' "$logs/doctor.txt" | |
| ls -d target/*windows-gnu | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: first-run-${{ matrix.os }}-${{ matrix.route }}-${{ matrix.mask_msvc || false }} | |
| path: .d2x/ci-logs/ | |
| if-no-files-found: ignore | |
| include-hidden-files: true | |
| linux-minimal: | |
| if: ${{ !inputs.diagnose }} | |
| name: fresh (Linux without a compiler, ${{ matrix.route }}) | |
| runs-on: ubuntu-24.04 | |
| container: ubuntu:24.04 | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| route: [readme, cold] | |
| steps: | |
| - name: Install transport and CI tools, no C++ compiler | |
| run: | | |
| apt-get update -qq | |
| DEBIAN_FRONTEND=noninteractive apt-get install -y curl ca-certificates git xz-utils unzip python3 | |
| useradd -m -s /bin/bash learner | |
| ! command -v g++ | |
| ! command -v clang++ | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| if: inputs.candidate_run != '' | |
| with: | |
| repository: d2learn/d2x | |
| run-id: ${{ inputs.candidate_run }} | |
| github-token: ${{ github.token }} | |
| name: candidate-linux-x86_64 | |
| path: ${{ env.D2X_CANDIDATE_DIR }} | |
| - name: Verify explicit candidate provenance | |
| if: inputs.candidate_run != '' | |
| shell: bash | |
| run: ${{ runner.os == 'Windows' && 'python' || 'python3' }} scripts/ci/candidate.py | |
| - name: Give the ordinary user a fresh checkout | |
| shell: bash | |
| env: | |
| ROUTE: ${{ matrix.route }} | |
| run: | | |
| course_dir="$GITHUB_WORKSPACE" | |
| if [[ "$ROUTE" == readme ]]; then | |
| course_dir="/home/learner/first use with spaces/$(python3 -c 'print("long-project-directory-" * 6)')" | |
| mkdir -p "$course_dir" | |
| cp -a "$GITHUB_WORKSPACE/." "$course_dir/" | |
| fi | |
| chown -R learner:learner "$course_dir" | |
| echo "COURSE_DIR=$course_dir" >> "$GITHUB_ENV" | |
| - name: Follow the README or start checker cold | |
| shell: bash | |
| env: | |
| ROUTE: ${{ matrix.route }} | |
| run: | | |
| cd "$COURSE_DIR" | |
| if [[ "$ROUTE" == cold ]]; then | |
| runuser -u learner -- python3 scripts/ci/prepare.py --install-only | |
| runuser -u learner -- env MCPP_HOME=/home/learner/.mcpp PATH="/home/learner/.xlings/subos/current/bin:$PATH" python3 scripts/ci/first-run.py --allow-source-edit --cold | |
| runuser -u learner -- env PATH="/home/learner/.xlings/subos/current/bin:$PATH" python3 scripts/ci/solutions.py | |
| else | |
| runuser -u learner -- python3 scripts/ci/readme.py | |
| fi | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: first-run-linux-${{ matrix.route }} | |
| path: ${{ env.COURSE_DIR }}/.d2x/ci-logs/ | |
| if-no-files-found: ignore | |
| include-hidden-files: true | |
| released-course: | |
| name: Published d2x install route (main only) | |
| if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' && inputs.candidate_run == '' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Follow the README using the public course download | |
| run: python3 scripts/ci/readme.py --published | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: published-course-first-use | |
| path: .d2x/ci-logs/ | |
| if-no-files-found: ignore | |
| include-hidden-files: true | |
| cold-diagnostics: | |
| if: inputs.diagnose | |
| runs-on: windows-2025 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| route: [build, run, checker] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Mask MSVC | |
| shell: powershell | |
| run: ./scripts/ci/mask-msvc.ps1 | |
| - name: Select independent cold home | |
| shell: bash | |
| run: echo "MCPP_HOME=$RUNNER_TEMP/diagnostic-${{ matrix.route }}" >> "$GITHUB_ENV" | |
| - name: Install tools only | |
| shell: powershell | |
| run: python scripts/ci/prepare.py --install-only | |
| - name: Diagnose baseline cold startup | |
| shell: bash | |
| env: | |
| DIAGNOSTIC_ROUTE: ${{ matrix.route }} | |
| run: python scripts/ci/cold-diagnostics.py | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: cold-diagnostic-${{ matrix.route }} | |
| path: .d2x/ci-logs/ | |
| include-hidden-files: true | |
| latest-stable: | |
| if: github.ref == 'refs/heads/main' && inputs.candidate_run == '' | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-24.04, macos-14, windows-2025] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install xlings (Unix) | |
| if: runner.os != 'Windows' | |
| run: bash scripts/install-xlings.sh | |
| - name: Install xlings (PowerShell 5.1) | |
| if: runner.os == 'Windows' | |
| shell: powershell | |
| run: ./scripts/install-xlings.ps1 | |
| - name: Check stable release, public latest and course pin | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: ${{ runner.os == 'Windows' && 'python' || 'python3' }} scripts/ci/latest.py | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: latest-stable-versions-${{ matrix.os }} | |
| path: .d2x/ci-logs/ | |
| include-hidden-files: true |