Skip to content

Revived the Windows workflows, which had reached no runner since 2025 - #174

Merged
fdesbiens merged 6 commits into
eclipse-threadx:devfrom
fdesbiens:ci/modernized-windows-workflows
Aug 27, 2026
Merged

Revived the Windows workflows, which had reached no runner since 2025#174
fdesbiens merged 6 commits into
eclipse-threadx:devfrom
fdesbiens:ci/modernized-windows-workflows

Conversation

@fdesbiens

@fdesbiens fdesbiens commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

The problem

The four GUIX Studio workflows requested runs-on: windows-2019, an image GitHub retired on 2025-06-30. Nothing can match a retired label, so every run queued for the full 24 hours and was then cancelled without ever starting a job:

run 28477318708  created   2026-06-30T21:33:40Z
                 cancelled 2026-07-01T21:33:41Z     <- exactly +24h, never executed

Every run of these workflows since 2025-09-29 has that same created-plus-24h-cancelled shape. The Studio demo, demo compile, view and MSIX package workflows have gated nothing for about a year. A manual workflow_dispatch on 2026-08-25 queued the same way.

Three more defects sat behind that one, so fixing the image alone would not have produced a green run — and once the workflows reached a runner they immediately surfaced two more that had been accumulating unseen.

Verified result

Every change here was confirmed on a real windows-2022 runner before this PR was opened, not reasoned about:

Workflow Result Tests Time
GUIX Studio Demo Test ✅ success 227 / 227 184 s
GUIX Studio Demo Compile Test ✅ success 212 / 212 143 s
GUIX Studio View Test ⚠️ runs fully 1097 pass / 32 fail ~80 min

Runners are assigned in seconds now, against 24 hours of queueing before.

What is fixed

1. Runner image and action pinning

windows-2019 to windows-2022, pinned rather than windows-latest on the same reasoning eclipse-threadx/threadx applies to ubuntu-24.04: which image the build ran on should be a reviewable commit, not something that changes underneath it.

Every action reference is now a 40-character commit SHA with the version in a trailing comment, following the pattern threadx adopted in #660. Versions moved with the pinning:

Action Was Now
actions/checkout v4 (unpinned) v7.0.1
actions/upload-artifact v3.1.3 v7.0.1
EnricoMi/publish-unit-test-result-action v2 v2.24.0

upload-artifact@v3.1.3 mattered on its own: GitHub began auto-failing every request that used v3 on 2025-01-30, and both upload steps run under if: success() || failure(), so every run would have ended red even with the tests passing.

Compatibility was checked against each new action.yml rather than assumed, for every input these workflows actually pass — checkout keeps submodules; upload-artifact keeps name and path, and the one upload per run means the v4 rule against uploading a name twice does not bite; the publish action keeps check_name and files, and the composite variant still exists at v2.24.0, which is the one a Windows runner needs. All three tags were confirmed to resolve to the SHAs pinned here, and all three are the current latest.

2. Visual Studio discovery

The scripts hard-coded a VS edition path. build_guix.cmd, test_studio_demo.cmd, test_studio_demo_compile.cmd and test_studio_view.cmd all called VS 2022 Enterprise, which no developer machine has; build_guix_studio.cmd called VS 2022 Community, which no GitHub runner has. So the demo test's build step would have failed on its first line.

All five now locate the installation with vswhere — matching what build_guix_studio_msix_package.cmd already did — and check the result instead of assuming the call succeeded. Verified against a Community install, where the Enterprise path does not exist.

Also removed the dead Program Files/Python36 PATH lines. No supported runner image has shipped that Python for years, python is already on PATH there, and the lines embedded literal quote characters into PATH.

3. IMAGE_INFO collided with the Windows SDK

With the workflows reaching a runner again, the Studio build failed immediately:

guix_studio/system_pngs.h(15,8):                          error C2011: 'IMAGE_INFO': 'struct' type redefinition
Windows Kits/10/Include/10.0.26100.0/um/Filter.h(340,16): error C2011: 'IMAGE_INFO': 'struct' type redefinition

plus eight C2027 errors following from it. GUIX Studio declared its own two-field IMAGE_INFO in the global namespace; a newer Windows SDK added a struct of the same name to um/Filter.h, which arrives through the Windows headers the MFC sources already include. SDK 10.0.22621.0 does not define it; 10.0.26100.0 does.

This was latent, not new, and the reason it hid is worth recording: studiox.vcxproj sets <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>, the MSBuild wildcard for "newest installed SDK". So which SDK compiles the Studio depends entirely on the machine — a box whose newest is 22621 builds, the runner image carrying 26100 does not. Any developer who installed a current SDK would have hit this.

Renamed the Studio type to STUDIO_IMAGE_INFO, 13 references across five files. It is private to the Studio, so nothing outside guix_studio sees the name.

Also dropped the -winsdk=10.0.22621.0 argument build_guix_studio.cmd passed to VsDevCmd. It never had the effect it looks like it has — the wildcard in the project file governs the SDK the compile actually uses, so the argument only set the shell environment while MSBuild picked the newest SDK anyway. Keeping it would suggest the build is pinned to an SDK when it is not.

4. Two stale paths from a February 2025 search-and-replace

522aafcc ("Updated scripts for VS Community 2022") moved three paths in test_demo/test_main.py from vs_2019 to vs_2022. Two were right: guix_studio/build/vs_2019 really had been renamed. The third was collateral damage — ports/win32/build/vs_2019 was never renamed, and still holds the only guix.vcxproj and guix.sln in the repository. So --build_guix has raised this for eighteen months, before compiling a single library configuration:

Exception: guix.sln not found. path=../../../ports/win32/build/vs_2022/guix.vcxproj

The same commit then made the opposite error: it never touched test_view/ at all, where three references still named the old Studio directory (test_main.py, test_utils.py, test_string_import_export.py). That suite could not locate the Studio to launch it:

MSBUILD : error MSB1009: Project file does not exist.
Switch: ../../../guix_studio/build/vs_2019/studiox.sln
Exception: Unable to locate Studio executable.

Both fixed. Verified by building the library locally — guix.vcxproj is Win32-only, still on PlatformToolset v142, and produces Debug/gx.lib.

5. Dependabot

A SHA pin with nothing moving it is worse than a floating tag: it holds CI on whatever was current the day it was written. This repository is the case study — nothing had ever reported that an action moved, so upload-artifact sat four majors behind on a version GitHub auto-fails.

.github/dependabot.yml follows the configuration threadx added in #662, with three differences specific to this repository and documented in the file: only three distinct actions are in use; there is no .github/CODEOWNERS here for reviewer routing; and the dependencies label does not exist yet, so Dependabot creates it on the first pull request.

target-branch: dev, so this arms on merge without firing — nothing happens until a release merge carries the file to master. That also opts out of Dependabot security updates, which only run against the default branch; for this ecosystem an action advisory arrives as an ordinary weekly bump, but it is a real trade and stated in the file rather than left to be rediscovered.

Trigger branches — scoped to evidence, not applied uniformly

The demo and demo compile workflows now also run on dev. They previously fired on master only, so they gated no pull request that anybody opened — the same defect threadx fixed in #652. Switched on only after both suites were verified green on a runner.

