From 60a55928687b461d539446224df1107e31029680 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 22 Mar 2026 08:08:45 +0000 Subject: [PATCH 1/5] Initial commit with task details Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: https://github.com/linksplatform/Numbers/issues/135 --- .gitkeep | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitkeep diff --git a/.gitkeep b/.gitkeep new file mode 100644 index 0000000..034a8dc --- /dev/null +++ b/.gitkeep @@ -0,0 +1 @@ +# .gitkeep file auto-generated at 2026-03-22T08:08:45.323Z for PR creation at branch issue-135-b2802964181f for issue https://github.com/linksplatform/Numbers/issues/135 \ No newline at end of file From 80e4a76a2af1eb3e1b0a3123af33967d27de1db4 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 22 Mar 2026 08:10:49 +0000 Subject: [PATCH 2/5] fix: remove unused std::process::exit import from get-bump-type.rs The `use std::process::exit;` import on line 30 of scripts/get-bump-type.rs was never used. With `RUSTFLAGS: -Dwarnings` set in CI, unused imports are promoted to compile errors, causing the Auto Release job to fail when rust-script attempted to compile and run the script. Root cause: dead import left behind after a prior refactor of the script. Fix: remove the single unused `use` statement. Also adds case study documentation in docs/case-studies/issue-135/ with full timeline, root cause analysis, CI log evidence, and notes on the Node.js 20 deprecation warnings present in the same run. Closes #135 Co-Authored-By: Claude Sonnet 4.6 --- docs/case-studies/issue-135/README.md | 122 ++++++++++++++++++++++++++ scripts/get-bump-type.rs | 1 - 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 docs/case-studies/issue-135/README.md diff --git a/docs/case-studies/issue-135/README.md b/docs/case-studies/issue-135/README.md new file mode 100644 index 0000000..00fb3ea --- /dev/null +++ b/docs/case-studies/issue-135/README.md @@ -0,0 +1,122 @@ +# Case Study: Issue #135 — CI/CD Auto Release Failure + +## Overview + +- **Issue:** [#135](https://github.com/linksplatform/Numbers/issues/135) +- **Failing Run:** [23398717024](https://github.com/linksplatform/Numbers/actions/runs/23398717024) +- **Date:** 2026-03-22 +- **Job:** Auto Release → "Determine bump type from changelog fragments" +- **Status:** Root cause identified and fixed. + +--- + +## Timeline / Sequence of Events + +1. Commit `bde6c03` was pushed to `main` (merge of PR #134). +2. The Rust CI/CD Pipeline was triggered. +3. All jobs passed except **Auto Release**. +4. The "Determine bump type from changelog fragments" step ran `rust-script scripts/get-bump-type.rs`. +5. The Rust compiler emitted a fatal error due to `RUSTFLAGS: -Dwarnings` treating unused imports as errors. +6. `rust-script` exited with code 1, failing the step and the entire Auto Release job. + +--- + +## Root Cause Analysis + +### Primary Root Cause + +In `scripts/get-bump-type.rs`, line 30 contained: + +```rust +use std::process::exit; +``` + +This import is **never used** anywhere in the file. All other scripts that import `exit` do call it; only `get-bump-type.rs` does not. + +### Why It Became a Fatal Error + +The CI workflow (`rust.yml`, line 48) sets: + +```yaml +env: + RUSTFLAGS: -Dwarnings +``` + +The `-Dwarnings` flag promotes all Rust compiler warnings to errors. The `unused-imports` lint (normally a warning) became a compile error, preventing `rust-script` from building and running the script. + +### Why Other Scripts Were Not Affected + +All other scripts that declare `use std::process::exit;` actually call `exit()`: + +| Script | Uses `exit()`? | +|--------|----------------| +| `bump-version.rs` | Yes (5 calls) | +| `check-file-size.rs` | Yes (2 calls) | +| `check-release-needed.rs` | Yes (3 calls) | +| `collect-changelog.rs` | Yes (3 calls) | +| `create-changelog-fragment.rs` | Yes (3 calls) | +| `get-version.rs` | Yes (2 calls) | +| **`get-bump-type.rs`** | **No — dead import** | + +### Why the Import Was Present + +The `get-bump-type.rs` script was likely refactored at some point to use Rust's `std::process::exit()` for error handling, then changed to use `return` or `eprintln!` patterns instead, leaving the `use` statement behind without removing it. + +--- + +## Impact + +- Auto Release job blocked on every push to `main`. +- Automated versioning and crate publishing could not proceed. +- No production code or tests were affected — only the release automation script. + +--- + +## Fix + +Remove the unused import from `scripts/get-bump-type.rs`: + +```diff +-use std::process::exit; + use regex::Regex; +``` + +This is a one-line change. No functional behavior is altered. + +--- + +## CI Log Evidence + +From `ci-logs/run-23398717024-failed.log`: + +``` +error: unused import: `std::process::exit` + --> /home/runner/work/Numbers/Numbers/scripts/get-bump-type.rs:30:5 + | +30 | use std::process::exit; + | ^^^^^^^^^^^^^^^^^^ + | + = note: `-D unused-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(unused_imports)]` + +error: could not compile `get-bump-type_412c20687aa3a320be6ee72f` due to 1 previous error +error: Could not execute cargo +``` + +--- + +## Additional Notes + +### Node.js 20 Deprecation Warnings + +The CI run also contained annotations about Node.js 20 actions being deprecated +(`actions/checkout@v4`, `actions/cache@v4`, `codecov/codecov-action@v4`). +These are warnings only and do not cause failures yet. GitHub will force Node.js 24 +by default starting **June 2nd, 2026**. These should be addressed before that date. +Updating to the latest versions of those actions should resolve the warnings. + +### Possible Future Improvement + +Consider adding a lint step that runs `rust-script --check` or simply compiles +all scripts in CI to catch such issues earlier (before the Auto Release stage). +Alternatively, scripts could be wrapped in a Cargo workspace for better lint coverage. diff --git a/scripts/get-bump-type.rs b/scripts/get-bump-type.rs index 3f3abed..9089cf0 100644 --- a/scripts/get-bump-type.rs +++ b/scripts/get-bump-type.rs @@ -27,7 +27,6 @@ use std::env; use std::fs; use std::io::Write; use std::path::Path; -use std::process::exit; use regex::Regex; fn get_arg(name: &str) -> Option { From eb35925264d6b9efa3b39b53c5aa19ba062b295c Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 22 Mar 2026 08:11:25 +0000 Subject: [PATCH 3/5] Revert "Initial commit with task details" This reverts commit 60a55928687b461d539446224df1107e31029680. --- .gitkeep | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitkeep diff --git a/.gitkeep b/.gitkeep deleted file mode 100644 index 034a8dc..0000000 --- a/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# .gitkeep file auto-generated at 2026-03-22T08:08:45.323Z for PR creation at branch issue-135-b2802964181f for issue https://github.com/linksplatform/Numbers/issues/135 \ No newline at end of file From 287f074684ed6d292105b622b9ea5ee361bf3135 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 22 Mar 2026 08:15:40 +0000 Subject: [PATCH 4/5] fix: add changelog fragment for unused import removal Adds required changelog.d fragment for the fix that removed the unused `std::process::exit` import from scripts/get-bump-type.rs. Co-Authored-By: Claude Sonnet 4.6 --- .../20260322_000000_fix_unused_import_get_bump_type.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog.d/20260322_000000_fix_unused_import_get_bump_type.md diff --git a/changelog.d/20260322_000000_fix_unused_import_get_bump_type.md b/changelog.d/20260322_000000_fix_unused_import_get_bump_type.md new file mode 100644 index 0000000..7c59811 --- /dev/null +++ b/changelog.d/20260322_000000_fix_unused_import_get_bump_type.md @@ -0,0 +1,7 @@ +--- +bump: patch +--- + +### Fixed + +- Removed unused `std::process::exit` import from `scripts/get-bump-type.rs` that caused a compiler warning From 766073a7212a9edf23cfa98db7637548bed19545 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 22 Mar 2026 09:11:08 +0000 Subject: [PATCH 5/5] fix: replace nuget.exe with dotnet nuget CLI in C# workflow The pushNuGetPackageToGitHubPackageRegistry job failed because nuget.exe requires Mono, which is not installed on Ubuntu 24.04 runners. This has been broken since at least July 2025 (run 16390287640). Changes: - Replace nuget CLI with dotnet nuget commands (no Mono needed) - Remove nuget/setup-nuget@v1 dependency - Update actions/checkout from v1/v3 to v4 - Update tj-actions/changed-files from v21 to v46 - Replace deprecated ::set-output with $GITHUB_OUTPUT - Update case study with C# CI failure analysis Co-Authored-By: Claude Opus 4.6 --- .github/workflows/csharp.yml | 27 +++--- docs/case-studies/issue-135/README.md | 129 ++++++++++++++++---------- 2 files changed, 95 insertions(+), 61 deletions(-) diff --git a/.github/workflows/csharp.yml b/.github/workflows/csharp.yml index 19ce60a..b4308be 100644 --- a/.github/workflows/csharp.yml +++ b/.github/workflows/csharp.yml @@ -2,7 +2,7 @@ name: csharp on: push: - branches: main + branches: main paths: - 'csharp/**' - '.github/workflows/csharp.yml' @@ -10,7 +10,7 @@ env: NUGETTOKEN: ${{ secrets.NUGET_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SCRIPTS_BASE_URL: https://raw.githubusercontent.com/linksplatform/Scripts/main/MultiProjectRepository - + defaults: run: working-directory: csharp @@ -19,7 +19,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: Test @@ -29,21 +29,20 @@ jobs: needs: test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - - uses: nuget/setup-nuget@v1 - name: Publish NuGet package to GitHub Package Registry run: | dotnet build -c Release dotnet pack -c Release - nuget source Add -Name "GitHub" -Source "https://nuget.pkg.github.com/linksplatform/index.json" -UserName linksplatform -Password ${{ secrets.GITHUB_TOKEN }} - nuget push **/*.nupkg -Source "GitHub" -SkipDuplicate + dotnet nuget add source "https://nuget.pkg.github.com/linksplatform/index.json" --name "GitHub" --username linksplatform --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text + dotnet nuget push ./**/*.nupkg --source "GitHub" --skip-duplicate pusnToNuget: runs-on: ubuntu-latest needs: test steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: Read project information @@ -60,7 +59,7 @@ jobs: runs-on: ubuntu-latest needs: test steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: Read project information @@ -82,12 +81,12 @@ jobs: outputs: isCsFilesChanged: ${{ steps.setIsCsFilesChangedOutput.outputs.isCsFilesChanged }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Get changed files using defaults id: changed-files - uses: tj-actions/changed-files@v21 + uses: tj-actions/changed-files@v46 - name: Set output isCsFilesChanged id: setIsCsFilesChangedOutput run: | @@ -100,14 +99,14 @@ jobs: isCsFilesChanged='true' fi done - echo "::set-output name=isCsFilesChanged::${isCsFilesChanged}" + echo "isCsFilesChanged=${isCsFilesChanged}" >> "$GITHUB_OUTPUT" echo "isCsFilesChanged: ${isCsFilesChanged}" generatePdfWithCode: runs-on: ubuntu-latest needs: [findChangedCsFiles] if: ${{ needs.findChangedCsFiles.outputs.isCsFilesChanged == 'true' }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: Generate PDF with code @@ -122,7 +121,7 @@ jobs: needs: [findChangedCsFiles] if: ${{ needs.findChangedCsFiles.outputs.isCsFilesChanged == 'true' }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: Publish documentation to gh-pages branch diff --git a/docs/case-studies/issue-135/README.md b/docs/case-studies/issue-135/README.md index 00fb3ea..2108f54 100644 --- a/docs/case-studies/issue-135/README.md +++ b/docs/case-studies/issue-135/README.md @@ -1,29 +1,30 @@ -# Case Study: Issue #135 — CI/CD Auto Release Failure +# Case Study: Issue #135 — CI/CD Failures in Rust and C# Pipelines ## Overview - **Issue:** [#135](https://github.com/linksplatform/Numbers/issues/135) -- **Failing Run:** [23398717024](https://github.com/linksplatform/Numbers/actions/runs/23398717024) +- **Failing Runs:** + - Rust: [23398717024](https://github.com/linksplatform/Numbers/actions/runs/23398717024) + - C#: [23398717023](https://github.com/linksplatform/Numbers/actions/runs/23398717023) - **Date:** 2026-03-22 -- **Job:** Auto Release → "Determine bump type from changelog fragments" -- **Status:** Root cause identified and fixed. +- **Status:** Root causes identified and fixed. --- ## Timeline / Sequence of Events 1. Commit `bde6c03` was pushed to `main` (merge of PR #134). -2. The Rust CI/CD Pipeline was triggered. -3. All jobs passed except **Auto Release**. -4. The "Determine bump type from changelog fragments" step ran `rust-script scripts/get-bump-type.rs`. -5. The Rust compiler emitted a fatal error due to `RUSTFLAGS: -Dwarnings` treating unused imports as errors. -6. `rust-script` exited with code 1, failing the step and the entire Auto Release job. +2. Both the Rust CI/CD Pipeline and the C# workflow were triggered. +3. **Rust:** All jobs passed except **Auto Release** — the "Determine bump type from changelog fragments" step failed. +4. **C#:** All jobs passed except **pushNuGetPackageToGitHubPackageRegistry** — the `nuget source Add` command failed. --- ## Root Cause Analysis -### Primary Root Cause +### Rust CI Failure: Unused Import in get-bump-type.rs + +**Primary Root Cause:** In `scripts/get-bump-type.rs`, line 30 contained: @@ -33,7 +34,7 @@ use std::process::exit; This import is **never used** anywhere in the file. All other scripts that import `exit` do call it; only `get-bump-type.rs` does not. -### Why It Became a Fatal Error +**Why It Became a Fatal Error:** The CI workflow (`rust.yml`, line 48) sets: @@ -44,50 +45,75 @@ env: The `-Dwarnings` flag promotes all Rust compiler warnings to errors. The `unused-imports` lint (normally a warning) became a compile error, preventing `rust-script` from building and running the script. -### Why Other Scripts Were Not Affected +**Fix:** Remove the unused import from `scripts/get-bump-type.rs`. + +### C# CI Failure: Mono Not Found on Ubuntu 24.04 + +**Primary Root Cause:** + +The `pushNuGetPackageToGitHubPackageRegistry` job used `nuget/setup-nuget@v1` to install `nuget.exe`, then ran: + +```yaml +nuget source Add -Name "GitHub" -Source "https://nuget.pkg.github.com/linksplatform/index.json" ... +nuget push **/*.nupkg -Source "GitHub" -SkipDuplicate +``` + +On Linux, `nuget.exe` is a .NET Framework executable that requires **Mono** to run. Ubuntu 24.04 GitHub-hosted runners **do not have Mono pre-installed**, resulting in: + +``` +/opt/hostedtoolcache/nuget.exe/7.3.0/x64/nuget: 2: mono: not found +##[error]Process completed with exit code 127. +``` -All other scripts that declare `use std::process::exit;` actually call `exit()`: +**How Long This Has Been Broken:** -| Script | Uses `exit()`? | -|--------|----------------| -| `bump-version.rs` | Yes (5 calls) | -| `check-file-size.rs` | Yes (2 calls) | -| `check-release-needed.rs` | Yes (3 calls) | -| `collect-changelog.rs` | Yes (3 calls) | -| `create-changelog-fragment.rs` | Yes (3 calls) | -| `get-version.rs` | Yes (2 calls) | -| **`get-bump-type.rs`** | **No — dead import** | +This same failure occurred in CI run [16390287640](https://github.com/linksplatform/Numbers/actions/runs/16390287640) on **2025-07-19**, confirming the issue has persisted for at least **8 months**. -### Why the Import Was Present +**Fix:** Replace `nuget.exe` CLI commands with `dotnet nuget` commands, which are part of the .NET SDK already installed on the runner: + +```yaml +# Before (requires Mono): +- uses: nuget/setup-nuget@v1 +- run: | + nuget source Add -Name "GitHub" -Source "..." -UserName ... -Password ... + nuget push **/*.nupkg -Source "GitHub" -SkipDuplicate + +# After (uses dotnet SDK directly): +- run: | + dotnet nuget add source "..." --name "GitHub" --username ... --password ... --store-password-in-clear-text + dotnet nuget push ./**/*.nupkg --source "GitHub" --skip-duplicate +``` -The `get-bump-type.rs` script was likely refactored at some point to use Rust's `std::process::exit()` for error handling, then changed to use `return` or `eprintln!` patterns instead, leaving the `use` statement behind without removing it. +### Additional Issues Fixed in C# Workflow + +| Issue | Before | After | Why | +|-------|--------|-------|-----| +| Outdated checkout action | `actions/checkout@v1` | `actions/checkout@v4` | v1 is 5+ years old, missing security fixes and features | +| Outdated changed-files action | `tj-actions/changed-files@v21` | `tj-actions/changed-files@v46` | v21 is outdated, potential security/compatibility issues | +| Deprecated set-output syntax | `::set-output name=...::` | `>> "$GITHUB_OUTPUT"` | set-output was deprecated in Oct 2022, will be removed | +| Node.js 20 deprecation | `nuget/setup-nuget@v1` | Removed (not needed) | Node.js 20 actions deprecated, forced to Node.js 24 from June 2026 | --- ## Impact +### Rust - Auto Release job blocked on every push to `main`. - Automated versioning and crate publishing could not proceed. - No production code or tests were affected — only the release automation script. ---- - -## Fix - -Remove the unused import from `scripts/get-bump-type.rs`: - -```diff --use std::process::exit; - use regex::Regex; -``` - -This is a one-line change. No functional behavior is altered. +### C# +- GitHub Package Registry publishing has been broken since at least July 2025. +- NuGet.org publishing (`pusnToNuget` job) was **not affected** — it uses `dotnet nuget push` and continued to work. +- The failure did not block other C# CI jobs (test, release, NuGet.org publish all succeeded). --- ## CI Log Evidence -From `ci-logs/run-23398717024-failed.log`: +### Rust (run 23398717024) + +From `ci-logs/rust-23398717024.log`: ``` error: unused import: `std::process::exit` @@ -97,26 +123,35 @@ error: unused import: `std::process::exit` | ^^^^^^^^^^^^^^^^^^ | = note: `-D unused-imports` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(unused_imports)]` error: could not compile `get-bump-type_412c20687aa3a320be6ee72f` due to 1 previous error error: Could not execute cargo ``` +### C# (run 23398717023) + +From `ci-logs/csharp-23398717023.log`: + +``` +Successfully created package '/home/runner/work/Numbers/Numbers/csharp/Platform.Numbers/bin/Release/Platform.Numbers.0.9.0.nupkg'. +Successfully created package '/home/runner/work/Numbers/Numbers/csharp/Platform.Numbers/bin/Release/Platform.Numbers.0.9.0.snupkg'. +/opt/hostedtoolcache/nuget.exe/7.3.0/x64/nuget: 2: mono: not found +##[error]Process completed with exit code 127. +``` + --- ## Additional Notes ### Node.js 20 Deprecation Warnings -The CI run also contained annotations about Node.js 20 actions being deprecated -(`actions/checkout@v4`, `actions/cache@v4`, `codecov/codecov-action@v4`). -These are warnings only and do not cause failures yet. GitHub will force Node.js 24 -by default starting **June 2nd, 2026**. These should be addressed before that date. -Updating to the latest versions of those actions should resolve the warnings. +Both workflows contained annotations about Node.js 20 actions being deprecated. +GitHub will force Node.js 24 by default starting **June 2nd, 2026**. +The C# workflow fix addresses this by removing the `nuget/setup-nuget@v1` dependency +and updating all actions to their latest versions. -### Possible Future Improvement +### Possible Future Improvements -Consider adding a lint step that runs `rust-script --check` or simply compiles -all scripts in CI to catch such issues earlier (before the Auto Release stage). -Alternatively, scripts could be wrapped in a Cargo workspace for better lint coverage. +1. **Rust:** Consider adding a lint step that compiles all scripts to catch import issues earlier. +2. **C#:** Consider adding a PR-triggered CI check (currently C# workflow only runs on push to main). +3. **C#:** The `pusnToNuget` and `publiseRelease` job names contain typos — consider renaming for clarity in a future PR.