Skip to content

refactor(ci): Global refactoring of pipeline workflows while addressi…#40

Merged
EtienneLescot merged 7 commits into
getopenscreen:mainfrom
psychosomat:refactor-ci
Jun 28, 2026
Merged

refactor(ci): Global refactoring of pipeline workflows while addressi…#40
EtienneLescot merged 7 commits into
getopenscreen:mainfrom
psychosomat:refactor-ci

Conversation

@psychosomat

@psychosomat psychosomat commented Jun 26, 2026

Copy link
Copy Markdown

Summary

Comprehensive refactor of the GitHub Actions workflows: splitting a monolithic god file, eliminating duplication, fixing a cross-platform cache collision, and adding AUR package publishing.

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Motivation

1. The discord.yaml god file

One workflow file contained three entirely unrelated jobs -- PR-to-forum sync, ROADMAP.md-to-Discord pin, and weekly contributor leaderboard -- sharing no secrets, no webhooks, no logic, and only the word "Discord" in common. At 769 lines with over 700 lines of inline JavaScript inside actions/github-script@v7, the file was untestable locally, exempt from Biome linting and tsc type-checking, and a single failure in one job could be misread as affecting the others.

Solution: Split into three independent workflow files, each with its own triggers and permissions. Extracted all inline JavaScript into standalone .mjs scripts under .github/scripts/, invoked via node. The scripts now import @actions/core and @actions/github (added to devDependencies) and are covered by CI lint and type-check.

2. Duplicated Node.js setup across 12 jobs

The actions/setup-node@v4 + npm ci pattern appeared verbatim 12 times across ci.yml (x4), build.yml (x3), diagnostic-artifact.yml (x2), and the three new Discord workflows (x3). Any Node.js version bump required editing every occurrence and hoping none were missed.

Solution: Created a composite action at .github/actions/setup/action.yml. All jobs now use uses: ./.github/actions/setup. The version is defined in one file.

3. Cross-platform caption-assets cache collision

The cache key caption-assets-${{ hashFiles('scripts/fetch-caption-model.mjs') }} was identical across Windows, macOS, and Linux runners. While the Whisper ONNX models and ONNX Runtime WASM files are nominally architecture-independent, @xenova/transformers installs platform-specific npm packages, and the wasm files in node_modules can differ per platform. A cache hit from a different OS would restore incorrect binaries silently.

Solution: Added ${{ runner.os }} to the cache key so each platform gets its own cache slot.

4. Implicit artifact names in publish-release

The publish-release job used a single actions/download-artifact@v4 call with no name parameter, downloading all artifacts into one directory and then running find artifacts -type f | sort. If any upstream job renamed its artifact, the release would silently omit it rather than failing.

Solution: Replaced with four explicit download-artifact calls, each specifying the exact name: matching the corresponding upload-artifact. A rename mismatch now fails loudly before the release is touched.

5. Duplicated native macOS helper build

Both build.yml (release packaging) and diagnostic-artifact.yml (diagnostic bundles) contained identical steps for npm run build:native:mac with OPENSCREEN_MAC_HELPER_ARCHS. Changes to the native build invocation needed to be mirrored in two places.

Solution: Created a reusable workflow build-native-mac.yml with workflow_call trigger, accepting arch as an input. Both workflows call it instead of duplicating the build step.

6. Race condition in Homebrew cask publishing

update-homebrew-cask.yml attempted to download and hash DMGs immediately upon release: published, before Apple notarization completed (which takes up to 15 minutes). The SHA-256 was computed against a DMG that could still be unsigned or mid-notarization.

Solution: Added a polling loop before the asset-finding step that waits up to 12 minutes for both DMG files to appear in the release, retrying every 30 seconds.

7. Missing AUR package

The project already builds .pacman packages via electron-builder --linux pacman in build-linux, and publishes to Homebrew, WinGet, and Nix -- but had no AUR workflow for Arch Linux users.

Solution: Added aur-publish.yml. On release publish, it finds the .pacman asset, computes its SHA-256, updates PKGBUILD and .SRCINFO in the AUR git repository via SSH, and pushes. Conditional on vars.AUR_PACKAGE_NAME and secrets.AUR_SSH_PRIVATE_KEY.