The other three are deliberately left alone, each for its own reason:

  • regression_test.yml does reach a runner, and is red. Its last real run (2026-06-30) was 5 failures out of 732: guix_all_widgets_accordion_menu, guix_ml_text_view_32bpp, guix_all_widgets_16bpp_canvas_animation (SEGFAULT), guix_animation_complete, guix_animation_complete_push_stack. Adding dev here would make every pull request red on a suite broken since June. It needs fixing first, and that is separate work.
  • studio_view_test.yml can find the Studio again and now runs its full GUI suite on a hosted runner — a useful discovery in itself — but it reports 32 failures out of 1129, spread across about nineteen sub-suites. Enabling gating on that is the wall of red this PR exists to avoid.
  • studio_msix_package.yml is workflow_dispatch only by design. It packages a release rather than testing a change, so there is nothing to gate. Its upload path was corrected from build/vs_2019/... to build/vs_2022/..., where build_guix_studio_msix_package.cmd actually builds; that artifact was always empty.

Scope note

This began as "bump a runner label" and became six commits. That is a consequence of the defect rather than scope creep: a year with no CI let three real bugs accumulate silently, and each had to be fixed before the next became visible. The two suites that now pass are the evidence that the sequence terminates.

Not fixed here, and worth tracking separately: the 5 regression-suite failures, the 32 view-test failures, and the absence of a CODEOWNERS file.

fdesbiens and others added 6 commits August 26, 2026 15:58
The four GUIX Studio workflows requested `runs-on: windows-2019`, an
image GitHub retired on 2025-06-30. Nothing can match a retired label,
so every run queued for the full 24 hours and was then cancelled without
ever starting a job:

    run 28477318708  created   2026-06-30T21:33:40Z
                     cancelled 2026-07-01T21:33:41Z

Every run of these workflows since 2025-09-29 has that same
created-plus-24h-cancelled shape. The Studio demo, demo compile, view and
MSIX package tests have gated nothing for about a year, and a manual
workflow_dispatch on 2026-08-25 queued the same way.

Three more defects were in the path behind that one, so fixing the image
alone would not have produced a green run.

  - actions/upload-artifact was pinned at v3.1.3 in all four workflows.
    GitHub began auto-failing every request that used v3 on 2025-01-30,
    and both upload steps run under `if: success() || failure()`, so
    every run would have ended red even with the tests passing.

  - The scripts hard-coded a Visual Studio edition path. build_guix.cmd,
    test_studio_demo.cmd, test_studio_demo_compile.cmd and
    test_studio_view.cmd all call VS 2022 *Enterprise*, which no
    developer machine has, and build_guix_studio.cmd calls VS 2022
    *Community*, which no GitHub runner has. So the demo test's build
    step would have failed on the first line. All five now locate the
    installation with vswhere, matching what
    build_guix_studio_msix_package.cmd already did, and check the result
    instead of assuming the call succeeded. Verified on a Community
    install, where the Enterprise path does not exist.

  - studio_msix_package.yml uploaded
    guix_studio/build/vs_2019/msix_package_project/AppPackages. That
    directory has not existed since the solution moved to vs_2022, which
    is where build_guix_studio_msix_package.cmd builds, so the artifact
    was always empty.

Every action reference is now a 40-character commit SHA with the version
in a trailing comment, following the pattern eclipse-threadx/threadx
adopted in August 2026. A tag can be repointed at any commit; a SHA
cannot, which is what makes "which code ran in our CI" answerable from
the repository. Versions moved with the pinning:

    actions/checkout                            v4      -> v7.0.1
    actions/upload-artifact                     v3.1.3  -> v7.0.1
    EnricoMi/publish-unit-test-result-action     v2      -> v2.24.0

Compatibility was checked against each new action.yml rather than
assumed, for every input these workflows actually pass: checkout keeps
`submodules`; upload-artifact keeps `name` and `path`, and the one
upload per run means the v4 rule against uploading a name twice does not
bite; the publish action keeps `check_name` and `files`, and the
`composite` variant still exists at v2.24.0, which is the one a Windows
runner needs. All three tags were confirmed to resolve to the SHAs
pinned here, and all three are the current latest.

The runner image is pinned rather than tracking windows-latest, on the
same reasoning threadx applies to ubuntu-24.04: which image the build
ran on should be a reviewable commit, not something that changes
underneath it. Floating would have hidden this failure differently
rather than preventing it.

Also removed the dead `C:\Program Files\Python36` PATH lines. No
supported runner image has shipped that Python for years, python is
already on PATH there, and the lines embedded literal quote characters
into PATH.

The trigger branches are deliberately left alone in this commit. These
workflows fire on master only, so they still gate no pull request to dev
-- the same defect threadx fixed in its own suites. That wants a
dispatch run to go green first, on evidence rather than hope, and is a
separate change.

Assisted-by: Claude Code (Opus 5)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follow-up to the pinning in the preceding commit.

A SHA pin with nothing moving it is worse than a floating tag: it holds
CI on whatever was current the day it was written. This repository is the
case study for that. Nothing had ever reported that an action moved, so
actions/upload-artifact sat at v3.1.3 in all four Windows workflows --
four majors behind, and a version GitHub began auto-failing every request
for on 2025-01-30 -- while actions/checkout sat on an unpinned @v4, three
majors behind.

This adds .github/dependabot.yml: weekly, github-actions only, and closes
the reference to that path which the pinning comment in each workflow now
makes. Dependabot understands the SHA form and rewrites the trailing
version comment together with the pin, so the comment cannot drift away
from the SHA it describes.

It follows the configuration eclipse-threadx/threadx added in August
2026, with three differences that are specific to this repository and
documented in the file:

  - Only three distinct actions are in use, so the default limit of five
    would be enough. Ten is set anyway, to match the sibling repositories
    and to leave room for a wave of majors after a long gap.
  - There is no .github/CODEOWNERS here, so no reviewer routing exists
    for Dependabot to honour. Worth adding, but not by this file.
  - The "dependencies" label does not exist in this repository yet.
    Dependabot creates it on the first pull request.

Two choices worth stating rather than leaving to be rediscovered.

target-branch is dev. Dependabot reads this file from the default
branch, which is master -- but master is deliberately kept behind dev,
and pull requests belong on dev. So this arms on merge without firing:
nothing happens until a release merge carries the file to master.
Setting target-branch also opts out of Dependabot security updates,
which only ever run against the default branch. For this ecosystem the
cost is small, since an action advisory arrives as an ordinary bump on
the weekly run, but it is a real trade.

Patch and minor are grouped into a single pull request, because a queue
reviewed one item at a time is a queue that gets ignored -- which is the
failure mode this file exists to prevent. Majors stay ungrouped, one
pull request each, because every breaking change met in an action here
has been a major: upload-artifact v4 stopped allowing an artifact name to
be uploaded twice in a run, and v6 requires a runner of 2.327.1 or newer.

Dependabot reports drift, not silence. The Windows workflows rotted
because they never reached a runner, not because nobody was told, and
the runner image fix in the preceding commit is the cure for that half.
The cross-repository reusable workflow in regression_test.yml is
correctly left alone: it references a branch, so it carries no version to
move.

Assisted-by: Claude Code (Opus 5)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
With the Windows workflows reaching a runner again, the Studio build
failed immediately on both of them:

    guix_studio\system_pngs.h(15,8): error C2011:
        'IMAGE_INFO': 'struct' type redefinition
    Windows Kits\10\Include\10.0.26100.0\um\Filter.h(340,16): error C2011:
        'IMAGE_INFO': 'struct' type redefinition

plus eight C2027 "use of undefined type" errors following from it.

guix_studio declared its own two-field `IMAGE_INFO` in the global
namespace. A newer Windows SDK added a struct of the same name to
um/Filter.h, which arrives through the Windows headers the MFC sources
already include. SDK 10.0.22621.0 does not define it; 10.0.26100.0 does.

This was latent rather than new. studiox.vcxproj sets
`<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>`, the
MSBuild wildcard for "newest installed SDK", so which SDK compiles the
Studio depends entirely on the machine. A developer box with 22621 as its
newest builds; the runner image, which carries 26100, does not. The
collision was simply waiting for whichever came first.

