-
Notifications
You must be signed in to change notification settings - Fork 26
Add CI and DocC Makefile workflows #148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
0cc59f5
fa5b42d
7030ace
cb1e984
46d733a
b0405da
c7ef873
83b1290
0544a2d
7e6776e
62b25a7
3d04c99
e4fb889
1e0672b
9eb00ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| concurrency: | ||
| group: ci-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| build-test-lint: | ||
| runs-on: macos-26 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Select latest stable Xcode | ||
| uses: maxim-lobanov/setup-xcode@v1 | ||
| with: | ||
| xcode-version: latest-stable | ||
|
|
||
| - name: Install tools | ||
| run: brew install swiftlint swiftformat | ||
|
|
||
| - name: Build | ||
| run: make build RAW_XCODEBUILD=1 | ||
|
|
||
| - name: Test | ||
| env: | ||
| XCORE_CI: "true" | ||
| SIMCTL_CHILD_XCORE_CI: "true" | ||
| run: make test XCORE_CI=1 | ||
|
|
||
| - name: Lint | ||
| run: make lint |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,71 +1,70 @@ | ||
| # Build and deploy DocC to GitHub pages. Based off of @pointfreeco's work here: | ||
| # https://github.com/pointfreeco/swift-composable-architecture/blob/main/.github/workflows/documentation.yml | ||
| name: Documentation | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - main | ||
| release: | ||
| types: [published] | ||
|
|
||
| concurrency: | ||
| group: docs-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: macos-15 | ||
| build-and-deploy: | ||
| runs-on: macos-26 | ||
| steps: | ||
| - name: Select Xcode 16.2 | ||
| run: sudo xcode-select -s /Applications/Xcode_16.2.app | ||
|
|
||
| - name: Checkout Package | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Checkout gh-pages Branch | ||
| uses: actions/checkout@v4 | ||
| - name: Select latest stable Xcode | ||
| uses: maxim-lobanov/setup-xcode@v1 | ||
| with: | ||
| ref: gh-pages | ||
| path: docs-out | ||
|
|
||
| - name: Build documentation | ||
| run: > | ||
| rm -rf docs-out/.git; | ||
| rm -rf docs-out/main; | ||
| git tag -l --sort=-v:refname | grep -e "\d\+\.\d\+.0" | tail -n +6 | xargs -I {} rm -rf {}; | ||
| xcode-version: latest-stable | ||
|
|
||
| for tag in $(echo "main"; git tag -l --sort=-v:refname | grep -e "\d\+\.\d\+.0" | head -6); | ||
| do | ||
| if [ -d "docs-out/$tag/data/documentation/xcore" ] | ||
| then | ||
| echo "✅ Documentation for "$tag" already exists."; | ||
| else | ||
| echo "⏳ Generating documentation for Xcore @ "$tag" release."; | ||
| rm -rf "docs-out/$tag"; | ||
| - name: Resolve documentation version | ||
| id: docs | ||
| run: | | ||
| if [[ "${{ github.event_name }}" == "release" ]]; then | ||
| version="${{ github.event.release.tag_name }}" | ||
| else | ||
| version="main" | ||
| fi | ||
|
|
||
| git checkout .; | ||
| git checkout "$tag"; | ||
| echo "version=$version" >> "$GITHUB_OUTPUT" | ||
| echo "base_path=xcore/$version" >> "$GITHUB_OUTPUT" | ||
|
|
||
| swift package \ | ||
| --allow-writing-to-directory docs-out/"$tag" \ | ||
| generate-documentation \ | ||
| --target Xcore \ | ||
| --disable-indexing \ | ||
| --output-path docs-out/"$tag" \ | ||
| --transform-for-static-hosting \ | ||
| --hosting-base-path /xcore/"$tag" \ | ||
| && echo "✅ Documentation generated for Xcore @ "$tag" release." \ | ||
| || echo "⚠️ Documentation skipped for Xcore @ "$tag"."; | ||
| fi; | ||
| done | ||
| - name: Build DocC static site | ||
| run: | | ||
| make build-docc \ | ||
| DOCC_OUTPUT_PATH="$PWD/.build/docc-site" \ | ||
| DOCC_HOSTING_BASE_PATH="${{ steps.docs.outputs.base_path }}" | ||
|
|
||
| - name: Fix permissions | ||
| run: "sudo chown -R $USER docs-out" | ||
| - name: Add redirect | ||
| run: | | ||
| cat > "$PWD/.build/docc-site/index.html" <<'HTML' | ||
| <!doctype html> | ||
| <html> | ||
| <head> | ||
| <meta http-equiv="refresh" content="0; url=documentation/xcore/"> | ||
| </head> | ||
| <body> | ||
| <a href="documentation/xcore/">Xcore documentation</a> | ||
| </body> | ||
| </html> | ||
| HTML | ||
|
|
||
| - name: Publish documentation to GitHub Pages | ||
| uses: JamesIves/github-pages-deploy-action@4.1.7 | ||
| - name: Deploy to gh-pages | ||
| uses: JamesIves/github-pages-deploy-action@v4 | ||
| with: | ||
| branch: gh-pages | ||
| folder: docs-out | ||
| single-commit: true | ||
| folder: .build/docc-site | ||
| target-folder: ${{ steps.docs.outputs.version }} | ||
| clean: false | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ xcuserdata | |
| DerivedData | ||
| *.hmap | ||
| *.ipa | ||
| *.doccarchive | ||
| *.xcuserstate | ||
| .DS_Store | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| --swiftversion 5.5 | ||
| --swiftversion 6.3 | ||
|
|
||
| # File Options | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ SHELL := /bin/bash | |
| .DEFAULT_GOAL := help | ||
| .NOTPARALLEL: | ||
|
|
||
| XCODE_APP ?= /Applications/Xcode.app | ||
| XCODE_APP ?= $(if $(MD_APPLE_SDK_ROOT),$(MD_APPLE_SDK_ROOT),/Applications/Xcode.app) | ||
| DEVELOPER_DIR ?= $(XCODE_APP)/Contents/Developer | ||
| export DEVELOPER_DIR | ||
| export PATH := $(DEVELOPER_DIR)/usr/bin:$(DEVELOPER_DIR)/Platforms/iPhoneSimulator.platform/Developer/usr/bin:$(PATH) | ||
|
|
@@ -12,6 +12,9 @@ SCHEME := Example | |
| CONFIGURATION ?= Debug | ||
| DERIVED_DATA_PATH ?= $(CURDIR)/.build/DerivedData | ||
| APP_BUNDLE_ID ?= com.xcore.example | ||
| DOCC_TARGET ?= Xcore | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cursoragent why does this need to be a var??? |
||
| DOCC_OUTPUT_PATH ?= $(CURDIR)/.build/docc | ||
| DOCC_HOSTING_BASE_PATH ?= xcore | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cursoragent same here. Why var? |
||
|
|
||
| SIMULATOR_NAME ?= iPhone 17 Pro | ||
| SIMULATOR_OS ?= latest | ||
|
|
@@ -20,12 +23,21 @@ BUILD_DESTINATION ?= generic/platform=iOS Simulator | |
| TEST_ONLY ?= | ||
|
|
||
| XCODEBUILD := xcodebuild | ||
| XCODEBUILD_FLAGS ?= -skipPackagePluginValidation -skipMacroValidation | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cursoragent shouldnt most of this be consolidated under CI flags so we can just simply do this in this file and not have logic in the workflow and the make file. |
||
| XCODEBUILD_BUILD_SETTINGS ?= | ||
| RAW_XCODEBUILD ?= | ||
| APP_PATH := $(DERIVED_DATA_PATH)/Build/Products/$(CONFIGURATION)-iphonesimulator/Example.app | ||
| XCODEBUILD_OUTPUT_FILTER := perl -ne 'next if /\[MT\] IDERunDestination: Supported platforms for the buildables in the current scheme is empty\.|\[MT\] IDETestOperationsObserverDebug:/; s/ on '\''[^'\'']+'\''// if /^(Test suite|Test case) /; print;' | ||
|
|
||
| ifeq ($(XCORE_CI),1) | ||
| XCODEBUILD_BUILD_SETTINGS += OTHER_SWIFT_FLAGS="\$$(inherited) -DXCORE_CI" | ||
| endif | ||
|
|
||
| define xcodebuild_run | ||
| @set -o pipefail; \ | ||
| if command -v xcpretty >/dev/null 2>&1; then \ | ||
| if [ -n "$(RAW_XCODEBUILD)" ]; then \ | ||
| $(1); \ | ||
| elif command -v xcpretty >/dev/null 2>&1; then \ | ||
| $(1) 2>&1 | $(XCODEBUILD_OUTPUT_FILTER) | xcpretty; \ | ||
| elif command -v xcbeautify >/dev/null 2>&1; then \ | ||
| $(1) 2>&1 | $(XCODEBUILD_OUTPUT_FILTER) | xcbeautify; \ | ||
|
|
@@ -40,7 +52,7 @@ TEST_ONLY_ARG := -only-testing:$(TEST_ONLY) | |
| endif | ||
| endif | ||
|
|
||
| .PHONY: help _ensure_xcode clean build tests test run lint format | ||
| .PHONY: help _ensure_xcode clean build build-docc tests test run lint format format-check | ||
|
|
||
| _ensure_xcode: | ||
| @test -d "$(DEVELOPER_DIR)" || (echo "Xcode not found at $(DEVELOPER_DIR)" && exit 1) | ||
|
|
@@ -57,17 +69,28 @@ clean: ## Remove local build and package state used by Make targets | |
| @rm -rf "$(DERIVED_DATA_PATH)" "$(CURDIR)/.build/workspace-state.json" | ||
|
|
||
| build: _ensure_xcode ## Build the example app and its framework dependencies | ||
| $(call xcodebuild_run,$(XCODEBUILD) build -workspace "$(WORKSPACE)" -scheme "$(SCHEME)" -configuration "$(CONFIGURATION)" -derivedDataPath "$(DERIVED_DATA_PATH)" -destination "$(BUILD_DESTINATION)") | ||
| $(call xcodebuild_run,$(XCODEBUILD) build $(XCODEBUILD_FLAGS) -workspace "$(WORKSPACE)" -scheme "$(SCHEME)" -configuration "$(CONFIGURATION)" -derivedDataPath "$(DERIVED_DATA_PATH)" -destination "$(BUILD_DESTINATION)" $(XCODEBUILD_BUILD_SETTINGS)) | ||
|
|
||
| build-docc: _ensure_xcode ## Generate DocC static site output under DOCC_OUTPUT_PATH | ||
| @rm -rf "$(DOCC_OUTPUT_PATH)" | ||
| @swift package \ | ||
| --allow-writing-to-directory "$(DOCC_OUTPUT_PATH)" \ | ||
| generate-documentation \ | ||
| --target "$(DOCC_TARGET)" \ | ||
| --disable-indexing \ | ||
| --output-path "$(DOCC_OUTPUT_PATH)" \ | ||
| --transform-for-static-hosting \ | ||
| --hosting-base-path "$(DOCC_HOSTING_BASE_PATH)" | ||
|
|
||
| test: _ensure_xcode ## Run tests through the Example scheme | ||
| @set -o pipefail; \ | ||
| $(XCODEBUILD) test -quiet -workspace "$(WORKSPACE)" -scheme "$(SCHEME)" -configuration "$(CONFIGURATION)" -derivedDataPath "$(DERIVED_DATA_PATH)" -destination "$(SIMULATOR_DESTINATION)" $(TEST_ONLY_ARG) 2>&1 | $(XCODEBUILD_OUTPUT_FILTER) && \ | ||
| $(XCODEBUILD) test -quiet $(XCODEBUILD_FLAGS) -workspace "$(WORKSPACE)" -scheme "$(SCHEME)" -configuration "$(CONFIGURATION)" -derivedDataPath "$(DERIVED_DATA_PATH)" -destination "$(SIMULATOR_DESTINATION)" $(TEST_ONLY_ARG) $(XCODEBUILD_BUILD_SETTINGS) 2>&1 | $(XCODEBUILD_OUTPUT_FILTER) && \ | ||
| echo "Tests passed" | ||
|
|
||
| run: _ensure_xcode ## Build, install, and launch the app in the configured simulator | ||
| @xcrun simctl boot "$(SIMULATOR_NAME)" >/dev/null 2>&1 || true | ||
| @xcrun simctl bootstatus "$(SIMULATOR_NAME)" -b | ||
| $(call xcodebuild_run,$(XCODEBUILD) build -workspace "$(WORKSPACE)" -scheme "$(SCHEME)" -configuration "$(CONFIGURATION)" -derivedDataPath "$(DERIVED_DATA_PATH)" -destination "$(SIMULATOR_DESTINATION)") | ||
| $(call xcodebuild_run,$(XCODEBUILD) build $(XCODEBUILD_FLAGS) -workspace "$(WORKSPACE)" -scheme "$(SCHEME)" -configuration "$(CONFIGURATION)" -derivedDataPath "$(DERIVED_DATA_PATH)" -destination "$(SIMULATOR_DESTINATION)" $(XCODEBUILD_BUILD_SETTINGS)) | ||
| @test -d "$(APP_PATH)" || (echo "Built app not found at $(APP_PATH)" && exit 1) | ||
| @open -a Simulator >/dev/null 2>&1 || true | ||
| @xcrun simctl install booted "$(APP_PATH)" | ||
|
|
@@ -76,5 +99,8 @@ run: _ensure_xcode ## Build, install, and launch the app in the configured simul | |
| format: ## Run SwiftFormat | ||
| @swiftformat . | ||
|
|
||
| format-check: ## Check SwiftFormat without changing files | ||
| @swiftformat --lint . | ||
|
|
||
| lint: ## Run SwiftLint | ||
| @swiftlint lint | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // | ||
| // Xcore | ||
| // Copyright © 2026 Xcore | ||
| // MIT license, see LICENSE file for details | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| enum TestEnvironment { | ||
| static var isCI: Bool { | ||
| #if XCORE_CI | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cursoragent why not just use CI flags instead of prefixing XcoreCI? CI means CI. |
||
| true | ||
| #else | ||
| let environment = ProcessInfo.processInfo.environment | ||
| return environment["CI"] == "true" || environment["XCORE_CI"] == "true" | ||
| #endif | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cursoragent remove this change as it's fairly massive change on each push to main. Doc build should be manual trigger.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the automatic DocC build on push to
main. The Documentation workflow now runs only on:workflow_dispatch)The
push: branches: [main]trigger is gone from.github/workflows/documentation.yml, so docs are no longer rebuilt and redeployed on every push tomain. The PR description was updated to match.