Don't forget to add the secrets.AUR_SSH_PRIVATE_KEY before the next release!

Files changed

File Change
.github/actions/setup/action.yml New: composite action for Node.js setup
.github/workflows/ci.yml Simplified with composite action (10 lines removed)
.github/workflows/build.yml Composite action, explicit download-artifact, cache key fix
.github/workflows/diagnostic-artifact.yml Composite action
.github/workflows/discord.yaml Deleted (split into 3 files)
.github/workflows/discord-pr-notify.yml New: PR-to-Discord forum sync
.github/workflows/discord-roadmap-sync.yml New: ROADMAP.md-to-Discord pin
.github/workflows/discord-weekly-leaderboard.yml New: weekly contributor leaderboard
.github/scripts/discord-pr-sync.mjs New: extracted from actions/github-script inline JS
.github/scripts/discord-roadmap-sync.mjs New: extracted from actions/github-script inline JS
.github/scripts/discord-weekly-leaderboard.mjs New: extracted from actions/github-script inline JS
.github/workflows/update-homebrew-cask.yml Added DMG availability polling
.github/workflows/build-native-mac.yml New: reusable native macOS helper build
.github/workflows/aur-publish.yml New: AUR package publishing
package.json / package-lock.json Added @actions/core and @actions/github as devDependencies
docs/github-actions-workflows.md New: architecture documentation with Mermaid graph

Testing

  • actionlint -- clean on all 13 workflow files
  • biome check -- clean on all 3 new .mjs scripts
  • tsc --noEmit -- clean (scripts are covered by the project tsconfig)

Summary by CodeRabbit

  • New Features
    • Added Discord automation to sync PR activity into forum threads, including pinned roadmap syncing and a weekly contributor leaderboard.
    • Added an automated workflow to publish release assets to AUR.
  • Bug Fixes
    • Improved DMG asset handling by waiting until both expected artifacts are available (up to 12 minutes).
  • Documentation
    • Documented the repository’s GitHub Actions workflow tiers and shared setup.
  • Tests
    • Added test coverage for Discord thread/channel validation and expanded test discovery to include .github/.
  • Chores
    • Standardized CI/build Node setup via a shared composite action and removed the outdated Discord workflow.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR splits Discord automation into separate workflows and scripts, adds a shared Node setup action used by CI and build jobs, updates release and package publication workflows, and expands the workflow documentation.

Changes

GitHub Actions workflow updates

Layer / File(s) Summary
Shared setup and callers
.github/actions/setup/action.yml, package.json, .github/workflows/ci.yml, .github/workflows/build.yml, .github/workflows/diagnostic-artifact.yml, vitest.config.ts
The composite action installs Node 22 with npm caching and npm ci; CI, build, and diagnostic workflows switch to it, package.json adds @actions/core and @actions/github, and Vitest scans .github/ tests.
PR Discord sync
.github/workflows/discord-pr-notify.yml, .github/scripts/discord-pr-sync.mjs, .github/scripts/discord-thread-validator.mjs, .github/scripts/discord-thread-validator.test.mjs
The PR notify workflow runs on pull request, review, and comment events, and the script creates or updates Discord forum threads, validates stored thread markers, and posts PR, review, and comment updates.
Roadmap Discord sync
.github/workflows/discord-roadmap-sync.yml, .github/scripts/discord-roadmap-sync.mjs
The roadmap workflow runs on merged pull requests and main pushes, and the script detects roadmap file changes, reads ROADMAP.md from main, updates the pinned Discord message, and pins it.
Weekly Discord leaderboard
.github/workflows/discord-weekly-leaderboard.yml, .github/scripts/discord-weekly-leaderboard.mjs
The scheduled workflow queries merged pull requests from the last 7 days and posts a Discord leaderboard embed with the top 10 contributors.
Release and registry workflows
.github/workflows/build.yml, .github/workflows/update-homebrew-cask.yml, .github/workflows/aur-publish.yml
The build workflow downloads release artifacts into per-platform directories, the Homebrew workflow waits for both DMG assets before continuing, and the AUR workflow resolves release assets, updates PKGBUILD and .SRCINFO, and pushes the package commit over SSH.
Workflow docs
docs/github-actions-workflows.md
The workflow guide adds tiered workflow descriptions, a dependency graph, shared setup notes, and script-transition notes for the GitHub Actions setup.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • getopenscreen/openscreen#36: Touches .github/workflows/diagnostic-artifact.yml, overlapping the local setup-action migration used here.

Poem

I hopped through caches, bright and keen,
and watched the Discord threads turn green.
Roadmaps pinned, the builds all sang,
AUR carrots clinked and rang.
Hoppy tailwags! 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is related to the workflow refactor, but it is truncated and too vague to clearly summarize the main change. Use a clearer title like "refactor(ci): split Discord workflows and centralize Node setup".
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description covers summary, type of change, motivation, files changed, and testing, so it is mostly complete for the template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (1)
.github/scripts/discord-roadmap-sync.mjs (1)

27-34: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Migrate the Discord pins calls to the new API
GET /channels/{channelId}/pins and PUT /channels/{channelId}/pins/{messageId} are the deprecated endpoints. The new API returns { items, has_more } from GET /channels/{channelId}/messages/pins, so this lookup should read items[].message and the pin call should move under /messages/pins/{messageId}.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/discord-roadmap-sync.mjs around lines 27 - 34, Update the
Discord pin handling in discord-roadmap-sync.mjs to use the new pins API instead
of the deprecated channel pins endpoints. In the logic around the pin lookup and
pinning flow (including the fetch that reads pins and the later pin request),
switch the GET request to /channels/{channelId}/messages/pins, read the returned
items list and inspect each item.message for the roadmap embed title, and move
the pin operation to /channels/{channelId}/messages/pins/{messageId}. Keep the
existing ROADMAP_EMBED_TITLE matching and existingMessageId flow intact while
adapting it to the new response shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/discord-pr-sync.mjs:
- Around line 195-199: The thread ID handling in discord-pr-sync.mjs is trusting
attacker-controlled PR body content from extractThreadId(body), which can
redirect bot actions to arbitrary Discord threads. Update the logic around
shouldCreateThread and the subsequent patchDiscordThread/discordPost flow to
treat any marker from pr.body as untrusted unless it can be validated against
the expected forum/channel via the Discord API or confirmed as previously
written by the bot. Ensure the bot only mutates a thread when the resolved
thread ID is verified to belong to the intended parent channel, and otherwise
ignore the marker and create/use a safe thread path.
- Line 226: The applied_tags list can exceed Discord’s 5-tag limit when
combining the status tag with mapped label tags. Update the appliedTags
construction in discord-pr-sync.mjs to cap the final array at 5 while always
keeping statusTag first when present, and apply the same clamping logic in the
other appliedTags usages in the sync flow so create/patch calls never send too
many tags.

In @.github/scripts/discord-weekly-leaderboard.mjs:
- Around line 19-34: The leaderboard logic in the search/query flow is only
reading the first page of results, so counts and totalMerged are incomplete when
there are more than 100 merged PRs. Update the search handling around
octokit.rest.search.issuesAndPullRequests and the counter/totalMerged
calculation to paginate through all result pages, accumulate every item before
ranking, and compute totalMerged from the full merged set rather than just
search.data.items.

In @.github/workflows/aur-publish.yml:
- Around line 37-44: The AUR secret check only stops the “Check AUR secrets”
step, so the later publish steps still run without a key and fail; add the same
missing-key condition as an if guard on the SSH/clone/push steps in the AUR
publish workflow. Reuse the existing AUR_SSH_PRIVATE_KEY check around the
publish-related steps so they are skipped entirely when the secret is absent,
rather than relying on exit 0 inside the first step.
- Around line 117-121: The AUR publish workflow can commit a stale .SRCINFO
because the fallback in the .SRCINFO generation step only warns when makepkg is
unavailable. Update the aur-publish job so the step using makepkg --printsrcinfo
either installs the needed Arch tooling first or fails the workflow when makepkg
cannot run, and ensure the publish path does not continue with an unchanged
.SRCINFO. Use the existing .SRCINFO generation block in the aur-publish.yml job
to locate and adjust this behavior.
- Around line 86-94: The AUR SSH setup in the workflow currently uses
ssh-keyscan, which trusts a live host response and weakens host verification.
Update the SSH config setup in the workflow to write a pinned aur.archlinux.org
known_hosts entry from a repository secret/variable instead of calling
ssh-keyscan, and keep the existing Host/IdentityFile config for the AUR
connection.

In @.github/workflows/build-native-mac.yml:
- Around line 1-23: The macOS native helper workflow is currently unreachable
because build-native-mac is only defined as a reusable workflow and nothing
calls it. Update the macOS build flow to invoke this workflow from the existing
build jobs that duplicate the native build step, referencing build-native-mac
and the macOS job definitions in build.yml and diagnostic-artifact.yml; if you
do not want to reuse it, remove the unused workflow file instead.

In @.github/workflows/build.yml:
- Around line 310-320: The macOS artifact download steps in publish-release
always fetch both architectures, which breaks single-arch workflow_dispatch
releases when one artifact is missing. Update the download steps for
openscreen-mac-arm64 and openscreen-mac-x64 so they are conditional on the built
architecture or otherwise tolerate absent artifacts, using the existing
publish-release job and actions/download-artifact invocations as the place to
adjust.

In @.github/workflows/update-homebrew-cask.yml:
- Around line 53-55: The readiness check in the release polling logic is too
broad because it counts any two DMG files instead of waiting for the specific
architecture assets. Update the asset check in the workflow step that uses gh
release view, ASSETS, and COUNT so it verifies the expected arm64 and x64 DMG
names emitted by the producer, and only proceeds when both matching assets are
present.

In `@docs/github-actions-workflows.md`:
- Line 5: The workflow inventory count in the overview is inconsistent with the
rest of the document. Update the summary in the github-actions-workflows
overview to match the actual number of workflow files shown in the graph and
section headers, or add the missing workflow entry so the count is accurate. Use
the document’s workflow inventory section and tier headers as the source of
truth when reconciling the total.

---

Nitpick comments:
In @.github/scripts/discord-roadmap-sync.mjs:
- Around line 27-34: Update the Discord pin handling in discord-roadmap-sync.mjs
to use the new pins API instead of the deprecated channel pins endpoints. In the
logic around the pin lookup and pinning flow (including the fetch that reads
pins and the later pin request), switch the GET request to
/channels/{channelId}/messages/pins, read the returned items list and inspect
each item.message for the roadmap embed title, and move the pin operation to
/channels/{channelId}/messages/pins/{messageId}. Keep the existing
ROADMAP_EMBED_TITLE matching and existingMessageId flow intact while adapting it
to the new response shape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: caaf367a-fe73-4ae7-bfc1-e8c0f1f6fa54

📥 Commits

Reviewing files that changed from the base of the PR and between af06dd2 and 80bfc16.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • .github/actions/setup/action.yml
  • .github/scripts/discord-pr-sync.mjs
  • .github/scripts/discord-roadmap-sync.mjs
  • .github/scripts/discord-weekly-leaderboard.mjs
  • .github/workflows/aur-publish.yml
  • .github/workflows/build-native-mac.yml
  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/diagnostic-artifact.yml
  • .github/workflows/discord-pr-notify.yml
  • .github/workflows/discord-roadmap-sync.yml
  • .github/workflows/discord-weekly-leaderboard.yml
  • .github/workflows/discord.yaml
  • .github/workflows/update-homebrew-cask.yml
  • docs/github-actions-workflows.md
  • package.json
💤 Files with no reviewable changes (1)
  • .github/workflows/discord.yaml

Comment thread .github/scripts/discord-pr-sync.mjs
Comment thread .github/scripts/discord-pr-sync.mjs Outdated
Comment thread .github/scripts/discord-weekly-leaderboard.mjs Outdated
Comment thread .github/workflows/aur-publish.yml
Comment thread .github/workflows/aur-publish.yml Outdated
Comment thread .github/workflows/aur-publish.yml Outdated
Comment thread .github/workflows/build-native-mac.yml Outdated
Comment thread .github/workflows/build.yml
Comment thread .github/workflows/update-homebrew-cask.yml Outdated
Comment thread docs/github-actions-workflows.md Outdated
- discord-pr-sync: validate thread channel via Discord API before acting
  on body-extracted threadId to prevent attacker-controlled redirects;
  cap appliedTags at 5 to match Discord forum limit
- discord-weekly-leaderboard: paginate search results via octokit.paginate;
  catch API errors gracefully instead of crashing
- aur-publish: gate all publish steps on key-check output; replace
  ssh-keyscan with pinned known_hosts from repo variable; install
  arch-install-scripts for makepkg on ubuntu-latest
- build.yml: tolerate missing per-arch macOS downloads via
  continue-on-error for single-arch workflow_dispatch
- update-homebrew-cask: match exact DMG asset names in poll instead of
  counting any two .dmg files
- discord-roadmap-sync: migrate from deprecated /pins to /messages/pins
  endpoints with new response shape
- docs: correct workflow count from 13 to 12
- build-native-mac.yml: remove unused reusable workflow (single npm run
  does not justify a separate job with artifact orchestration)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
.github/workflows/build.yml (1)

310-322: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

continue-on-error resolves single-arch dispatch but can silently ship a release missing macOS DMGs.

Adding continue-on-error: true makes the macOS downloads tolerant of absent artifacts, which addresses the prior single-arch workflow_dispatch concern. However, it also suppresses transient download failures on a full tag release: if a macOS artifact build succeeded but the download step fails, the job proceeds and the "Publish release assets" step only aborts when all downloads are empty (Line 336). The net effect is a published release silently missing macOS installers.

Consider scoping the tolerance to the dispatch path (or asserting expected assets are present for tag pushes) so genuine failures on a full release still fail loudly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build.yml around lines 310 - 322, The macOS artifact
download steps in the release workflow are too permissive and can let tag
releases publish without DMGs; update the download logic in the build job so the
tolerance only applies to the single-arch workflow_dispatch path, while
tag/release runs still fail if expected artifacts are missing. Use the existing
download steps for openscreen-mac-arm64 and openscreen-mac-x64 as the place to
gate this behavior, and ensure the downstream release-asset publishing path only
proceeds when the expected macOS artifacts are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/discord-pr-sync.mjs:
- Around line 54-76: Treat PR-body thread markers as untrusted: the current
validateThreadChannel flow still returns true when botToken or forumChannelId is
missing and only verifies parent_id, which can let a forged marker pass. Update
validateThreadChannel in discord-pr-sync.mjs to fail closed unless a bot-owned
lookup can fully verify the thread, and avoid trusting marker-provided thread
data; if thread names are not reliable, use a bot-side lookup path that is
independent of the PR body before suppressing notifications or resolving the
target thread.

In @.github/workflows/aur-publish.yml:
- Around line 115-124: The fallback install step does not ensure makepkg is
actually available before the later makepkg --printsrcinfo call. Update the
Install makepkg step to explicitly install the package that provides makepkg (or
add a command -v makepkg verification) in the fallback path, and keep the
existing logic in the aur publish workflow block that checks
steps.aur_secret.outputs.configured.

---

Duplicate comments:
In @.github/workflows/build.yml:
- Around line 310-322: The macOS artifact download steps in the release workflow
are too permissive and can let tag releases publish without DMGs; update the
download logic in the build job so the tolerance only applies to the single-arch
workflow_dispatch path, while tag/release runs still fail if expected artifacts
are missing. Use the existing download steps for openscreen-mac-arm64 and
openscreen-mac-x64 as the place to gate this behavior, and ensure the downstream
release-asset publishing path only proceeds when the expected macOS artifacts
are present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c0e0feb-8a07-4c5b-a175-88377992dc5e

📥 Commits

Reviewing files that changed from the base of the PR and between 80bfc16 and bd05222.

