Skip to content

Add unit tests and a CI workflow - #2

Merged
Ramiz69 merged 6 commits into
mainfrom
tests-and-ci
Oct 19, 2026
Merged

Ramiz69 merged 6 commits into
mainfrom
tests-and-ci

Conversation

@Ramiz69

@Ramiz69 Ramiz69 commented Oct 19, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the first test suite and a CI workflow. Builds on #1. Until #1 is merged, its commits also show up here; the commit that belongs to this PR is 7cff50f.

Changes

  • New FrameGenTests target using Swift Testing and hosted by the app, added to the shared FrameGen scheme. It has 34 tests:
    • ProjectInfo decoding of xcodebuild -list -json, including fallbacks when schemes or configurations are missing;
    • XcodeCommand arguments for every platform, including paths with spaces and quotes;
    • XCFrameworkBuilder.makePlan (slices, dSYMs, error cases, stale output) and finalize (checksum, snippet, privacy manifests in flat and versioned frameworks);
    • ProcessRunner (line streaming, exit codes, merged and separate stderr, cancellation, missing executable);
    • BuildState activity parsing and resets;
    • ProjectLocator (search depth, packages, hidden folders).
  • .github/workflows/ci.yml builds and tests on pushes and pull requests to main. It needs Xcode 27; on a runner without it, the "Select Xcode 27" step fails with a message pointing to a self-hosted runner.
  • The README explains how to run the tests. No production code changed.

Testing

  • xcodebuild test -scheme FrameGen -destination 'platform=macOS,arch=arm64' CODE_SIGNING_ALLOWED=NO passes locally: 34 passed, 0 failed.
  • This PR is the workflow's first run on GitHub, so it will show whether hosted runners have Xcode 27.

Notes for reviewers

  • Test helper: /var is a symlink to /private/var, so TemporaryDirectory uses realpath to give path comparisons a canonical root.

…ation

- Run xcodebuild directly with an argument array and currentDirectoryURL
  instead of interpolating paths into a bash string, so paths with spaces
  or quotes no longer break the build.
- Build the archive path with URL APIs so custom output folders without a
  trailing slash resolve correctly.
- Drain stdout and stderr concurrently to avoid hanging once a pipe buffer
  fills up; return early when the process fails to launch.
- Report cancellation as TaskError.canceled; on the first failure cancel
  the remaining archives and show a single error instead of error + success.
- Use generic/platform=macOS,variant=Mac Catalyst instead of x86_64-only.
After every selected platform is archived, FrameGen now:
- runs xcodebuild -create-xcframework with each framework and its dSYM;
- zips the bundle with ditto and computes the SwiftPM checksum (SHA-256);
- writes a ready-to-paste .binaryTarget snippet next to the zip;
- warns about slices that ship without PrivacyInfo.xcprivacy.

Archives are built with SWIFT_ENABLE_LIBRARY_EVOLUTION and
SWIFT_EMIT_MODULE_INTERFACE set explicitly: current Xcode no longer derives
them from BUILD_LIBRARIES_FOR_DISTRIBUTION, and -create-xcframework rejects
Swift frameworks without a .swiftinterface.

The success alert now offers "Show in Finder".
UI (AppKit, NSViewController-based MVC, no SwiftUI):
- Welcome screen with Open Project (⌘O), recent projects and drag and drop
  of an .xcodeproj or its folder anywhere in the window.
- Project form in the System Settings style: scheme, configuration,
  platform switches and output folder; choices persist per project.
- Live build screen with step statuses, durations, the current xcodebuild
  action and a collapsible log; Stop with ⌘. or Esc.
- Inline result with files, SwiftPM checksum and binaryTarget snippet with
  copy buttons, and a privacy manifest warning instead of modal alerts.
- Failure screen with the failed step, extracted compiler errors and the log.
- Full menu bar (File, Edit, Product, Window), unified toolbar, Settings
  window (⌘,), window frame autosave, system colors and Dark Mode.

Architecture:
- Models: Workspace, Project and BuildState as @observable classes;
  view controllers follow them through withObservationTracking.
- BuildController runs the pipeline with async/await and task cancellation.
- ProcessRunner streams xcodebuild output as an AsyncThrowingStream and
  interrupts the process on cancellation; xcodebuild -list -json replaces
  text parsing and every command passes -project explicitly.

Project settings: Xcode 27.1, macOS 27.0 deployment target, arm64 only,
Swift 6 language mode with MainActor default isolation and approachable
concurrency. Info.plist and entitlements drop unused iOS keys and rights.

The previous MVP sources (Flows, Managers, Resources, Core) are no longer
part of the target and can be deleted.
Flows, Managers, Resources and Core were replaced by the AppKit MVC
controllers, models and services and were no longer part of the target.
- Rewrite the README for the AppKit redesign: features, requirements,
  usage, output layout, shortcuts, building and architecture.
- Replace the screenshots of the old UI with the welcome, configuration,
  progress and result screens.
- Add a .gitignore and remove xcuserdata from the index; the files stay
  on disk.
- New FrameGenTests target (Swift Testing, hosted by the app) in the
  shared scheme, with 34 tests covering:
  - ProjectInfo decoding of xcodebuild -list -json, including fallbacks;
  - XcodeCommand arguments, including paths with spaces and quotes;
  - XCFrameworkBuilder plans (slices, dSYMs, errors, stale output) and
    finalize (checksum, snippet, privacy manifests in flat and versioned
    frameworks);
  - ProcessRunner streaming, exit codes, stderr handling, cancellation;
  - BuildState activity parsing and resets;
  - ProjectLocator search depth, packages, hidden folders.
- .github/workflows/ci.yml builds and tests on pushes and pull requests to
  main. Hosted runners may lack Xcode 27; the workflow fails with a clear
  message and points to a self-hosted runner.
- README explains how to run the tests.

No production code changed.
@Ramiz69
Ramiz69 merged commit 4c07acd into main Oct 19, 2026
1 check failed
@Ramiz69
Ramiz69 deleted the tests-and-ci branch October 19, 2026 13:29
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