Renamed the Studio type to STUDIO_IMAGE_INFO -- 13 references across five
files. It is private to the Studio, so nothing outside guix_studio sees
the name.

Also dropped the `-winsdk=10.0.22621.0` argument that
build_guix_studio.cmd passed to VsDevCmd. It never had the effect it
looks like it has: the wildcard in the project file governs the SDK the
compile actually uses, so the argument only set the shell environment and
left MSBuild to pick the newest SDK anyway. Keeping it would suggest the
build is pinned to an SDK when it is not. With the collision fixed there
is nothing to pin against.

Verified by rebuilding the Studio against SDK 10.0.22621.0 locally; the
runner will exercise 10.0.26100.0.

Assisted-by: Claude Code (Opus 5)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The demo compile test could not build the GUIX library at all:

    Exception: guix.sln not found.
        path=../../../ports/win32/build/vs_2022/guix.vcxproj

522aafc ("Updated scripts for VS Community 2022", February 2025) moved
three paths in test_main.py from vs_2019 to vs_2022. Two of them were
right: guix_studio/build/vs_2019 really had been renamed to vs_2022. The
third was collateral damage from the same search and replace --
ports/win32/build/vs_2019 was never renamed, and still holds the only
guix.vcxproj and guix.sln in the repository.

So --build_guix has raised this exception for eighteen months, before
compiling a single library configuration. Nothing said so, because the
workflow that calls it never reached a runner.

Restored the vs_2019 path. Verified by building the library locally:
guix.vcxproj is Win32-only and still on PlatformToolset v142, and it
produces Debug/gx.lib.

Assisted-by: Claude Code (Opus 5)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Studio view test could not start the Studio at all:

    MSBUILD : error MSB1009: Project file does not exist.
    Switch: ../../../guix_studio/build/vs_2019/studiox.sln
    Exception: Unable to locate Studio executable.

522aafc ("Updated scripts for VS Community 2022", February 2025) renamed
guix_studio/build/vs_2019 to vs_2022 and updated test_demo/test_main.py
for it, but never touched the test_view directory. Three references there
still named the old directory:

  - test_view/test_main.py           project_sln_path
  - test_view/test_utils.py          studio_exe_path
  - test_view/test_string_import_export.py  studio_release

So this suite has been unable to locate the Studio for eighteen months.
Like the guix.vcxproj path in the preceding commit, nothing reported it,
because the workflow that runs it never reached a runner.

The remaining build/vs_2019 references in the tree belong to
ports/win32/build/vs_2019, which is a real directory and is left alone.

This commit makes the suite able to find and launch the Studio. Whether
it then passes on a hosted runner is a separate question -- it drives the
Studio through win32 window handles, and no run has got far enough to
say. Its trigger branches are deliberately not changed here for that
reason.

Assisted-by: Claude Code (Opus 5)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The demo and demo compile workflows trigger on master only, for both push
and pull_request. dev is the integration branch, so these suites have
gated no pull request that anybody opened -- the same defect
eclipse-threadx/threadx fixed in its own regression suites in August 2026.

Switched on only after both suites were verified green on a runner, on
this branch, rather than on the assumption that they would be:

    GUIX Studio Demo Test          227 of 227 generation tests   147 s
    GUIX Studio Demo Compile Test  212 of 212 compile tests      146 s

The other three workflows are deliberately left on their current
triggers, and each for its own reason:

  - regression_test.yml does reach a runner, and is red. Its last real
    run, 2026-06-30, was 5 failures out of 732: accordion menu,
    ml_text_view_32bpp, animation_complete, animation_complete_push_stack
    and one more. Adding dev here would make every pull request red on a
    suite that has been broken since June. It needs fixing first, and
    that is not this change.

  - studio_view_test.yml can now find the Studio again, but no run has
    got far enough to say whether GUI automation through win32 window
    handles survives a hosted runner. Enabling gating on an unknown is
    what this commit is written to avoid.

  - studio_msix_package.yml is workflow_dispatch only by design. It
    packages a release rather than testing a change, so there is nothing
    to gate.

Assisted-by: Claude Code (Opus 5)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@fdesbiens
fdesbiens merged commit d049c7f into eclipse-threadx:dev Aug 27, 2026
3 checks passed
fdesbiens added a commit that referenced this pull request Aug 27, 2026
compare_file() locates the line where comparison should start, so that the
banner GUIX Studio writes into every generated file -- which carries a revision
string and a generation timestamp -- is skipped rather than compared. It looked
that line up correctly in the first file and then looked it up in the first file
again for the second:

    for line in list_2:
        if compare_start_string in line:
            start_row_2 = list_1.index(line)

So the golden was sliced at the *generated* file's offset. While both files
happened to reach "#include" on the same line the mistake was invisible, which
is why it survived since the tests were added in #84.

The offsets diverged when 6ba13db added a ten-line MIT licence header to all
111 golden .c and .h files. GUIX Studio does not emit that header, so every
golden now reaches its first #include ten lines later than the file it is
compared against. The golden was therefore sliced ten lines early and compared
banner text against source.

That made every one of the 107 .c and .h comparisons in the suite fail -- all 29
reported test failures -- while the .csv, .xliff and .xml comparisons passed.
Those use skip_line instead of compare_start_string and never reach this code,
which is exactly the split the failure log shows.

The reported mismatch is the same in all 29: a generated "#include" line against
a golden banner comment. Confirmed arithmetically -- in every case the golden
line reported sits exactly ten lines before that golden's own first #include:

    generic_16bpp_resources.c        reported idx 13, #include at 23, delta 10
    generic_16bpp_resources.h        reported idx 16, #include at 26, delta 10
    generic_16bpp_specifications.c   reported idx 14, #include at 24, delta 10
    generic_16bpp_specifications.h   reported idx 16, #include at 26, delta 10

compare_output_file() is the only caller that passes compare_start_string, so
the change cannot affect the xliff, xml or plain-file comparisons.

Verified by running the suite locally against a Studio built from this tree.
Seven suites that fail in CI now pass with no mismatches at all, each gaining
exactly the tests it had been failing:

                              CI (broken)   local (fixed)
    Font                       9 / 1         10 / 0
    Multi-Themes              18 / 1         19 / 0
    Project Import            10 / 2         12 / 0
    Trigger Edit               6 / 1          7 / 0
    Trigger Target Rename      1 / 1          2 / 0
    Bidi Text                  3 / 1          4 / 0
    Widget Name                3 / 1          4 / 0

Project Import compares a generated specifications file, so this also shows that
the screen flow prototype block added by #173 does not disturb these goldens:
that block is only emitted for projects that use Screen Flow, and these do not.

No golden file is regenerated. The goldens still carry "GUIX Studio Revision
6.1.12.0" and a 2022 timestamp in their banners, and still name Azure RTOS
rather than Eclipse ThreadX, but the banner is what the comparison is supposed
to skip -- so none of that needs to be touched to make the suite correct.

This workflow had never actually executed before 2026-08-27. Every earlier run
was cancelled after queueing 24 hours for the retired windows-2019 image, or
sat awaiting approval on a fork pull request, including the run for the v6.5.1
release itself. #174 gave it a runner again; this is the first result it has
ever produced, and the defect it found is in the test harness rather than in
GUIX or in Studio.

Note that studio_view_test.yml triggers only on pull requests targeting master,
so this change is not exercised by its own pull request into dev. It is
validated by the release pull request that carries dev to master.

Assisted-by: Claude Code (Opus 5)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@fdesbiens
fdesbiens deleted the ci/modernized-windows-workflows branch August 28, 2026 02:13
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.

1 participant