mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-11-10 19:07:11 +01:00
Gate the invariants, fix ECOTE's unrunnable tests, contain build output
Two invariants had been established by hand and left ungated, which is the
"a remedy that only works if someone remembers" pattern:
- scripts/check_ignore_consistency.sh fails the commit if any TRACKED file
is also gitignored. .binary-allowlist used to *instruct* the reader to
re-run that check; now it is enforced. Verified both ways -- passes on the
tree, and fails when an ignored file is force-added.
DOCS-runnability.md now really has two columns. Each environment writes only
its own gates/runnability-<env>.tsv and the doc renders from both, so a CI run
cannot clobber the local results. The ci tsv is gitignored: committing a copy
generated here would label this machine's capabilities as the runner's.
Rendering it surfaced a classic bug -- awk's NR==FNR idiom silently swallows
the SECOND file when the first is empty, so the table came out with a header
and no rows. It compares FILENAME instead.
runnability.yml deliberately does NOT diff against a committed baseline. A
status is a property of the machine, so `runnable` locally and `blocked` on a
runner is correct rather than drift, and diffing would make the workflow red
by construction. It fails on `error` instead -- a runner that crashes or
reports an unknown kind.
Then five more courses were actually run, because EADS alone had produced four
real bugs and one sample proves nothing:
- ECOAR and EPFU build (nasm + 32-bit gcc, and gcc respectively).
- ECOTE's 17 test modules could not run AT ALL. Its package is named `code/`,
which shadows the standard library: pytest's debugging plugin imports pdb,
pdb imports code, and it got this directory instead, so the suite died
with an INTERNALERROR before collecting a single test. Renamed to
translator/ with all 17 imports updated -- 26 tests now pass.
- A LaTeX report builds. That one exposed a hazard rather than a bug:
latexmk wrote its PDF beside the source, and in a course where the built
name matches the submitted one it would have silently overwritten a
tracked deliverable. Both the LaTeX and C++ runners now build into a
gitignored build/, and rebuilding ECOGR leaves `git status` empty.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
This commit is contained in:
parent
badc21d653
commit
e512bde26f
@ -18,9 +18,10 @@
|
|||||||
# - the repo root, gates/, scripts/ and .github/ have no entry either, so a
|
# - the repo root, gates/, scripts/ and .github/ have no entry either, so a
|
||||||
# binary added there is blocked.
|
# binary added there is blocked.
|
||||||
#
|
#
|
||||||
# Every pattern here must also survive `git ls-files | git check-ignore
|
# An allowlisted file that .gitignore ALSO matches fails silently on
|
||||||
# --stdin --no-index` printing nothing -- an allowlisted file that .gitignore
|
# `git add` rather than erroring. That is enforced, not remembered: the
|
||||||
# also matches fails silently on `git add` rather than erroring.
|
# ignore-consistency pre-commit hook (scripts/check_ignore_consistency.sh)
|
||||||
|
# fails the commit if any tracked file is gitignored.
|
||||||
|
|
||||||
# --- Reports and presentations (155 .pdf, 3 .docx, 1 .doc, 1 .pptx) ---------
|
# --- Reports and presentations (155 .pdf, 3 .docx, 1 .doc, 1 .pptx) ---------
|
||||||
Programming/*.pdf
|
Programming/*.pdf
|
||||||
|
|||||||
40
.github/workflows/runnability.yml
vendored
Normal file
40
.github/workflows/runnability.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
name: runnability
|
||||||
|
|
||||||
|
# Probes every course directory and fails if any RUNNER is broken.
|
||||||
|
#
|
||||||
|
# Deliberately NOT a diff against a committed baseline. A runner's status is a
|
||||||
|
# property of the machine, not of the commit: MATLAB, Unity and the .NET SDK
|
||||||
|
# are absent here and present locally, so `runnable` on a laptop and `blocked`
|
||||||
|
# on ubuntu-latest is correct rather than drift. Diffing the two would make
|
||||||
|
# this workflow red by construction, which is the one outcome the whole
|
||||||
|
# exercise is meant to avoid.
|
||||||
|
#
|
||||||
|
# What IS a defect, and what this catches: a run.sh that crashes, hangs, or
|
||||||
|
# reports an unknown kind. Those are `error`, and any `error` fails the job.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
runnability:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Probe every course directory
|
||||||
|
run: ./run.sh status
|
||||||
|
|
||||||
|
- name: Fail on any broken runner
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if grep -qP '\terror\t' gates/runnability-ci.tsv; then
|
||||||
|
echo "::error::a course run.sh failed to probe"
|
||||||
|
grep -P '\terror\t' gates/runnability-ci.tsv
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "all runners probed cleanly"
|
||||||
|
cut -f2 gates/runnability-ci.tsv | sort | uniq -c
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -482,3 +482,7 @@ Programming/ERSMS-project/nginx/ssl/nginx.crt
|
|||||||
|
|
||||||
# Output of ./run.sh run <dir> for the C++ courses.
|
# Output of ./run.sh run <dir> for the C++ courses.
|
||||||
build/
|
build/
|
||||||
|
|
||||||
|
# Generated fresh by the runner on each CI run. Committing a local copy
|
||||||
|
# would label this machine capabilities as the runner is, which is a lie.
|
||||||
|
gates/runnability-ci.tsv
|
||||||
|
|||||||
@ -56,6 +56,15 @@ repos:
|
|||||||
language: script
|
language: script
|
||||||
pass_filenames: true
|
pass_filenames: true
|
||||||
|
|
||||||
|
# A tracked file that .gitignore also matches fails silently on
|
||||||
|
# `git add`. 130 of those were fixed by hand; this keeps them fixed.
|
||||||
|
- id: ignore-consistency
|
||||||
|
name: no tracked file is gitignored
|
||||||
|
entry: scripts/check_ignore_consistency.sh
|
||||||
|
language: script
|
||||||
|
pass_filenames: false
|
||||||
|
always_run: true
|
||||||
|
|
||||||
# Thin shim into ~/utils, which owns the four markdown namespaces.
|
# Thin shim into ~/utils, which owns the four markdown namespaces.
|
||||||
- id: md-naming
|
- id: md-naming
|
||||||
name: markdown naming convention
|
name: markdown naming convention
|
||||||
|
|||||||
@ -2,53 +2,57 @@
|
|||||||
|
|
||||||
Generated by `./run.sh status`. Do not edit by hand.
|
Generated by `./run.sh status`. Do not edit by hand.
|
||||||
|
|
||||||
Status is recorded PER ENVIRONMENT. A directory that is `runnable` locally and
|
Status is recorded PER ENVIRONMENT, from `gates/runnability-local.tsv` and
|
||||||
|
`gates/runnability-ci.tsv`. A directory that is `runnable` locally and
|
||||||
`blocked` in CI is the normal case, not drift: the runner has no MATLAB, no
|
`blocked` in CI is the normal case, not drift: the runner has no MATLAB, no
|
||||||
Unity and no .NET SDK. CI compares only its own column.
|
Unity and no .NET SDK. Each environment rewrites only its own file, so a CI
|
||||||
|
run cannot clobber the local column.
|
||||||
|
|
||||||
| Course | local | Detail |
|
`-` means that environment has not probed yet.
|
||||||
|---|---|---|
|
|
||||||
| `NotProgramming/DPZ` | runnable | builds the report with latexmk |
|
| Course | local | ci | Detail (local) |
|
||||||
| `NotProgramming/ECOGR` | runnable | builds the report with latexmk |
|
|---|---|---|---|
|
||||||
| `NotProgramming/EDABA` | runnable | builds the report with latexmk |
|
| `NotProgramming/DPZ` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/EDABA-LAB` | runnable | builds the report with latexmk |
|
| `NotProgramming/ECOGR` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/EDISE` | runnable | builds the report with latexmk |
|
| `NotProgramming/EDABA` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/EDISP` | no-code | submitted lab reports as PDFs only; no source was produced |
|
| `NotProgramming/EDABA-LAB` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/ELAC` | runnable | builds the report with latexmk |
|
| `NotProgramming/EDISE` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/EMISY` | runnable | builds the report with latexmk |
|
| `NotProgramming/EDISP` | no-code | - | submitted lab reports as PDFs only; no source was produced |
|
||||||
| `NotProgramming/ENUME` | blocked | needs MATLAB or Octave (none of: matlab octave) |
|
| `NotProgramming/ELAC` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/EPHY2` | no-code | submitted lab reports as PDFs only; no source was produced |
|
| `NotProgramming/EMISY` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/EPOGAI` | no-code | a presentation only; no source was produced |
|
| `NotProgramming/ENUME` | blocked | - | needs MATLAB or Octave (none of: matlab octave) |
|
||||||
| `NotProgramming/ERPM` | runnable | builds the report with latexmk |
|
| `NotProgramming/EPHY2` | no-code | - | submitted lab reports as PDFs only; no source was produced |
|
||||||
| `NotProgramming/ESDP1` | runnable | builds the report with latexmk |
|
| `NotProgramming/EPOGAI` | no-code | - | a presentation only; no source was produced |
|
||||||
| `NotProgramming/ESOEN` | runnable | builds the report with latexmk |
|
| `NotProgramming/ERPM` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/MOM` | runnable | builds the report with latexmk |
|
| `NotProgramming/ESDP1` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/SDM` | runnable | builds the report with latexmk |
|
| `NotProgramming/ESOEN` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/SDM2` | runnable | builds the report with latexmk |
|
| `NotProgramming/MOM` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/SPD` | runnable | builds the report with latexmk |
|
| `NotProgramming/SDM` | runnable | - | builds the report with latexmk |
|
||||||
| `NotProgramming/STUP` | runnable | npm install && npm start |
|
| `NotProgramming/SDM2` | runnable | - | builds the report with latexmk |
|
||||||
| `Programming/AIS` | runnable | builds the report with latexmk |
|
| `NotProgramming/SPD` | runnable | - | builds the report with latexmk |
|
||||||
| `Programming/BD2` | runnable | npm install && npm start |
|
| `NotProgramming/STUP` | runnable | - | npm install && npm start |
|
||||||
| `Programming/BSS` | runnable | builds the report with latexmk |
|
| `Programming/AIS` | runnable | - | builds the report with latexmk |
|
||||||
| `Programming/EADS` | runnable | compiles each standalone .cpp |
|
| `Programming/BD2` | runnable | - | npm install && npm start |
|
||||||
| `Programming/EARIN` | runnable | python3 the entry script |
|
| `Programming/BSS` | runnable | - | builds the report with latexmk |
|
||||||
| `Programming/ECOAR` | runnable | make |
|
| `Programming/EADS` | runnable | - | compiles each standalone .cpp |
|
||||||
| `Programming/ECOTE` | runnable | python3 /home/kuhy/WUT_Computer_Science/Programming/ECOTE/program/code/main.py |
|
| `Programming/EARIN` | runnable | - | python3 the entry script |
|
||||||
| `Programming/ECRYPT` | no-code | test1.py is a 0-byte stub; this course produced no submitted code |
|
| `Programming/ECOAR` | runnable | - | make |
|
||||||
| `Programming/ECRYPT_PROJECT` | runnable | python3 /home/kuhy/WUT_Computer_Science/Programming/ECRYPT_PROJECT/code |
|
| `Programming/ECOTE` | runnable | - | python3 /home/kuhy/WUT_Computer_Science/Programming/ECOTE/program/translator/main.py |
|
||||||
| `Programming/EGUI` | runnable | dotnet build |
|
| `Programming/ECRYPT` | no-code | - | test1.py is a 0-byte stub; this course produced no submitted code |
|
||||||
| `Programming/EOOP` | runnable | compiles each standalone .cpp |
|
| `Programming/ECRYPT_PROJECT` | runnable | - | python3 /home/kuhy/WUT_Computer_Science/Programming/ECRYPT_PROJECT/code |
|
||||||
| `Programming/EOPSY` | runnable | make |
|
| `Programming/EGUI` | runnable | - | dotnet build |
|
||||||
| `Programming/EPFU` | runnable | make |
|
| `Programming/EOOP` | runnable | - | compiles each standalone .cpp |
|
||||||
| `Programming/E-PSYOPS` | runnable | opens in the Unity editor |
|
| `Programming/EOPSY` | runnable | - | make |
|
||||||
| `Programming/ERSMS-project` | runnable | docker compose up |
|
| `Programming/EPFU` | runnable | - | make |
|
||||||
| `Programming/NLP` | runnable | python3 the entry script |
|
| `Programming/E-PSYOPS` | runnable | - | opens in the Unity editor |
|
||||||
| `Programming/PBAD` | runnable | jupyter nbconvert --execute |
|
| `Programming/ERSMS-project` | runnable | - | docker compose up |
|
||||||
| `Programming/PORR` | runnable | python3 /home/kuhy/WUT_Computer_Science/Programming/PORR/code |
|
| `Programming/NLP` | runnable | - | python3 the entry script |
|
||||||
| `Programming/PSD` | runnable | starts the Kafka/Flink stack (installs packages with sudo) |
|
| `Programming/PBAD` | runnable | - | jupyter nbconvert --execute |
|
||||||
| `Programming/psd_project` | runnable | mvn package |
|
| `Programming/PORR` | runnable | - | python3 /home/kuhy/WUT_Computer_Science/Programming/PORR/code |
|
||||||
| `Programming/TRAK` | runnable | python3 the entry script |
|
| `Programming/PSD` | runnable | - | starts the Kafka/Flink stack (installs packages with sudo) |
|
||||||
| `Programming/twm_4` | runnable | jupyter nbconvert --execute |
|
| `Programming/psd_project` | runnable | - | mvn package |
|
||||||
| `Programming/USD` | no-code | README describes a MetaDrive RL assignment; no implementation was submitted |
|
| `Programming/TRAK` | runnable | - | python3 the entry script |
|
||||||
| `Programming/WDWR` | runnable | python3 the entry script |
|
| `Programming/twm_4` | runnable | - | jupyter nbconvert --execute |
|
||||||
| `Programming/ZPOB` | runnable | builds the report with latexmk |
|
| `Programming/USD` | no-code | - | README describes a MetaDrive RL assignment; no implementation was submitted |
|
||||||
|
| `Programming/WDWR` | runnable | - | python3 the entry script |
|
||||||
|
| `Programming/ZPOB` | runnable | - | builds the report with latexmk |
|
||||||
|
|||||||
@ -1,9 +1,21 @@
|
|||||||
To run unit tests:
|
# ECOTE translator
|
||||||
Enter project environment:
|
|
||||||
|
|
||||||
source /ecote/bin/activate
|
Translates LaTeX `tabular` environments into HTML tables.
|
||||||
|
|
||||||
Run tests:
|
| Path | What it is |
|
||||||
|
|---|---|
|
||||||
|
| `translator/` | The implementation. Entry point `translator/main.py`. |
|
||||||
|
| `translator/functional_tests/` | End-to-end fixtures. |
|
||||||
|
| `unit_tests/test_code/` | 17 pytest modules. |
|
||||||
|
|
||||||
|
## Run the tests
|
||||||
|
|
||||||
|
```bash
|
||||||
python -m pytest unit_tests
|
python -m pytest unit_tests
|
||||||
|
```
|
||||||
|
|
||||||
|
> The package used to be called `code/`, which shadows Python's standard
|
||||||
|
> library `code` module. That is not cosmetic: pytest's debugging plugin
|
||||||
|
> imports `pdb`, `pdb` imports `code`, and it got this directory instead, so
|
||||||
|
> the whole suite died with an INTERNALERROR before collecting a single test.
|
||||||
|
> Renaming it is what makes these tests runnable at all.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Tests begin document function
|
Tests begin document function
|
||||||
"""
|
"""
|
||||||
from code.main import begin_document
|
from translator.main import begin_document
|
||||||
|
|
||||||
# Write python tests for a function translating LaTeX documentclass to html
|
# Write python tests for a function translating LaTeX documentclass to html
|
||||||
def given_empty_then_error():
|
def given_empty_then_error():
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Tests begin document function
|
Tests begin document function
|
||||||
"""
|
"""
|
||||||
from code.main import begin_tabular
|
from translator.main import begin_tabular
|
||||||
|
|
||||||
# Write python tests for a function translating LaTeX documentclass to html
|
# Write python tests for a function translating LaTeX documentclass to html
|
||||||
def given_empty_then_error():
|
def given_empty_then_error():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import command_name_check
|
from translator.main import command_name_check
|
||||||
|
|
||||||
|
|
||||||
def given_valid_then_empty():
|
def given_valid_then_empty():
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Tests document class function
|
Tests document class function
|
||||||
"""
|
"""
|
||||||
from code.main import document_class
|
from translator.main import document_class
|
||||||
|
|
||||||
# Write python tests for a function translating LaTeX documentclass to html
|
# Write python tests for a function translating LaTeX documentclass to html
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import document_class_only_checks
|
from translator.main import document_class_only_checks
|
||||||
|
|
||||||
|
|
||||||
def test_missing_curly_bracket():
|
def test_missing_curly_bracket():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import generic_checks
|
from translator.main import generic_checks
|
||||||
|
|
||||||
|
|
||||||
def test_empty_string():
|
def test_empty_string():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import generic_checks_command
|
from translator.main import generic_checks_command
|
||||||
|
|
||||||
|
|
||||||
def test_empty_string():
|
def test_empty_string():
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Tests begin document function
|
Tests begin document function
|
||||||
"""
|
"""
|
||||||
from code.main import length_conversions
|
from translator.main import length_conversions
|
||||||
|
|
||||||
# Write python tests for a function translating LaTeX documentclass to html
|
# Write python tests for a function translating LaTeX documentclass to html
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import only_pipes_and_space
|
from translator.main import only_pipes_and_space
|
||||||
|
|
||||||
|
|
||||||
def given_empty_then_true():
|
def given_empty_then_true():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import split_columns
|
from translator.main import split_columns
|
||||||
|
|
||||||
|
|
||||||
def given_empty_then_correct():
|
def given_empty_then_correct():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import split_rows
|
from translator.main import split_rows
|
||||||
|
|
||||||
|
|
||||||
def given_empty_then_correct():
|
def given_empty_then_correct():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import tabular_columns_parameters
|
from translator.main import tabular_columns_parameters
|
||||||
|
|
||||||
|
|
||||||
def given_empty_then_error():
|
def given_empty_then_error():
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
Tests tabular_parameters function
|
Tests tabular_parameters function
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from code.main import tabular_parameters
|
from translator.main import tabular_parameters
|
||||||
|
|
||||||
def given_empty_then_empty():
|
def given_empty_then_empty():
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
Tests tabular_parameters function
|
Tests tabular_parameters function
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from code.main import tabular_required_parameters
|
from translator.main import tabular_required_parameters
|
||||||
|
|
||||||
|
|
||||||
def given_empty_then_error():
|
def given_empty_then_error():
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from code.main import translate_column
|
from translator.main import translate_column
|
||||||
|
|
||||||
|
|
||||||
def given_empty_then_correct():
|
def given_empty_then_correct():
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from code.main import translate_inside_to_html
|
from translator.main import translate_inside_to_html
|
||||||
from code.main import tabular_required_parameters
|
from translator.main import tabular_required_parameters
|
||||||
|
|
||||||
|
|
||||||
def given_correct_then_correct():
|
def given_correct_then_correct():
|
||||||
|
|||||||
@ -8,5 +8,5 @@ set -euo pipefail
|
|||||||
. "$(dirname "$(readlink -f "$0")")/../../scripts/course_lib.sh"
|
. "$(dirname "$(readlink -f "$0")")/../../scripts/course_lib.sh"
|
||||||
|
|
||||||
course_main --kind python \
|
course_main --kind python \
|
||||||
--entry "$(dirname "$(readlink -f "$0")")/program/code/main.py" \
|
--entry "$(dirname "$(readlink -f "$0")")/program/translator/main.py" \
|
||||||
-- "$@"
|
-- "$@"
|
||||||
|
|||||||
44
gates/runnability-local.tsv
Normal file
44
gates/runnability-local.tsv
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
NotProgramming/DPZ runnable builds the report with latexmk
|
||||||
|
NotProgramming/ECOGR runnable builds the report with latexmk
|
||||||
|
NotProgramming/EDABA runnable builds the report with latexmk
|
||||||
|
NotProgramming/EDABA-LAB runnable builds the report with latexmk
|
||||||
|
NotProgramming/EDISE runnable builds the report with latexmk
|
||||||
|
NotProgramming/EDISP no-code submitted lab reports as PDFs only; no source was produced
|
||||||
|
NotProgramming/ELAC runnable builds the report with latexmk
|
||||||
|
NotProgramming/EMISY runnable builds the report with latexmk
|
||||||
|
NotProgramming/ENUME blocked needs MATLAB or Octave (none of: matlab octave)
|
||||||
|
NotProgramming/EPHY2 no-code submitted lab reports as PDFs only; no source was produced
|
||||||
|
NotProgramming/EPOGAI no-code a presentation only; no source was produced
|
||||||
|
NotProgramming/ERPM runnable builds the report with latexmk
|
||||||
|
NotProgramming/ESDP1 runnable builds the report with latexmk
|
||||||
|
NotProgramming/ESOEN runnable builds the report with latexmk
|
||||||
|
NotProgramming/MOM runnable builds the report with latexmk
|
||||||
|
NotProgramming/SDM runnable builds the report with latexmk
|
||||||
|
NotProgramming/SDM2 runnable builds the report with latexmk
|
||||||
|
NotProgramming/SPD runnable builds the report with latexmk
|
||||||
|
NotProgramming/STUP runnable npm install && npm start
|
||||||
|
Programming/AIS runnable builds the report with latexmk
|
||||||
|
Programming/BD2 runnable npm install && npm start
|
||||||
|
Programming/BSS runnable builds the report with latexmk
|
||||||
|
Programming/EADS runnable compiles each standalone .cpp
|
||||||
|
Programming/EARIN runnable python3 the entry script
|
||||||
|
Programming/ECOAR runnable make
|
||||||
|
Programming/ECOTE runnable python3 /home/kuhy/WUT_Computer_Science/Programming/ECOTE/program/translator/main.py
|
||||||
|
Programming/ECRYPT no-code test1.py is a 0-byte stub; this course produced no submitted code
|
||||||
|
Programming/ECRYPT_PROJECT runnable python3 /home/kuhy/WUT_Computer_Science/Programming/ECRYPT_PROJECT/code
|
||||||
|
Programming/EGUI runnable dotnet build
|
||||||
|
Programming/EOOP runnable compiles each standalone .cpp
|
||||||
|
Programming/EOPSY runnable make
|
||||||
|
Programming/EPFU runnable make
|
||||||
|
Programming/E-PSYOPS runnable opens in the Unity editor
|
||||||
|
Programming/ERSMS-project runnable docker compose up
|
||||||
|
Programming/NLP runnable python3 the entry script
|
||||||
|
Programming/PBAD runnable jupyter nbconvert --execute
|
||||||
|
Programming/PORR runnable python3 /home/kuhy/WUT_Computer_Science/Programming/PORR/code
|
||||||
|
Programming/PSD runnable starts the Kafka/Flink stack (installs packages with sudo)
|
||||||
|
Programming/psd_project runnable mvn package
|
||||||
|
Programming/TRAK runnable python3 the entry script
|
||||||
|
Programming/twm_4 runnable jupyter nbconvert --execute
|
||||||
|
Programming/USD no-code README describes a MetaDrive RL assignment; no implementation was submitted
|
||||||
|
Programming/WDWR runnable python3 the entry script
|
||||||
|
Programming/ZPOB runnable builds the report with latexmk
|
||||||
|
41
run.sh
41
run.sh
@ -84,39 +84,56 @@ probe_one() {
|
|||||||
cmd_status() {
|
cmd_status() {
|
||||||
local env_label="${CI:+ci}"
|
local env_label="${CI:+ci}"
|
||||||
env_label="${env_label:-local}"
|
env_label="${env_label:-local}"
|
||||||
|
local store="${SCRIPT_DIR}/gates/runnability-${env_label}.tsv"
|
||||||
log "probing course directories (${env_label})"
|
log "probing course directories (${env_label})"
|
||||||
|
|
||||||
local tmp
|
|
||||||
tmp="$(mktemp)"
|
|
||||||
trap 'rm -f "${tmp:-}"' RETURN
|
|
||||||
|
|
||||||
local dir rel line
|
local dir rel line
|
||||||
|
: > "$store"
|
||||||
while IFS= read -r dir; do
|
while IFS= read -r dir; do
|
||||||
rel="${dir#"${SCRIPT_DIR}"/}"
|
rel="${dir#"${SCRIPT_DIR}"/}"
|
||||||
line="$(probe_one "$dir")"
|
line="$(probe_one "$dir")"
|
||||||
printf '%s\t%s\n' "$rel" "$line" >> "$tmp"
|
printf '%s\t%s\n' "$rel" "$line" >> "$store"
|
||||||
done < <(course_dirs)
|
done < <(course_dirs)
|
||||||
|
|
||||||
write_runnability_doc "$tmp" "$env_label"
|
# Each environment writes only its OWN file, then the doc is rendered from
|
||||||
|
# both. Writing a single shared column would mean a CI run silently
|
||||||
|
# overwrote the local results with its own -- and the whole point of
|
||||||
|
# recording per environment is that "runnable here, blocked on a runner"
|
||||||
|
# is the normal case rather than drift.
|
||||||
|
write_runnability_doc
|
||||||
log "wrote ${RUNNABILITY_DOC##*/}"
|
log "wrote ${RUNNABILITY_DOC##*/}"
|
||||||
awk -F'\t' '{ n[$2]++ } END { for (k in n) printf " %-10s %d\n", k, n[k] }' "$tmp"
|
awk -F'\t' '{ n[$2]++ } END { for (k in n) printf " %-10s %d\n", k, n[k] }' "$store"
|
||||||
}
|
}
|
||||||
|
|
||||||
write_runnability_doc() {
|
write_runnability_doc() {
|
||||||
local data="$1" env_label="$2"
|
local local_tsv="${SCRIPT_DIR}/gates/runnability-local.tsv"
|
||||||
|
local ci_tsv="${SCRIPT_DIR}/gates/runnability-ci.tsv"
|
||||||
|
[[ -f "$local_tsv" ]] || : > "$local_tsv"
|
||||||
|
[[ -f "$ci_tsv" ]] || : > "$ci_tsv"
|
||||||
|
|
||||||
{
|
{
|
||||||
cat <<'MD'
|
cat <<'MD'
|
||||||
# Runnability
|
# Runnability
|
||||||
|
|
||||||
Generated by `./run.sh status`. Do not edit by hand.
|
Generated by `./run.sh status`. Do not edit by hand.
|
||||||
|
|
||||||
Status is recorded PER ENVIRONMENT. A directory that is `runnable` locally and
|
Status is recorded PER ENVIRONMENT, from `gates/runnability-local.tsv` and
|
||||||
|
`gates/runnability-ci.tsv`. A directory that is `runnable` locally and
|
||||||
`blocked` in CI is the normal case, not drift: the runner has no MATLAB, no
|
`blocked` in CI is the normal case, not drift: the runner has no MATLAB, no
|
||||||
Unity and no .NET SDK. CI compares only its own column.
|
Unity and no .NET SDK. Each environment rewrites only its own file, so a CI
|
||||||
|
run cannot clobber the local column.
|
||||||
|
|
||||||
|
`-` means that environment has not probed yet.
|
||||||
|
|
||||||
MD
|
MD
|
||||||
printf '| Course | %s | Detail |\n|---|---|---|\n' "$env_label"
|
printf '| Course | local | ci | Detail (local) |\n|---|---|---|---|\n'
|
||||||
awk -F'\t' '{ printf "| `%s` | %s | %s |\n", $1, $2, $3 }' "$data"
|
# Compare FILENAME rather than using the NR==FNR idiom: with an EMPTY
|
||||||
|
# first file awk never reads it, so NR==FNR stays true for every row
|
||||||
|
# of the second file and the whole table comes out blank.
|
||||||
|
awk -F'\t' -v cifile="$ci_tsv" '
|
||||||
|
FILENAME == cifile { ci[$1] = $2; next }
|
||||||
|
{ printf "| `%s` | %s | %s | %s |\n", $1, $2, ($1 in ci ? ci[$1] : "-"), $3 }
|
||||||
|
' "$ci_tsv" "$local_tsv"
|
||||||
} > "$RUNNABILITY_DOC"
|
} > "$RUNNABILITY_DOC"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
42
scripts/check_ignore_consistency.sh
Executable file
42
scripts/check_ignore_consistency.sh
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Fail if any TRACKED file is also matched by a .gitignore rule.
|
||||||
|
#
|
||||||
|
# That combination fails silently: `git add` on such a file is not an error,
|
||||||
|
# the edit simply never lands. This repo had 130 of them -- dist/ swallowing
|
||||||
|
# the vendored jQuery bundle, and the LaTeX template's man-page patterns
|
||||||
|
# (*.[1-9]) eating EPFU's date-named doc/21.11/ directory along with its
|
||||||
|
# report.pdf.
|
||||||
|
#
|
||||||
|
# They were fixed by hand once. This is the gate that keeps them fixed, so
|
||||||
|
# that .binary-allowlist can stop *instructing* the reader to re-run a command
|
||||||
|
# and just have it enforced instead.
|
||||||
|
#
|
||||||
|
# Usage: scripts/check_ignore_consistency.sh
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local offenders
|
||||||
|
offenders="$(git ls-files | git check-ignore --stdin --no-index 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [[ -z "$offenders" ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Tracked files that .gitignore also matches:" >&2
|
||||||
|
printf '%s\n' "$offenders" | sed 's/^/ /' >&2
|
||||||
|
cat >&2 <<'MSG'
|
||||||
|
|
||||||
|
Each of these fails SILENTLY on `git add` -- not an error, the edit just
|
||||||
|
never lands. Fix by either:
|
||||||
|
1. adding a "!" override in .gitignore (if the file belongs in the repo), or
|
||||||
|
2. `git rm --cached` it (if it is build output that should never have been
|
||||||
|
tracked; --cached keeps it on disk).
|
||||||
|
MSG
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@ -140,11 +140,19 @@ _run() {
|
|||||||
[[ -n "$tex" ]] || _no_code "no .tex found"
|
[[ -n "$tex" ]] || _no_code "no .tex found"
|
||||||
local tool
|
local tool
|
||||||
tool="$(_require_any 'a LaTeX toolchain' latexmk pdflatex xelatex)"
|
tool="$(_require_any 'a LaTeX toolchain' latexmk pdflatex xelatex)"
|
||||||
|
# Build into build/, never beside the source. A submitted report.pdf
|
||||||
|
# is a tracked deliverable, and a rebuild whose output name happens
|
||||||
|
# to match it would silently overwrite what was handed in.
|
||||||
|
local dir base
|
||||||
|
dir="$(dirname "$tex")"
|
||||||
|
base="$(basename "$tex")"
|
||||||
if [[ $tool == latexmk ]]; then
|
if [[ $tool == latexmk ]]; then
|
||||||
( cd "$(dirname "$tex")" && latexmk -pdf -interaction=nonstopmode "$(basename "$tex")" )
|
( cd "$dir" && latexmk -pdf -interaction=nonstopmode -outdir=build "$base" )
|
||||||
else
|
else
|
||||||
( cd "$(dirname "$tex")" && "$tool" -interaction=nonstopmode "$(basename "$tex")" )
|
( cd "$dir" && mkdir -p build \
|
||||||
|
&& "$tool" -interaction=nonstopmode -output-directory=build "$base" )
|
||||||
fi
|
fi
|
||||||
|
printf 'output in %s/build\n' "$dir"
|
||||||
;;
|
;;
|
||||||
python)
|
python)
|
||||||
local entry="${COURSE_ENTRY:-}"
|
local entry="${COURSE_ENTRY:-}"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user