Skip to content

Run the library testing on a pull request (#307) - #324

Merged
adrpo merged 1 commit into
OpenModelica:masterfrom
adrpo:library-testing-for-pull-requests
Aug 24, 2026
Merged

Run the library testing on a pull request (#307)#324
adrpo merged 1 commit into
OpenModelica:masterfrom
adrpo:library-testing-for-pull-requests

Conversation

@adrpo

@adrpo adrpo commented Aug 24, 2026

Copy link
Copy Markdown
Member

Closes #307 (the testing side of it; the reports are pages, not comments - see
the open question at the end).

The library testing runs against a branch and tells us what broke after a
change was merged. This tests a pull request before that, against master.

Building the pull request

git fetch --force https://github.com/OpenModelica/OpenModelica.git refs/pull/<N>/merge
git checkout -f --detach FETCH_HEAD

refs/pull/<N>/merge rather than /head: the question is what happens once it
is merged, not what the branch looks like on its own. It is fetched from GitHub
itself, because refs/pull/* is not on the read-only mirror the job clones, and
checked out detached so that nothing is left behind in the shared workspace for
the next run to trip over. A pull request GitHub cannot merge has no such ref,
and the job says so instead of failing obscurely.

The run fills a pr-<N> table like any other branch, which the shared database
of #295 makes cheap: the claim is (branch, libname), so it cannot collide with
a master run, and the results carry their own omcversion, so nothing else can
reuse them by mistake.

The comparison, which did not exist

all-reports.py reports a branch against its own previous run - what a pull
request must not do - and its query reads one table. pr-report.py takes the
newest run of pr-<N> and the newest run of the baseline branch and compares
them with the same rule and the same thresholds as the nightly reports: the phase
each model reached, and what each phase cost.

./pr-report.py <N>              # --baseline=master by default

Per library it compares the newest run each side has of that library, not the
two run dates: a run does not necessarily hold every library, since one whose
version, compiler and configuration were tested before keeps the results of the
run that produced them.

It writes history/pr-<N>/<baseline run>..<pull request run>.html next to the
nightly reports, and 00_comment.md beside it - the same summary as markdown, to
comment on the pull request with. Both are published with everything else.

Two ways to be wrong, which the report says out loud

  • The machine. Two runs produced on different hardware compare the hardware
    as much as the change. pull_request_node defaults to the node that produces
    the master runs, and the report names the machines of both runs, which Record the machine that produced each library's results #320
    records per library.
  • The libraries. Two runs that tested different library versions, or verified
    against different reference files, differ for reasons of their own; those
    libraries are listed.

The baseline being the newest master run rather than the commit the pull
request is based on is stated in the report itself.

Models that one run has and the other does not are counted and listed rather than
quietly dropped from the comparison: a library that failed to load looks like
nothing at all otherwise.

In Jenkins

parameter
pull_request the number; nothing of this runs when it is empty
pull_request_baseline the branch it is compared against, master
pull_request_config what it tests, configs/conf.json
pull_request_node where it runs, the machine that produces the baseline
drop_stale_pull_request_tables the housekeeping below

A full run takes days, so this is on demand and takes a configuration file:
testing every pull request this way is not the idea. The pull request report is
its own stage - regenerating every overview for a job that tested one thing would
take longer than the report.

Housekeeping

The tables accumulate, roughly 19500 rows each, and unlike a branch a pull
request is tested once and never again. drop-pr-tables.py drops the tables of
pull requests that have been merged or closed, and of those tested more than
--older-than days ago (60 by default), together with the rows their runs left
in omcversion, libversion, history and job_claim. It lists them and does
nothing unless it is given --yes; the reports published for them are not
touched. The same stage removes the per-pull-request omc builds left in
~/saved_omc on the test node.

Tested

pr-report.py against a sqlite database holding a master run and a pr-1234
run built from it:

case
a model that stops verifying reported as a regression, Verify -> Failed
a model that simulates 10x slower reported as a performance regression
identical runs 0 of everything, report and summary still written
a model only the pull request run has listed under "only in pr-1234"
the two runs on different machines caveat naming both
a library at a different version caveat, and the library listed
a database from before #320 (no host column) works, machine is "unknown"
the same report generated twice the index entry is replaced, not repeated
no such table / not a number says so and exits 1

drop-pr-tables.py against the same database, with the tables renamed to a
merged pull request (16357) and an open one tested 100 days ago (15703): both
selected for the right reason, listed without --yes, and dropped with it,
including their rows in the other tables. A pull request that does not exist is
left alone.

The Jenkinsfile changes could not be run from here.

The open question from the issue: both

The report is a page under branches/history/pr-<N>/, and the summary is
posted as a comment on the pull request when --comment is given. It replaces
the comment an earlier run of the same pull request left rather than adding to a
pile - it recognises its own by a marker in the body - and it posts as whoever
the token belongs to: GITHUB_TOKEN or GH_TOKEN in the environment, or the
account gh is logged in as, which is how it can be
run by hand.

In Jenkins it is the pull_request_comment parameter, taking the token from a
github-token credential. The credential is bound where it is used rather than
for the stage, so a job that does not ask for a comment runs whether one is
configured or not.

Verified against a throwaway pull request in a fork,
adrpo/OpenModelicaLibraryTesting#1:
the first run posted the summary, the second updated the same comment rather
than posting a second one, a bad token fails loudly after the report has been
written, and no token at all is not an error - it says where the summary is.


Generated by Claude Code.

The library testing runs against a branch and says what broke after a
change was merged. This tests a pull request before that, and compares it
against master.

The compiler is built from refs/pull/<N>/merge - the pull request as it
would land, not the branch on its own - fetched from GitHub itself, since
refs/pull/* is not on the read-only mirror the job clones. It is checked
out detached, so nothing is left in the shared workspace for the next run
to trip over. The run fills a pr-<N> table like any other branch, which
the shared database of OpenModelica#295 makes cheap: the claim is (branch, libname),
so it cannot collide with a master run, and the results carry their own
omcversion, so nothing else can reuse them by mistake.

What did not exist is the comparison. all-reports.py reports a branch
against its own previous run, which is exactly what a pull request must
not do, and its query reads one table. pr-report.py takes the newest run
of pr-<N> and the newest run of the baseline branch and compares them with
the same rule and the same thresholds: the phase each model reached, and
what each phase cost. Per library it compares the newest run each side has
of it, because a run does not necessarily hold every library - one whose
version, compiler and configuration were tested before keeps the results
of the run that produced them.

It writes the report next to the nightly ones, in
history/pr-<N>/<baseline run>..<pull request run>.html, and a summary to
comment on the pull request with beside it. Two things would make a
difference mean something other than "the pull request did this", and the
report says so when they apply:

  - the machine, since two runs produced on different hardware compare the
    hardware as much as the change. The parameter defaults to the node
    that produces the master runs, and the report names both machines,
    which OpenModelica#320 records per library;
  - the libraries, since two runs that tested different library versions,
    or verified against different reference files, differ for reasons of
    their own.

The models one run has and the other does not are counted and listed
rather than quietly left out of the comparison, since a library that
failed to load looks like nothing at all otherwise.

In Jenkins it is the pull_request parameter, with pull_request_baseline,
pull_request_config and pull_request_node beside it. A full run takes
days, so this is on demand and takes a configuration file: testing every
pull request is not the idea.

The tables accumulate, roughly 19500 rows each, and unlike a branch a
pull request is tested once and never again. drop-pr-tables.py drops the
tables of pull requests that have been merged or closed, and of those
tested more than --older-than days ago, together with the rows their runs
left in the other tables; it lists them and does nothing unless it is
given --yes. The reports published for them are not touched. It is the
drop_stale_pull_request_tables parameter in Jenkins, and the same stage
keeps the per-pull-request omc builds on the test node from piling up.

---
Generated by Claude Code.
@adrpo
adrpo merged commit 86f08e4 into OpenModelica:master Aug 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run the library testing on an OpenModelica pull request, to see the impact before merging

1 participant