📒 Files selected for processing (8)
  • .github/scripts/discord-pr-sync.mjs
  • .github/scripts/discord-roadmap-sync.mjs
  • .github/scripts/discord-weekly-leaderboard.mjs
  • .github/workflows/aur-publish.yml
  • .github/workflows/build.yml
  • .github/workflows/discord-pr-notify.yml
  • .github/workflows/update-homebrew-cask.yml
  • docs/github-actions-workflows.md
✅ Files skipped from review due to trivial changes (1)
  • docs/github-actions-workflows.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/update-homebrew-cask.yml
  • .github/workflows/discord-pr-notify.yml
  • .github/scripts/discord-weekly-leaderboard.mjs
  • .github/scripts/discord-roadmap-sync.mjs

Comment thread .github/scripts/discord-pr-sync.mjs Outdated
Comment thread .github/workflows/aur-publish.yml
CodeRabbit identified two remaining weaknesses:
- Validation failed open when DISCORD_BOT_TOKEN was unset (returned
  true, trusting any marker)
- Parent-ID-only check allowed forged markers pointing to any thread
  in the same forum

Changes:
- Fail closed: return false when botToken is missing so markers are
  never trusted without the ability to validate
- Verify thread name matches the bot's deterministic naming convention
  (PR # - *) so only threads the bot itself created for this
  specific PR pass validation
- Forum channel ID check is now optional (thread name alone is a
  sufficient identity when parent cannot be verified)

@EtienneLescot EtienneLescot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the cleanup — splitting the god file, dropping the inline JS into linted .mjs, the runner.os cache-key fix, and the explicit download-artifact name: calls are all real wins. The thread-marker injection is properly closed now: validateThreadChannel fails closed without DISCORD_BOT_TOKEN and requires both parent_id === forumChannelId and channel.name.startsWith("PR #N - "). The only residual (attacker-owned thread in the same forum named PR #N - …) is bounded by who can open PRs and the data is public anyway, so I'm not blocking on it.

Left a few small items inline. This is an automatic review pass; feel free to push back on any of them.

Comment thread .github/scripts/discord-weekly-leaderboard.mjs Outdated
Comment thread docs/github-actions-workflows.md Outdated
Comment thread docs/github-actions-workflows.md Outdated
Comment thread .github/scripts/discord-pr-sync.mjs Outdated
- discord-weekly-leaderboard: replace setFailed with warning for
  non-critical Discord webhook failure; drop unused import
- docs: remove stale build-native-mac.yml node and edges from
  mermaid graph; delete orphaned Tier 2 subsection
- discord-pr-sync: extract validateThreadChannel into standalone
  module (discord-thread-validator.mjs) with dependency injection
  for botToken/forumChannelId so it is independently testable
- test: add unit tests for validateThreadChannel covering:
  fail-closed without token, wrong parent rejection, sibling PR
  name mismatch, valid thread acceptance, API errors, and network
  failures
- vitest.config: add .github/ to test include pattern
@psychosomat

Copy link
Copy Markdown
Author

Im running out of ideas for commit names :d
I agree with all your comments corrected everything.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/scripts/discord-weekly-leaderboard.mjs (2)

66-75: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Catch rejected webhook requests too.

This only downgrades HTTP error responses. A network/TLS/DNS failure still makes fetch(...) reject, which will red-fail the weekly cron even though this flow is supposed to warn and continue on non-critical webhook problems.

Suggested fix
-	const res = await fetch(`${spotlightWebhook}?wait=true`, {
-		method: "POST",
-		headers: { "Content-Type": "application/json" },
-		body: JSON.stringify(payload),
-	});
-
-	if (!res.ok) {
-		const txt = await res.text();
-		warning(`Leaderboard post failed ${res.status}: ${txt}`);
-	}
+	try {
+		const res = await fetch(`${spotlightWebhook}?wait=true`, {
+			method: "POST",
+			headers: { "Content-Type": "application/json" },
+			body: JSON.stringify(payload),
+		});
+
+		if (!res.ok) {
+			const txt = await res.text();
+			warning(`Leaderboard post failed ${res.status}: ${txt}`);
+		}
+	} catch (err) {
+		warning(`Leaderboard post failed: ${err instanceof Error ? err.message : String(err)}`);
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/discord-weekly-leaderboard.mjs around lines 66 - 75, The
webhook send in fetch for the weekly leaderboard only handles non-2xx responses,
so network/TLS/DNS failures still reject and break the cron. Update the request
flow in discord-weekly-leaderboard.mjs around the fetch/payload send to catch
rejected fetch calls as well, log a warning with the error details, and continue
execution instead of letting the job fail.

15-19: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Pass the full ISO timestamp to merged:. substring(0, 10) broadens the search to the whole UTC day, so “Last 7 days” can include extra PRs; GitHub search accepts full merged:>=YYYY-MM-DDTHH:MM:SSZ timestamps.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/discord-weekly-leaderboard.mjs around lines 15 - 19, The
weekly leaderboard search in discord-weekly-leaderboard.mjs is truncating the
`since` value when building `q`, which broadens the `merged:` filter to the
whole day. Update the query construction to pass the full ISO timestamp from
`since` directly into the `merged:>=...` qualifier, keeping the `owner`/`repo`
and `q` logic otherwise unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/discord-thread-validator.mjs:
- Around line 10-13: The Discord thread validation fetch can hang indefinitely
on a stalled network path, so add an abort timeout around the request in
discord-thread-validator.mjs. Update the fetch call inside the try block to use
an AbortController (or equivalent timeout mechanism) and ensure the request is
cancelled after a short limit so the workflow can continue promptly even if
Discord is unresponsive. Keep the change localized to the validation logic that
uses fetch and threadId/botToken.

---

Outside diff comments:
In @.github/scripts/discord-weekly-leaderboard.mjs:
- Around line 66-75: The webhook send in fetch for the weekly leaderboard only
handles non-2xx responses, so network/TLS/DNS failures still reject and break
the cron. Update the request flow in discord-weekly-leaderboard.mjs around the
fetch/payload send to catch rejected fetch calls as well, log a warning with the
error details, and continue execution instead of letting the job fail.
- Around line 15-19: The weekly leaderboard search in
discord-weekly-leaderboard.mjs is truncating the `since` value when building
`q`, which broadens the `merged:` filter to the whole day. Update the query
construction to pass the full ISO timestamp from `since` directly into the
`merged:>=...` qualifier, keeping the `owner`/`repo` and `q` logic otherwise
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 844b8bcb-6584-4653-9f67-db3023ffe262

📥 Commits

Reviewing files that changed from the base of the PR and between 49b4a3c and f11a680.

📒 Files selected for processing (6)
  • .github/scripts/discord-pr-sync.mjs
  • .github/scripts/discord-thread-validator.mjs
  • .github/scripts/discord-thread-validator.test.mjs
  • .github/scripts/discord-weekly-leaderboard.mjs
  • docs/github-actions-workflows.md
  • vitest.config.ts
💤 Files with no reviewable changes (1)
  • docs/github-actions-workflows.md

Comment thread .github/scripts/discord-thread-validator.mjs
Without a timeout, a stalled network path during the best-effort
validation step can hang the job indefinitely. continue-on-error
only helps after the request completes or the job-level timeout
(360 min default) fires. Add a 5-second AbortController abort so
the workflow moves on quickly when Discord is unreachable.

- Fetch call now passes an AbortSignal with 5s timeout
- Test verifies the signal is wired into fetch arguments
arch-install-scripts only provides pacstrap/arch-chroot/genfstab; it does
NOT ship the makepkg binary. If pacman-package-manager failed to install
and arch-install-scripts succeeded, the step exited 0 and the later
makepkg --printsrcinfo call failed downstream with 'command not found'.

- Try makepkg package directly in the fallback chain (the explicit
  provider per packages.ubuntu.com).
- Verify with command -v makepkg after install so a silent failure
  fails the job instead of leaking past the 'Install makepkg' step.

Addresses CodeRabbit comment r3484700062.
@EtienneLescot EtienneLescot merged commit f6b81e7 into getopenscreen:main Jun 28, 2026
12 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.

2 participants