Put a placeholder where the example carried a real secret #333
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: CI | |
| on: | |
| push: | |
| # develop as well as main. Work reaches the integration branch by merge and | |
| # occasionally by direct push, and neither used to run anything here, so a | |
| # regression could sit on develop until some later pull request inherited it. | |
| branches: [main, develop] | |
| pull_request: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Nothing here writes back to the repository. Without a declaration the | |
| # workflow token carries whatever the repository default grants, which is | |
| # usually write, and a checkout plus a third-party dependency install is the | |
| # wrong place to be holding it. Jobs that need more can ask for it locally. | |
| permissions: | |
| contents: read | |
| jobs: | |
| lint: | |
| name: Lint and format | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install ruff | |
| run: python -m pip install "ruff==0.15.20" "PyYAML>=6" | |
| - name: Lint | |
| run: ruff check BalloonPoppingGymEnv/ tests/ doc/examples/ scripts/ | |
| - name: Format check | |
| run: ruff format --check BalloonPoppingGymEnv/ tests/ doc/examples/ scripts/ | |
| # Here as well as in the suite, because the suite is the thing it checks: | |
| # delete the `test` job and the only run left to notice is the one that | |
| # cannot block. Reads the workflow as data, so it needs no simulator. | |
| - name: Check CI tests what it says it tests | |
| run: python -m unittest tests.test_ci_installs_what_it_checks -v | |
| test: | |
| name: Tests and coverage (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Competitors run this on their own machines, and pyproject.toml claims | |
| # >=3.10, so the floor is tested rather than only asserted. ActiveRocketPy | |
| # already runs its own CI on 3.10. | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.14"] | |
| # Measured at about six minutes for the slower leg. The default ceiling is | |
| # six hours, and this repository has already seen a non-finite command leave | |
| # the solver refusing to return. | |
| timeout-minutes: 25 | |
| env: | |
| # Whether the token exists, not the token. `secrets` cannot be read from a | |
| # step's `if`, which is why this is here at all, and putting the value | |
| # itself here hands it to pip, pytest and everything they start. | |
| HAS_CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN != '' }} | |
| # Run the opt-in slow regression tests (e.g. the scenario #1 Monte Carlo | |
| # golden master) in CI; they are skipped by default for fast local runs. | |
| BPC_RUN_SLOW_TESTS: "1" | |
| # Without this the matrix is decoration: uv takes its interpreter from | |
| # .python-version, which pins 3.14, so the leg named 3.10 would build a | |
| # 3.14 environment and quietly retire the floor #75 exists to test. | |
| UV_PYTHON: ${{ matrix.python-version }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| # Install what the lockfile pins. The old unpinned `pip install` sat next | |
| # to a `uv lock --check` that said nothing about it: the lockfile pinned | |
| # matplotlib 3.10.9, numpy 2.4.5, scipy 1.17.1 and CI installed 3.11.1, | |
| # 2.5.1, 1.18.0. `--locked` also catches a stale lock against the submodule. | |
| - name: Install the locked dependencies | |
| run: | | |
| python -m pip install "uv==0.11.14" | |
| uv sync --locked --extra dev | |
| # Fail if the leg is not running the version it is named for. #89 cost | |
| # time because nothing recorded which versions CI had installed. | |
| - name: Report and check the environment | |
| run: | | |
| uv run --no-sync python -VV | |
| uv run --no-sync python -c "import sys; \ | |
| got = '.'.join(map(str, sys.version_info[:2])); \ | |
| want = '${{ matrix.python-version }}'; \ | |
| assert got == want, f'this leg is running {got}, not {want}'" | |
| uv pip freeze | |
| # --no-sync, so this runs the environment the step above built rather | |
| # than letting uv re-resolve on the way past. | |
| - name: Run tests with coverage | |
| run: | | |
| uv run --no-sync pytest tests/ \ | |
| --cov=BalloonPoppingGymEnv --cov-report=xml --cov-report=term | |
| - name: Upload coverage artifact | |
| if: ${{ !cancelled() }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-xml-py${{ matrix.python-version }} | |
| path: coverage.xml | |
| # A run that produced no coverage at all has nothing to say about | |
| # coverage, and `warn` lets it upload nothing and still look fine. | |
| if-no-files-found: error | |
| # Skipped until a CODECOV_TOKEN repository secret is configured. | |
| - name: Upload coverage to Codecov | |
| if: ${{ env.HAS_CODECOV_TOKEN == 'true' && matrix.python-version == '3.14' }} | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: coverage.xml | |
| # Fails once there is a token to fail with. Without one this step does | |
| # not run at all, so this cannot turn a missing secret into a red run. | |
| fail_ci_if_error: true | |
| latest-dependencies: | |
| name: Latest dependencies, Python ${{ matrix.python-version }} (early warning) | |
| runs-on: ubuntu-latest | |
| # The gate installs what the lockfile pins, so nothing there would notice a | |
| # new release breaking the package. Matplotlib 3.11 took out the default | |
| # renderer (#89) and CI only saw it because CI installed unpinned too. | |
| # | |
| # So an unpinned install keeps running, under its own name, and does not | |
| # block: a release on PyPI should tell us something rather than stop | |
| # unrelated work from merging. Fast suite only, because it is looking for | |
| # import and API breakage rather than trajectory drift. | |
| # | |
| # Both versions, because the old matrix covered both and pip does not | |
| # resolve the same stack on each: the lockfile itself carries numpy 2.2.6 | |
| # for Python < 3.11 and 2.4.5 above it. | |
| # | |
| # This is the contributor install, `requirements-dev.txt`, not the one the | |
| # README gives a competitor. That one is `requirements.txt`, which installs | |
| # ActiveRocketPy as a built wheel rather than editable, so it can fail in | |
| # ways this cannot see. Worth covering separately rather than mislabelling | |
| # this as covering it. | |
| continue-on-error: true | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.14"] | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install the newest dependencies pip will resolve | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements-dev.txt | |
| - name: Report what that resolved to | |
| run: | | |
| python -VV | |
| python -m pip list | |
| - name: Run tests | |
| run: pytest tests/ -q |