Skip to content

feat: release server before macos build#1075

Merged
Nikhil (shadowfax92) merged 4 commits into
mainfrom
fix/0530-0911-duck
May 30, 2026
Merged

feat: release server before macos build#1075
Nikhil (shadowfax92) merged 4 commits into
mainfrom
fix/0530-0911-duck

Conversation

@shadowfax92
Copy link
Copy Markdown
Contributor

Summary

  • Bump @browseros/server to 0.0.97.
  • Make the server release workflow reusable and run the full production build/upload path to Cloudflare R2.
  • Gate nightly macOS packaging on a successful server release so R2 latest is refreshed first.

Design

The nightly workflow resolves the target ref and server package version, calls the reusable server release workflow before packaging, and only starts the macOS build after that upload succeeds. Manual branch builds must disable server release rather than publishing non-default-branch artifacts to global R2 latest.

Test plan

  • ruby YAML parse for nightly-macos-build.yml and release-server.yml
  • actionlint for both changed workflows, ignoring the existing custom self-hosted runner label warning
  • bun run --filter @browseros/server typecheck
  • bun --env-file=apps/server/.env.development test apps/server/tests/build.test.ts
  • bun run lint (exits 0; existing unrelated warnings remain)

@shadowfax92
Copy link
Copy Markdown
Contributor Author

Claude (@claude) review

@shadowfax92
Copy link
Copy Markdown
Contributor Author

Greptile (@greptileai) review

@claude
Copy link
Copy Markdown

claude Bot commented May 30, 2026

Claude finished Nikhil (@shadowfax92)'s task in 2m 0s —— View job


Code Review

  • Gather context
  • Read changed files
  • Analyze and post review feedback

Overall this is a well-structured refactor. The resolve_inputs job cleanly centralises all conditional logic before any expensive work starts, the gate on non-default-branch server releases is clear and correctly enforced, and the always() + explicit result checks in build correctly handle skipped vs failed dependencies. A few items worth addressing:


Medium — No timeout on release_server job

.github/workflows/nightly-macos-build.yml lines 114-126

The build job has timeout-minutes: 600, but the new release_server job has no timeout. If the server build or R2 upload hangs the whole nightly pipeline stalls indefinitely. Consider adding a reasonable cap (e.g. timeout-minutes: 30).

Fix this →


Low — release_server defaults to true for manual dispatch

.github/workflows/nightly-macos-build.yml lines 26-29

release_server:
  description: Build and upload server artifacts before packaging
  type: boolean
  default: true

A developer dispatching manually from a feature branch will hit the resolve_inputs error unless they remember to uncheck release_server. The error message is clear, but the blast radius is: the whole workflow fails immediately. Consider defaulting to false so the common "manual test build on a branch" case just works, and only the scheduled nightly opts in automatically (the schedule path already hardcodes release_server="true").


Low — Silent skip vs explicit failure in release-server.yml

.github/workflows/release-server.yml line 23

if: github.ref == 'refs/heads/main'

When this workflow is triggered directly via workflow_dispatch from a non-main branch, the job is silently skipped rather than failing with a clear error. The workflow run shows green but nothing actually happened. A fail-fast step or an exit 1 guard would make this more obvious:

- name: Guard non-main release
  if: github.ref != 'refs/heads/main'
  run: |
    echo "::error::Server release is only allowed on main (got ${{ github.ref }})"
    exit 1

Nit — Python inline script for version reading

.github/workflows/nightly-macos-build.yml lines 98-105

The inline Python heredoc works fine, but jq (available on ubuntu-latest) or node -p would be shorter and remove the minor risk of Python not being on the PATH:

server_version=$(jq -r '.version' packages/browseros-agent/apps/server/package.json)
echo "server_version=$server_version" >> "$GITHUB_OUTPUT"

Informational — Thin race window between resolve_inputs checkout and release-server.yml checkout

