Skip to content

Implement GutenbergKitResources binary dependency build#318

Open
mokagio wants to merge 28 commits intotrunkfrom
ainfra-1967-implement-gutenbergkitresources-binary-dependency-build
Open

Implement GutenbergKitResources binary dependency build#318
mokagio wants to merge 28 commits intotrunkfrom
ainfra-1967-implement-gutenbergkitresources-binary-dependency-build

Conversation

@mokagio
Copy link
Contributor

@mokagio mokagio commented Feb 11, 2026

What?

Adds infrastructure to build and distribute GutenbergKitResources as a pre-built XCFramework, decoupling the JS build from Swift consumers.

Based on the research work done on #315 .

Why?

Currently, every Swift consumer must run the full JS build to get Gutenberg editor assets.
With a binary XCFramework for resources, consumers can pull a pre-built artifact from CDN instead, significantly reducing build times and simplifying integration.

How?

  • New GutenbergKitResources SPM target wrapping bundled editor assets (HTML, CSS, JS)
  • Package.swift uses Context.environment to switch between local source and CDN binary target
  • build_xcframework.sh assembles a proper .framework from SPM archive DerivedData (binary, swiftmodule, modulemap, headers, resource bundles) since SPM archives don't produce installable frameworks
  • Fastlane release lane handles versioning, GitHub release, and S3 upload
  • CI pipeline updated with XCFramework build step and artifact publishing
  • GutenbergKit target depends on GutenbergKitResources instead of bundling assets directly
  • All package access modifiers migrated to internal (required by packageAccess: false)
  • Tracked JS build artifacts removed from Git

Testing Instructions

  1. make build — builds web assets and copies to all platform directories
  2. make build-swift-package — builds the Swift package with local resources
  3. make build-resources-xcframework — produces GutenbergKitResources-<sha>.xcframework.zip
  4. Verify the XCFramework contains both ios-arm64 and ios-arm64_x86_64-simulator slices with the binary, Modules, Headers, and resource bundle

Generated with the help of Claude Opus 4.6

@mokagio mokagio added the [Type] Task Issues or PRs that have been broken down into an individual action to take label Feb 11, 2026
@mokagio mokagio force-pushed the ainfra-1967-implement-gutenbergkitresources-binary-dependency-build branch from d39e34e to e53dfea Compare February 12, 2026 01:35
/// - ``always``: Always returns `true` - cached responses are always used.
///
package func allowsResponseWith(date: Date, currentDate: Date = .now) -> Bool {
func allowsResponseWith(date: Date, currentDate: Date = .now) -> Bool {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

SwiftPM required packageAccess: false on the GutenbergKit target for binary target compatibility.

With that flag off, the compiler no longer passes -package-name, so the package access modifier silently degrades to fileprivate breaking visibility across files within the module.

Comment on lines -55 to 57
let gutenbergCSS = Self.loadGutenbergCSS() ?? ""
let gutenbergCSS = GutenbergKitResources.loadGutenbergCSS() ?? ""
assert(!gutenbergCSS.isEmpty, "Failed to load Gutenberg CSS from bundle. Previews will not render correctly.")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There might be more robust ways to handle a path error internally, but I consider them out of scope for the moment.

Comment on lines +192 to +193
/ios/Sources/GutenbergKit/Gutenberg/assets
/ios/Sources/GutenbergKit/Gutenberg/index.html
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These should not actually be generated anymore. We can keep them here for a while to avoid issues while local copies update, or get rid of them already to avoid carrying dead weight. What do you think?

Suggested change
/ios/Sources/GutenbergKit/Gutenberg/assets
/ios/Sources/GutenbergKit/Gutenberg/index.html

@@ -0,0 +1,152 @@
#!/usr/bin/env bash
Copy link
Contributor Author

@mokagio mokagio Feb 12, 2026

Choose a reason for hiding this comment

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

It took me a while to get this to run in #315 and it's based on a setup that had it in the root and I wasn't game to move it just yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mokagio and others added 19 commits February 19, 2026 18:17
Introduces a new `GutenbergKitResources` target to host
the built Gutenberg web assets as a separate module.

`Package.swift` uses `GUTENBERGKIT_SWIFT_USE_LOCAL_RESOURCES`
env var to switch between a local source target (development)
and a pre-built XCFramework binary target (releases).

Sets `packageAccess: false` on `GutenbergKit` — required
for binary target compatibility within the same package.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Required by `packageAccess: false` on the GutenbergKit
target, which enables binary target compatibility for
GutenbergKitResources within the same package.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace `Bundle.module` lookups in `EditorViewController`
and `HTMLPreviewManager` with the new module's API.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resources are now served by GutenbergKitResources.
The `Gutenberg/` directory is excluded from the target
and both build output directories are gitignored.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The script archives GutenbergKitResources for device and
simulator, creates an XCFramework, and outputs a zip with
checksum for SPM consumption.

Makefile changes:

- Set GUTENBERGKIT_SWIFT_USE_LOCAL_RESOURCES for all targets
- Copy dist output to GutenbergKitResources/Resources/
- Add build-resources-xcframework target

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Swift tests now build resources locally first
- Add XCFramework build step with artifact upload

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Modeled on wordpress-rs. The `release` lane:

1. Validates the version doesn't already exist
2. Updates Package.swift version and checksum
3. Tags, pushes, and creates a GitHub release
4. Uploads XCFramework zip to S3

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These ~58 files are now generated during the build and
distributed via the GutenbergKitResources XCFramework.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The XCFramework build failed because xcodebuild only
auto-creates schemes for products, not bare targets.
Test signing failed because CI lacks a code identity
for the new resource bundle.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
xcodebuild requires -destination for SPM packages.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The auto-generated GutenbergKit product scheme no
longer includes a test action now that there are
multiple products in the package.

---

Generated with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SPM archives on Xcode 26 no longer produce a usable .framework in
the archive Products directory. Assemble it manually from DerivedData
(binary, swiftmodule, modulemap, headers, resource bundles).

Also bump simulator destination to OS=26.1.

---

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The inline call used `-scheme GutenbergKitTests` which doesn't
exist when the package uses the local resources layout.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The GutenbergKit scheme has no test action configured.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mokagio and others added 9 commits February 19, 2026 18:18
Neither GutenbergKit nor GutenbergKitTests have the test
action. GutenbergKit-Package does.

---

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Avoids breakage when CI and local have different
Xcode point releases.

---

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The macro now takes the scheme as a parameter, removing
the duplicated xcodebuild invocation.

---

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

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

Generate with the help of Claude Code, https://code.claude.com

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Buildkite's interpolator doesn't support shell parameter
expansion (`${VAR#pattern}`).
`$$` passes through as a literal `$` to the shell.

---

Generated with the help of Claude Code, https://claude.ai/code

Co-Authored-By: Claude Code Opus 4.6 <noreply@anthropic.com>
@mokagio mokagio force-pushed the ainfra-1967-implement-gutenbergkitresources-binary-dependency-build branch from 9e7a477 to 76639c8 Compare February 19, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Task Issues or PRs that have been broken down into an individual action to take

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments