Skip to content

ci: build, test and API-break check - #29

Merged
romchornyi merged 7 commits into
masterfrom
ci/build-test-api-check
Oct 23, 2026
Merged

romchornyi merged 7 commits into
masterfrom
ci/build-test-api-check

Conversation

@romchornyi

@romchornyi romchornyi commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Issue being fixed or feature implemented

The only check on this repo was Validate PR title. Nothing compiled the library on a PR, so a change that does not build, fails its tests, or breaks the public API that dashwallet-ios uses could be merged.

What was done?

ci.yml — on every PR and on pushes to master:

  • Build: iOS device + macOS — Release build for devices (generic/platform=iOS), plus swift build on macOS (the documented local build, which also compiles the AppKit branches).
  • Unit tests (iOS Simulator) — the test suite on an iPhone simulator. The runtime is the newest one the selected Xcode can run that has an iPhone (.github/scripts/pick-simulator.sh). It runs on the simulator because the #if canImport(UIKit) files are compiled out on macOS.
  • Lint CI config (actionlint, shellcheck) — actionlint 1.7.12 (the tarball is checked against its sha256) and shellcheck on .github/scripts/*.sh.

api-check.yml — Breaking changes / Public API, iOS floor, tools version fails on a breaking change unless the PR title declares it with a conventional-commit ! (feat!: …, feat(scope)!: …). It compares the PR merge commit with its first parent, the base it was merged onto. It counts:

  • public API changes from swift package diagnose-api-breaking-changes. The package is built for the iOS Simulator, because on the macOS host the UIKit-only public API does not exist and was never compared;
  • a raised iOS deployment target;
  • a raised swift-tools-version.

New DashIcon.* enum cases are not counted, because every icon import adds them. The title is read live from the API, since a re-run reuses the old event payload. A new commit cancels the running check. A body edit (CodeRabbit) queues a new run instead of cancelling, so the required check is never left pending. The logic lives in .github/scripts/api-check.sh.

Also:

  • Every action is pinned by SHA.
  • The title check moves to action-semantic-pull-request v6.1.1 (Node 24) and gets a read-only token. pull_request_target would otherwise get the repo's default write token.
  • Xcode is selected in one place (.github/actions/select-xcode, 26.6).
  • Dependabot keeps the actions current, with the ci prefix so its PR titles pass the title check.

Known gaps:

  • Raising @available on a single public declaration is not detected, because the digester ignores availability. It belongs in the convention checks planned next.
  • macOS-only public API is not diffed. iOS is the only declared platform.
  • workflow_dispatch is deliberately absent. A dispatched run on a PR branch posts checks with the same names on the head SHA, and that could mask a failing merge-ref result.
  • After a stacked PR is retargeted, push a commit or close and reopen it. A base change fires only edited, and ci.yml doesn't listen to it, so that CodeRabbit body edits don't rebuild everything.

After merge:

  • Add Build: iOS device + macOS, Unit tests (iOS Simulator), Lint CI config (actionlint, shellcheck) and Public API, iOS floor, tools version to the master ruleset as required checks, pinned to GitHub Actions. Until then a red result informs but doesn't block.
  • Open PRs pick the checks up on their next push or on close/reopen.
  • chore!: raise the deployment target to iOS 18 #15 will need chore!: in its title, because raising the floor to iOS 18 is breaking for consumers by this rule.

How Has This Been Tested?

Locally with Xcode 27. The runner uses Xcode 26.6, and this PR's own run is the first time the workflows run on it.

  • actionlint 1.7.12 and shellcheck 0.11 pass clean.
  • Release builds for device and simulator pass, swift build passes, and 16/16 tests pass on an iPhone 17 (iOS 27) picked by the script.
  • api-check.sh was run on simulated git merge --no-ff commits onto master:
Change Title Result
this branch ci: … pass
Toast.init label renamed (UIKit-only file) feat: … / feat(toast)!: … fail / pass
new DashIcon.Menu case feat(icons): … pass
new DashIcon.Menu case + Toast.init change feat: … fail
.iOS(.v14) → .iOS(.v15) chore: … / chore!: … fail / pass
#15 merged (iOS 18) chore: … / chore!: … fail / pass
base ref missing — fail with an explicit error

Breaking Changes

None. These are CI changes only. No Swift sources, Package.swift, docs or assets are touched.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Added automated checks for builds, tests, code quality, and compatibility changes across Apple platforms.
    • Updated development-tool selection and dependency monitoring to support more consistent project maintenance.
    • Tightened permissions and pinned a workflow action to a specific version for more predictable automation.

romchornyi and others added 6 commits October 23, 2026 14:57
Nothing compiled the library on a PR, so a change that does not build, or
that uses a newer-iOS API inside a component annotated for iOS 14, could be
merged. Add:

- Build (iOS): iOS Simulator build in Debug (compiles previews) and Release
- Test: tests on an available iPhone simulator
- API compatibility: diagnose-api-breaking-changes against the base branch;
  a break passes only when the PR title marks it with "!"
- Lint workflows: actionlint 1.7.12

Pin every action by SHA (including the existing semantic PR title action)
and let Dependabot keep them current.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- API check: build for the iOS Simulator, where the UIKit-only public API
  exists (on the macOS host it was compiled out and never compared), and
  compare against the merge commit's first parent instead of the live base
  tip, so a re-run after the base moves does not report new base API as
  removed. Body edits no longer cancel a running check.
- Type-check the sources at the iOS floor from Package.swift: xcodebuild
  raises the deployment target to the SDK minimum and missed iOS 15 APIs.
- Test: pick a simulator runtime the selected Xcode can run, keep the
  failure output and test count in the log, skip the 10-minute diagnostics
  collection on failure. Drop the Debug build the test run already does.
- actionlint tarball is checksum-verified; Xcode selection lives in one
  composite action; master runs are grouped per commit; no
  workflow_dispatch; the title-check token is read-only; the "!" title
  match follows the conventional-commit parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- API check also fails on a raised iOS deployment target without "!",
  reads the PR title live (a re-run reuses the old payload), cancels only
  on a new commit, and puts just the verdict in the step summary. Logic
  moved to .github/scripts/api-check.sh so it is shellchecked and testable.
- Floor type-check: parse major.minor from exactly one .iOS(.vNN) entry,
  pass the SwiftPM defines/package name, fail loudly on manifest shapes it
  does not model and on an empty source list, one DEBUG pass instead of two.
- Build: arm64-only Release build, plus `swift build` for the macOS path.
- Lint: shellcheck the scripts, which actionlint does not cover.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- API check: new DashIcon cases are not counted as breaking (every icon
  import adds them); the summary verdict also matches the singular
  "1 breaking change detected" and drops OSC-8 hyperlinks; build at the
  package's own platform instead of the SDK version; no temp file.
- Simulator: compare runtimes by major.minor against the SDK and pick the
  newest runtime that actually has an iPhone.
- Type-check: guard tools version, Package@swift-*.swift and release- or
  device-only branches it does not cover; clean up on failure too.
- ios-floor.sh ignores trailing comments and names the base manifest.
- Xcode selection moved into a shellchecked script.
- Title check on action-semantic-pull-request v6.1.1 (Node 24).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The swiftc type-check at iOS 14 checked a configuration no toolchain that
reads this manifest can build: swift-tools-version 6.3 needs Xcode 26.4+,
which raises the target to iOS 15. The only consumer is on iOS 18 and #15
moves the floor there, after which the regular build catches newer APIs.

- API check: raising swift-tools-version is a break too; the digester
  output streams to the log while it runs.
- pick-simulator.sh reads simctl JSON through files, not arguments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Build the Release configuration for devices, the slice that ships.
- API check: skip closed PRs (`edited` fires there too), keep GH_TOKEN
  away from the PR build, accept any whitespace/case in the
  swift-tools-version header, clearer version_raised helper.
- pick-simulator.sh: simctl failures surface before jq.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 5034779 and 6469cc8.

📒 Files selected for processing: 9
  • .github/actions/select-xcode/action.yml
  • .github/dependabot.yml
  • .github/scripts/api-check.sh
  • .github/scripts/ios-floor.sh
  • .github/scripts/pick-simulator.sh
  • .github/scripts/select-xcode.sh
  • .github/workflows/api-check.yml
  • .github/workflows/ci.yml
  • .github/workflows/semantic-pull-request.yml

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

Adds GitHub Actions workflows for builds, simulator tests, linting, and API compatibility checks. Adds scripts and a composite action to select Xcode and simulators, and updates Dependabot and semantic pull request settings.

Changes: Build and compatibility checks

Layer / File(s) Summary
Xcode and simulator selection
.github/actions/select-xcode/action.yml, .github/scripts/select-xcode.sh, .github/scripts/pick-simulator.sh
Adds an action and scripts to select an Xcode version and an eligible iPhone simulator.
Build, test, and lint workflow
.github/workflows/ci.yml
Adds pull request and master checks for iOS and macOS builds, simulator tests, actionlint, and shellcheck.
API compatibility workflow
.github/workflows/api-check.yml, .github/scripts/ios-floor.sh, .github/scripts/api-check.sh
Adds a pull request workflow and script that compare platform and Swift tools versions and run SwiftPM API-breakage diagnostics. The script reports results and allows breaks when the PR title contains a conventional-commit breaking marker.

Repository automation settings

Layer / File(s) Summary
Dependency updates and pull request validation
.github/dependabot.yml, .github/workflows/semantic-pull-request.yml
Configures weekly GitHub Actions dependency updates. The semantic pull request workflow uses read-only pull request permissions and pins its action to a commit.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 6469c

The new checks are ready to merge subject to normal CI validation; no actionable blocking issue was established.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. (5 skipped: 5… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the pull request's primary changes: CI build and test checks, plus API-break detection.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. (5 skipped: 5 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

- Job names say what they check: "Build: iOS device + macOS",
  "Unit tests (iOS Simulator)", "Lint CI config (actionlint, shellcheck)",
  and "Breaking changes / Public API, iOS floor, tools version".
- The API check failed on the runner (Swift 6.3) with "Unable to parse
  empty data": the native build system, the default there, cannot feed the
  digester for an iOS cross-build. Select swiftbuild explicitly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@romchornyi
romchornyi requested a review from llbartekll October 23, 2026 13:34
@romchornyi

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@romchornyi
romchornyi merged commit 0e97023 into master Oct 23, 2026
10 checks passed
@romchornyi
romchornyi deleted the ci/build-test-api-check branch October 23, 2026 17:59
@coderabbitai coderabbitai Bot mentioned this pull request Oct 23, 2026
4 tasks done
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