resolve_inputs reads the server version from its own checkout at target_ref. release-server.yml does a separate fresh checkout at github.sha (the event's SHA). In the normal nightly schedule path both land on the same commit, so no issue. The validate-version step inside release-server.yml (line 47-59) acts as the correct integrity check and will catch any divergence, so this is handled — just noting it for awareness.


Summary: No blocking issues. The timeout gap on release_server is the most actionable item. Everything else is polish. The core design — gating macOS packaging on a successful server upload, with a hardcoded guard against publishing from non-default branches — is correct and well-implemented.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

✅ Tests passed — 1059/1064

Suite Passed Failed Skipped
agent 91/91 0 0
build 10/10 0 0
eval 95/95 0 0
server-agent 246/246 0 0
server-api 64/64 0 0
server-browser 4/4 0 0
server-integration 9/10 0 1
server-lib 252/253 0 1
server-root 59/62 0 3
server-tools 229/229 0 0

View workflow run

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 30, 2026

Greptile Summary

This PR makes the server release workflow reusable (workflow_call), gates the nightly macOS packaging job on a successful server upload to R2, and bumps @browseros/server to 0.0.97. Input resolution is extracted into a dedicated resolve_inputs job that validates branch constraints, reads the server version from package.json, and propagates all resolved values to downstream jobs.

  • nightly-macos-build.yml: adds resolve_inputs (ubuntu-latest) and release_server (reusable call) jobs; build now depends on both and only proceeds when the server release either succeeded or was intentionally disabled.
  • release-server.yml: adds workflow_call trigger with a version input; replaces build:server:ci with build:server, explicitly injecting R2 credentials and config env vars that were previously baked into the CI script.
  • apps/server/package.json: version bump 0.0.96 → 0.0.97.

Confidence Score: 4/5

Safe to merge for repos whose default branch is named main; the hardcoded branch check in release-server.yml warrants a minor follow-up.

The job-dependency and condition logic is correctly wired: scheduled runs always release the server first, dispatch builds can opt out, and the macOS build is blocked when the server release fails. The one inconsistency is that release-server.yml hardcodes refs/heads/main while the nightly workflow dynamically reads DEFAULT_BRANCH — if those ever diverge, the server release job would silently return success without actually uploading, and the macOS build would proceed with stale R2 artifacts.

.github/workflows/release-server.yml — the if: github.ref == refs/heads/main on the release job is worth hardening to match the dynamic branch logic in the caller.

Important Files Changed

Filename Overview
.github/workflows/nightly-macos-build.yml Adds resolve_inputs and release_server jobs; refactors build inputs to use outputs from the new resolve_inputs job; gates macOS build on server release success. Logic for schedule vs dispatch events, branch guards, and job-dependency conditions is correctly wired.
.github/workflows/release-server.yml Adds workflow_call trigger with version input; upgrades build step from build:server:ci to build:server with explicit env vars for R2 and config URLs. The job-level if condition hardcodes refs/heads/main, which is inconsistent with the caller's dynamic DEFAULT_BRANCH handling.
packages/browseros-agent/apps/server/package.json Version bump from 0.0.96 to 0.0.97; no other changes.

Sequence Diagram

sequenceDiagram
    participant Trigger as Trigger (schedule / dispatch)
    participant RI as resolve_inputs
    participant AM as authorize_manual_dispatch
    participant RS as release_server (workflow_call)
    participant B as build (macOS)
    participant R2 as Cloudflare R2

    Trigger->>RI: start (ubuntu-latest)
    Trigger->>AM: start (macOS, dispatch only)
    RI->>RI: resolve target_ref, bump_mode, release_server
    RI->>RI: git checkout target_ref
    RI->>RI: read server version from package.json

    alt "release_server == true AND target_ref == DEFAULT_BRANCH"
        RI-->>RS: outputs (server_version)
        AM-->>RS: result (schedule: skipped, dispatch: success)
        RS->>RS: validate version matches package.json
        RS->>RS: "bun run build:server (NODE_ENV=production)"
        RS->>R2: upload server artifacts
        RS->>RS: create GitHub release + tag
        RS-->>B: "result == success"
    else "release_server == false"
        RI-->>B: "result == success (release_server skipped)"
    end

    RI-->>B: outputs (target_ref, bump_mode, commit_version, upload_to_r2)
    AM-->>B: result
    B->>B: sync repo to target_ref
    B->>B: bump version
    B->>B: build BrowserOS (macOS arm64)
    B->>R2: "upload DMG (if upload_to_r2 == true)"
Loading

Comments Outside Diff (1)

  1. .github/workflows/release-server.yml, line 23 (link)

    P2 Hardcoded branch name inconsistent with caller's dynamic check

    The release job guards on github.ref == 'refs/heads/main', but when invoked via the new workflow_call path, github.ref is the ref of the calling workflow. The nightly workflow validates the target ref dynamically against github.event.repository.default_branch. If the default branch is ever renamed, resolve_inputs would allow release_server=true through (since target_ref == DEFAULT_BRANCH would still be satisfied), but the release job here would silently skip — returning success — causing the macOS build to proceed with potentially stale R2 artifacts and no actual server release having occurred.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: .github/workflows/release-server.yml
    Line: 23
    
    Comment:
    **Hardcoded branch name inconsistent with caller's dynamic check**
    
    The `release` job guards on `github.ref == 'refs/heads/main'`, but when invoked via the new `workflow_call` path, `github.ref` is the ref of the *calling* workflow. The nightly workflow validates the target ref dynamically against `github.event.repository.default_branch`. If the default branch is ever renamed, `resolve_inputs` would allow `release_server=true` through (since `target_ref == DEFAULT_BRANCH` would still be satisfied), but the `release` job here would silently skip — returning `success` — causing the macOS build to proceed with potentially stale R2 artifacts and no actual server release having occurred.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
.github/workflows/release-server.yml:23
**Hardcoded branch name inconsistent with caller's dynamic check**

The `release` job guards on `github.ref == 'refs/heads/main'`, but when invoked via the new `workflow_call` path, `github.ref` is the ref of the *calling* workflow. The nightly workflow validates the target ref dynamically against `github.event.repository.default_branch`. If the default branch is ever renamed, `resolve_inputs` would allow `release_server=true` through (since `target_ref == DEFAULT_BRANCH` would still be satisfied), but the `release` job here would silently skip — returning `success` — causing the macOS build to proceed with potentially stale R2 artifacts and no actual server release having occurred.

Reviews (1): Last reviewed commit: "feat: release server before macos build" | Re-trigger Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 30, 2026

Greptile Summary

This PR gates the nightly macOS build on a successful server release by extracting a reusable release-server.yml workflow and inserting a new resolve_inputs + release_server job phase into the nightly pipeline. It also bumps @browseros/server to 0.0.97 and moves the R2 upload into the server build step.

  • nightly-macos-build.yml: A new resolve_inputs job centralises all parameter resolution (target ref, version, flags) and enforces that server release is only permitted when building the default branch. The release_server job is inserted after authorisation and before the macOS build job; the build job's if condition gates on release_server.result == 'success' when the flag is active.
  • release-server.yml: A workflow_call trigger is added alongside workflow_dispatch, and the build step is upgraded from build:server:ci to build:server with R2 credentials and production env vars injected directly in the step.
  • package.json / bun.lock: Routine 0.0.96 → 0.0.97 version bump.

Confidence Score: 3/5

The workflow orchestration logic is generally correct, but two failure scenarios could silently break the automated nightly before anyone notices.

The new release_server job now runs through environment: release-core on every scheduled nightly, which could block automation if that environment has required reviewers. Separately, if BROWSEROS_NIGHTLY_REF is ever pointed at a non-default branch, the hardcoded release_server=true for schedule events will cause resolve_inputs to exit 1 on every nightly run with no override path. Both issues affect the core nightly automation path.

.github/workflows/nightly-macos-build.yml (scheduled-run guard logic) and .github/workflows/release-server.yml (environment protection interaction)

Important Files Changed

Filename Overview
.github/workflows/nightly-macos-build.yml Refactored to add a resolve_inputs job that centralises input resolution, reads the server package version, and gates server release to default-branch only; new release_server reusable-workflow call is inserted between authorisation and the main macOS build.
.github/workflows/release-server.yml Added workflow_call trigger to make the workflow reusable; replaced build:server:ci with build:server and injected all R2/env vars inline so the full production upload path runs in CI.
packages/browseros-agent/apps/server/package.json Version bump from 0.0.96 to 0.0.97; no other changes.
packages/browseros-agent/bun.lock Lock file updated to reflect the 0.0.97 version bump; no dependency changes.

Sequence Diagram

sequenceDiagram
    participant Scheduler as GitHub Scheduler / Dispatch
    participant RI as resolve_inputs<br/>(ubuntu-latest)
    participant AMD as authorize_manual_dispatch<br/>(macOS self-hosted)
    participant RS as release_server<br/>(reusable: release-server.yml)
    participant Build as build<br/>(macOS self-hosted)

    Scheduler->>RI: trigger (schedule or workflow_dispatch)
    RI->>RI: resolve target_ref, bump_mode, release_server, upload_to_r2
    RI->>RI: "guard: release_server=true only on DEFAULT_BRANCH"
    RI->>RI: checkout target_ref
    RI->>RI: read server package.json → server_version

    alt workflow_dispatch
        Scheduler->>AMD: trigger (environment: release-core)
        AMD-->>Build: authorize
    end

    alt "release_server == 'true'"
        RI-->>RS: pass server_version
        RS->>RS: validate version vs package.json
        RS->>RS: bun run build:server (+ R2 upload)
        RS->>RS: verify artifacts
        RS->>RS: generate release notes
        RS->>RS: create GitHub release / tag
        RS-->>Build: success gate
    end

    Build->>Build: sync repo to target_ref
    Build->>Build: bump version
    Build->>Build: build BrowserOS (macOS arm64)
    Build->>Build: upload DMG artifact
Loading

Comments Outside Diff (1)

  1. .github/workflows/release-server.yml, line 22-27 (link)

    P1 environment: release-core on a job now called from the automated nightly

    The release job uses environment: release-core. Before this PR, the workflow was only triggered via workflow_dispatch (a human action), so any required-reviewer protection on that environment made sense. Now it is also called from the scheduled nightly via workflow_call. If release-core has required reviewers configured, every scheduled run will pause waiting for manual approval, effectively breaking the nightly automation. It is worth verifying that the environment's deployment protection rules either have no required reviewers, or explicitly allow automated (schedule-triggered) runs to bypass the review gate.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: .github/workflows/release-server.yml
    Line: 22-27
    
    Comment:
    **`environment: release-core` on a job now called from the automated nightly**
    
    The `release` job uses `environment: release-core`. Before this PR, the workflow was only triggered via `workflow_dispatch` (a human action), so any required-reviewer protection on that environment made sense. Now it is also called from the scheduled nightly via `workflow_call`. If `release-core` has required reviewers configured, every scheduled run will pause waiting for manual approval, effectively breaking the nightly automation. It is worth verifying that the environment's deployment protection rules either have no required reviewers, or explicitly allow automated (schedule-triggered) runs to bypass the review gate.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
.github/workflows/nightly-macos-build.yml:63-80
**Scheduled run hard-blocked if `BROWSEROS_NIGHTLY_REF` targets a non-default branch**

For `schedule` events, `release_server` is unconditionally hardcoded to `"true"` (line 68) with no way to override it. If `BROWSEROS_NIGHTLY_REF` is ever set to a branch other than `DEFAULT_BRANCH` (e.g., for a release-candidate or hotfix cycle), the `resolve_inputs` guard at line 77 will always exit 1, silently killing every nightly macOS build until the variable is cleared. There is no escape hatch — `release_server` cannot be disabled for scheduled runs the way it can for `workflow_dispatch`.

### Issue 2 of 2
.github/workflows/release-server.yml:22-27
**`environment: release-core` on a job now called from the automated nightly**

The `release` job uses `environment: release-core`. Before this PR, the workflow was only triggered via `workflow_dispatch` (a human action), so any required-reviewer protection on that environment made sense. Now it is also called from the scheduled nightly via `workflow_call`. If `release-core` has required reviewers configured, every scheduled run will pause waiting for manual approval, effectively breaking the nightly automation. It is worth verifying that the environment's deployment protection rules either have no required reviewers, or explicitly allow automated (schedule-triggered) runs to bypass the review gate.

Reviews (2): Last reviewed commit: "feat: release server before macos build" | Re-trigger Greptile

Comment thread .github/workflows/nightly-macos-build.yml
@shadowfax92 Nikhil (shadowfax92) merged commit 146d317 into main May 30, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant