diff --git a/.github/workflows/syndikit.yml b/.github/workflows/syndikit.yml index 3f2f504..40c43e4 100644 --- a/.github/workflows/syndikit.yml +++ b/.github/workflows/syndikit.yml @@ -1,89 +1,127 @@ name: SyndiKit on: push: - branches-ignore: - - '*WIP' - + branches: + - main + - 'v[0-9]+.[0-9]+.[0-9]+' + paths-ignore: + - '**.md' + - 'docs/**' + - 'LICENSE' + - '.github/ISSUE_TEMPLATE/**' + pull_request: + paths-ignore: + - '**.md' + - 'docs/**' + - 'LICENSE' + - '.github/ISSUE_TEMPLATE/**' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + +env: + PACKAGE_NAME: SyndiKit + jobs: - build-ubuntu: - name: Build on Ubuntu - env: - PACKAGE_NAME: SyndiKit + configure: + name: Configure Matrix runs-on: ubuntu-latest - container: ${{ matrix.swift.nightly && format('swiftlang/swift:nightly-{0}-noble', matrix.swift.version) || format('swift:{0}', matrix.swift.version) }} - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} - strategy: - matrix: - os: [noble, jammy] - swift: - - version: "5.10" - - version: "6.0" - - version: "6.1" - - version: "6.2" - - version: "6.3" - nightly: true + outputs: + full-matrix: ${{ steps.matrix.outputs.full-matrix }} + ubuntu-os: ${{ steps.matrix.outputs.ubuntu-os }} + ubuntu-swift: ${{ steps.matrix.outputs.ubuntu-swift }} + ubuntu-type: ${{ steps.matrix.outputs.ubuntu-type }} steps: - - uses: actions/checkout@v4 - - uses: brightdigit/swift-build@v1.5.0 - with: - scheme: ${{ env.PACKAGE_NAME }} - skip-package-resolved: ${{ contains(matrix.swift.version, '5.') }} - - uses: sersoft-gmbh/swift-coverage-action@v4 - id: coverage-files - with: - fail-on-empty-output: true - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - fail_ci_if_error: true - flags: ubuntu,ubuntu-${{ matrix.os }},swift-${{ matrix.swift.version }}${{ matrix.swift.nightly && '-nightly' || '' }} - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - files: ${{ join(fromJSON(steps.coverage-files.outputs.files), ',') }} - build-wasm: - name: Build on WASM - env: - PACKAGE_NAME: SyndiKit + - id: check + name: Determine matrix scope + run: | + FULL=false + REF="${{ github.ref }}" + EVENT="${{ github.event_name }}" + BASE_REF="${{ github.base_ref }}" + if [[ "$REF" == "refs/heads/main" ]]; then + FULL=true + elif [[ "$REF" =~ ^refs/heads/v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then + FULL=true + elif [[ "$EVENT" == "workflow_dispatch" ]]; then + FULL=true + elif [[ "$EVENT" == "pull_request" ]]; then + if [[ "$BASE_REF" == "main" || "$BASE_REF" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then + FULL=true + fi + fi + echo "full=$FULL" >> "$GITHUB_OUTPUT" + - id: matrix + name: Build matrix values + run: | + if [[ "${{ steps.check.outputs.full }}" == "true" ]]; then + echo 'full-matrix=true' >> "$GITHUB_OUTPUT" + echo 'ubuntu-os=["noble","jammy"]' >> "$GITHUB_OUTPUT" + echo 'ubuntu-swift=[{"version":"5.10"},{"version":"6.0"},{"version":"6.1"},{"version":"6.2"},{"version":"6.3"}]' >> "$GITHUB_OUTPUT" + echo 'ubuntu-type=["","wasm","wasm-embedded"]' >> "$GITHUB_OUTPUT" + else + echo 'full-matrix=false' >> "$GITHUB_OUTPUT" + echo 'ubuntu-os=["noble"]' >> "$GITHUB_OUTPUT" + echo 'ubuntu-swift=[{"version":"6.3"}]' >> "$GITHUB_OUTPUT" + echo 'ubuntu-type=[""]' >> "$GITHUB_OUTPUT" + fi + + build-ubuntu: + name: Build on Ubuntu + needs: configure runs-on: ubuntu-latest - container: ${{ matrix.swift.nightly && format('swiftlang/swift:nightly-{0}-{1}', matrix.swift.version, matrix.os) || format('swift:{0}-{1}', matrix.swift.version, matrix.os) }} - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + container: swift:${{ matrix.swift.version }}-${{ matrix.os }} strategy: - fail-fast: false matrix: - os: [noble, jammy] - type: ["wasm", "wasm-embedded"] - swift: - - version: "6.2" + os: ${{ fromJSON(needs.configure.outputs.ubuntu-os) }} + swift: ${{ fromJSON(needs.configure.outputs.ubuntu-swift) }} + type: ${{ fromJSON(needs.configure.outputs.ubuntu-type) }} + exclude: + - swift: {version: "5.10"} + type: wasm + - swift: {version: "5.10"} + type: wasm-embedded + - swift: {version: "6.0"} + type: wasm + - swift: {version: "6.0"} + type: wasm-embedded + - swift: {version: "6.1"} + type: wasm + - swift: {version: "6.1"} + type: wasm-embedded steps: - - uses: actions/checkout@v4 - - uses: brightdigit/swift-build@v1.5.0 - id: build + - uses: actions/checkout@v6 + - id: build + uses: brightdigit/swift-build@v1 with: - scheme: ${{ env.PACKAGE_NAME }} - skip-package-resolved: ${{ contains(matrix.swift.version, '5.') }} type: ${{ matrix.type }} - - uses: sersoft-gmbh/swift-coverage-action@v4 + skip-package-resolved: ${{ contains(matrix.swift.version, '5.') }} + - name: Install curl + if: steps.build.outputs.contains-code-coverage == 'true' + run: | + if ! command -v curl &> /dev/null; then + apt-get update -q + apt-get install -y curl + fi + - name: Process Coverage if: steps.build.outputs.contains-code-coverage == 'true' - id: coverage-files + uses: sersoft-gmbh/swift-coverage-action@v5 with: fail-on-empty-output: true - name: Upload coverage to Codecov if: steps.build.outputs.contains-code-coverage == 'true' - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v6 with: - fail_ci_if_error: true - flags: ubuntu,ubuntu-${{ matrix.os }},swift-${{ matrix.swift.version }}${{ matrix.swift.nightly && '-nightly' || '' }},${{ matrix.type }} - verbose: true token: ${{ secrets.CODECOV_TOKEN }} - files: ${{ join(fromJSON(steps.coverage-files.outputs.files), ',') }} + flags: spm,${{ matrix.os }},${{ matrix.swift.version }} + fail_ci_if_error: true + build-macos: name: Build on macOS - env: - PACKAGE_NAME: SyndiKit runs-on: ${{ matrix.runs-on }} - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} strategy: - fail-fast: false matrix: include: # SPM Build Matrix - Xcode 15.4 @@ -94,42 +132,24 @@ jobs: - runs-on: macos-15 xcode: "/Applications/Xcode_16.4.app" - # SPM Build Matrix - Xcode 26.0 - - runs-on: macos-26 - xcode: "/Applications/Xcode_26.0.app" - - # SPM Build Matrix - Xcode 26.1 - - runs-on: macos-26 - xcode: "/Applications/Xcode_26.1.app" - - # SPM Build Matrix - Xcode 26.2 + # SPM Build Matrix - Xcode 26.4 - runs-on: macos-26 - xcode: "/Applications/Xcode_26.2.app" + xcode: "/Applications/Xcode_26.4.app" - # SPM Build Matrix - Xcode 15.4 + # macOS Build Matrix - Xcode 15.4 - type: macos runs-on: macos-14 xcode: "/Applications/Xcode_15.4.app" - # SPM Build Matrix - Xcode 16.4 + # macOS Build Matrix - Xcode 16.4 - type: macos runs-on: macos-15 xcode: "/Applications/Xcode_16.4.app" - # SPM Build Matrix - Xcode 26.0 + # macOS Build Matrix - Xcode 26.4 - type: macos runs-on: macos-26 - xcode: "/Applications/Xcode_26.0.app" - - # SPM Build Matrix - Xcode 26.1 - - type: macos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.1.app" - - # SPM Build Matrix - Xcode 26.2 - - type: macos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.2.app" + xcode: "/Applications/Xcode_26.4.app" # iOS Build Matrix - Xcode 15.4 - type: ios @@ -142,29 +162,16 @@ jobs: - type: ios runs-on: macos-15 xcode: "/Applications/Xcode_16.4.app" - deviceName: "iPhone 16 Pro" - osVersion: "18.6" - - # iOS Build Matrix - Xcode 26.0 - - type: ios - runs-on: macos-26 - xcode: "/Applications/Xcode_26.0.app" - deviceName: "iPhone 17 Pro" - osVersion: "26.0.1" - - # iOS Build Matrix - Xcode 26.1 - - type: ios - runs-on: macos-26 - xcode: "/Applications/Xcode_26.1.app" - deviceName: "iPhone 17 Pro" - osVersion: "26.1" + deviceName: "iPhone 16" + osVersion: "18.5" - # iOS Build Matrix - Xcode 26.2 + # iOS Build Matrix - Xcode 26.4 - type: ios runs-on: macos-26 - xcode: "/Applications/Xcode_26.2.app" - deviceName: "iPhone 17 Pro" - osVersion: "26.2" + xcode: "/Applications/Xcode_26.4.app" + deviceName: "iPhone 17" + osVersion: "26.4" + download-platform: true # watchOS Build Matrix - Xcode 15.4 - type: watchos @@ -180,211 +187,125 @@ jobs: deviceName: "Apple Watch Ultra 2 (49mm)" osVersion: "11.5" - # watchOS Build Matrix - Xcode 26.0 + # watchOS Build Matrix - Xcode 26.4 - type: watchos runs-on: macos-26 - xcode: "/Applications/Xcode_26.0.app" + xcode: "/Applications/Xcode_26.4.app" deviceName: "Apple Watch Ultra 3 (49mm)" - osVersion: "26.0" - - # watchOS Build Matrix - Xcode 26.1 - - type: watchos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.1.app" - deviceName: "Apple Watch Ultra 3 (49mm)" - osVersion: "26.1" - - # watchOS Build Matrix - Xcode 26.2 - - type: watchos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.2.app" - deviceName: "Apple Watch Ultra 3 (49mm)" - osVersion: "26.2" + osVersion: "26.4" + download-platform: true # tvOS Build Matrix - Xcode 16.4 - type: tvos runs-on: macos-15 xcode: "/Applications/Xcode_16.4.app" - deviceName: "Apple TV" + deviceName: "Apple TV 4K (3rd generation)" osVersion: "18.5" - # tvOS Build Matrix - Xcode 26.0 - - type: tvos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.0.app" - deviceName: "Apple TV" - osVersion: "26.0" - - # tvOS Build Matrix - Xcode 26.1 + # tvOS Build Matrix - Xcode 26.4 - type: tvos runs-on: macos-26 - xcode: "/Applications/Xcode_26.1.app" - deviceName: "Apple TV" - osVersion: "26.1" - - # tvOS Build Matrix - Xcode 26.2 - - type: tvos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.2.app" - deviceName: "Apple TV" - osVersion: "26.2" + xcode: "/Applications/Xcode_26.4.app" + deviceName: "Apple TV 4K (3rd generation)" + osVersion: "26.4" + download-platform: true # visionOS Build Matrix - Xcode 16.4 - type: visionos runs-on: macos-15 xcode: "/Applications/Xcode_16.4.app" deviceName: "Apple Vision Pro" - osVersion: "2.4" - - # visionOS Build Matrix - Xcode 26.0 - - type: visionos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.0.app" - deviceName: "Apple Vision Pro" - osVersion: "26.0" + osVersion: "2.5" - # visionOS Build Matrix - Xcode 26.1 + # visionOS Build Matrix - Xcode 26.4 - type: visionos runs-on: macos-26 - xcode: "/Applications/Xcode_26.1.app" + xcode: "/Applications/Xcode_26.4.app" deviceName: "Apple Vision Pro" - osVersion: "26.1" - - # visionOS Build Matrix - Xcode 26.2 - - type: visionos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.2.app" - deviceName: "Apple Vision Pro" - osVersion: "26.2" + osVersion: "26.4" + download-platform: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Disable Xcode macro fingerprint validation if: ${{ contains(matrix.xcode, 'Xcode_15.4') && matrix.type != '' }} run: defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES - - name: Build and Test - uses: brightdigit/swift-build@v1.5.0 + - id: build + name: Build and Test + uses: brightdigit/swift-build@v1 with: scheme: ${{ env.PACKAGE_NAME }} type: ${{ matrix.type }} xcode: ${{ matrix.xcode }} deviceName: ${{ matrix.deviceName }} osVersion: ${{ matrix.osVersion }} + download-platform: ${{ matrix.download-platform }} build-only: ${{ contains(matrix.xcode, 'Xcode_15.4') && matrix.type != '' }} skip-package-resolved: ${{ contains(matrix.xcode, 'Xcode_15.4') }} - # Common Coverage Steps - name: Process Coverage - uses: sersoft-gmbh/swift-coverage-action@v4 - - - name: Set coverage flags - id: coverage-flags - run: | - # Select Xcode version - sudo xcode-select -s "${{ matrix.xcode }}" - - # Extract Xcode version from path like /Applications/Xcode_16.4.app - XCODE_VERSION=$(echo "${{ matrix.xcode }}" | sed -n 's/.*Xcode_\([0-9.]*\).*/\1/p') - - # Extract Swift version - SWIFT_VERSION=$(xcrun swift --version | head -n 1 | sed -n 's/.*Swift version \([0-9.]*\).*/\1/p') - - # Extract macOS version from runs-on - MACOS_VERSION=$(echo "${{ matrix.runs-on }}" | sed 's/macos-//') - - # Determine platform - PLATFORM="${{ matrix.type || 'macos' }}" - - # Build flags - if [ -n "${{ matrix.osVersion }}" ]; then - # Platform build (iOS, tvOS, etc.) - FLAGS="${PLATFORM},${PLATFORM}-${{ matrix.osVersion }},swift-${SWIFT_VERSION},xcode-${XCODE_VERSION}" - else - # SPM/macOS build - FLAGS="macos,macos-${MACOS_VERSION},swift-${SWIFT_VERSION},xcode-${XCODE_VERSION}" - fi - - echo "flags=${FLAGS}" >> $GITHUB_OUTPUT + if: ${{ steps.build.outputs.contains-code-coverage == 'true' }} + uses: sersoft-gmbh/swift-coverage-action@v5 + with: + fail-on-empty-output: true + search-paths: | + ./.build + /Users/runner/work/_temp/DerivedData - name: Upload Coverage - uses: codecov/codecov-action@v4 + if: ${{ steps.build.outputs.contains-code-coverage == 'true' }} + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} - flags: ${{ steps.coverage-flags.outputs.flags }} + flags: ${{ matrix.type && format('{0}{1}', matrix.type, matrix.osVersion) || 'spm' }} + fail_ci_if_error: true build-windows: name: Build on Windows - env: - PACKAGE_NAME: SyndiKit + needs: [configure] + if: needs.configure.outputs.full-matrix == 'true' runs-on: ${{ matrix.runs-on }} - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} strategy: - fail-fast: false matrix: - include: - - runs-on: windows-2022 - swift: - version: swift-6.1-release - build: 6.1-RELEASE - - - runs-on: windows-2022 - swift: - version: swift-6.2-release - build: 6.2-RELEASE - - - runs-on: windows-2025 - swift: - version: swift-6.1-release - build: 6.1-RELEASE - - - runs-on: windows-2025 - swift: - version: swift-6.2-release - build: 6.2-RELEASE - + runs-on: [windows-2022, windows-2025] + swift: + - version: swift-6.1-release + build: 6.1-RELEASE + - version: swift-6.2-release + build: 6.2-RELEASE + - version: swift-6.3-release + build: 6.3-RELEASE steps: - - uses: actions/checkout@v4 - - - name: Build and Test - uses: brightdigit/swift-build@v1.5.0 + - uses: actions/checkout@v6 + - id: build + uses: brightdigit/swift-build@v1 with: - scheme: ${{ env.PACKAGE_NAME }} windows-swift-version: ${{ matrix.swift.version }} windows-swift-build: ${{ matrix.swift.build }} - - - name: Set coverage flags - id: coverage-flags - shell: bash - run: | - # Extract version from swift-6.1-release format - VERSION=$(echo "${{ matrix.swift.version }}" | sed 's/swift-\([0-9.]*\)-.*/\1/') - OS_VERSION=$(echo "${{ matrix.runs-on }}" | sed 's/windows-//') - echo "flags=windows,windows-${OS_VERSION},swift-${VERSION}" >> $GITHUB_OUTPUT - - - name: Upload Coverage - uses: codecov/codecov-action@v4 + - name: Upload coverage to Codecov + if: steps.build.outputs.contains-code-coverage == 'true' + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} - flags: ${{ steps.coverage-flags.outputs.flags }} + flags: windows,${{ matrix.swift.version }} + fail_ci_if_error: true build-android: name: Build on Android - env: - PACKAGE_NAME: SyndiKit + needs: [configure] + if: needs.configure.outputs.full-matrix == 'true' runs-on: ubuntu-latest - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} strategy: - fail-fast: false matrix: - swift-version: ["6.1"] - # Testing API 21+ (64-bit architectures) to avoid zlib linking issues on 32-bit ARM - # See: https://github.com/android/ndk/issues/1391 - api-level: [28, 33, 34] - + swift: + - version: "6.1" + - version: "6.2" + - version: "6.3" + android-api-level: [28, 33, 36] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Free Disk Space run: | @@ -395,47 +316,44 @@ jobs: sudo apt-get clean sudo docker image prune --all --force - - name: Build and Test - uses: brightdigit/swift-build@v1.5.0 + - id: build + uses: brightdigit/swift-build@v1 with: - scheme: ${{ env.PACKAGE_NAME }} type: android - android-swift-version: ${{ matrix.swift-version }} - android-api-level: ${{ matrix.api-level }} + android-swift-version: ${{ matrix.swift.version }} + android-api-level: ${{ matrix.android-api-level }} android-run-tests: true android-copy-files: Data/ - - - name: Process Coverage - uses: sersoft-gmbh/swift-coverage-action@v4 - - - name: Upload Coverage - uses: codecov/codecov-action@v4 + - name: Upload coverage to Codecov + if: steps.build.outputs.contains-code-coverage == 'true' + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} - flags: android,android-api-${{ matrix.api-level }},swift-${{ matrix.swift-version }} + flags: android,${{ matrix.swift.version }},${{ matrix.android-api-level }} + fail_ci_if_error: true lint: name: Linting - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + if: ${{ always() && !cancelled() && !failure() }} runs-on: ubuntu-latest - needs: [build-ubuntu, build-wasm, build-macos, build-windows, build-android] + needs: [build-ubuntu, build-macos, build-windows, build-android] env: MINT_PATH: .mint/lib MINT_LINK_PATH: .mint/bin steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Cache mint id: cache-mint - uses: actions/cache@v4 + uses: actions/cache@v4 env: cache-name: cache with: path: | .mint - Mint + Mint key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }} restore-keys: | - ${{ runner.os }}-mint- + ${{ runner.os }}-mint- - name: Install mint if: steps.cache-mint.outputs.cache-hit == '' run: | @@ -448,16 +366,15 @@ jobs: swift-source-compat-suite: name: Test Swift 6.x For Source Compatibility Suite runs-on: ubuntu-latest - if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} strategy: matrix: container: - swift:6.0 - swift:6.1 - swift:6.2 - - swiftlang/swift:nightly-6.3-noble + - swift:6.3 container: ${{ matrix.container }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Run Swift 6.x tests run: swift build --disable-sandbox --verbose --configuration release -Xswiftc -swift-version -Xswiftc 6 diff --git a/Package.resolved b/Package.resolved index cf882cd..cc03319 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "d89a86339208901efc12996ce5a8971f0709998201ec5816da51f5963a95f916", + "originHash" : "c95d6920cf861679fb4428d5d98394c4e9996bffb0d3918f023219cf78fba501", "pins" : [ { "identity" : "xmlcoder", "kind" : "remoteSourceControl", "location" : "https://github.com/CoreOffice/XMLCoder", "state" : { - "revision" : "5e1ada828d2618ecb79c974e03f79c8f4df90b71", - "version" : "0.18.0" + "revision" : "b2b5d72345bab9e1938a483cf862b498aeed3796", + "version" : "0.18.1" } } ], diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 12ebfd1..d037d3f 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -39,7 +39,8 @@ let package = Package( .target( name: "SyndiKit", dependencies: ["XMLCoder"], - swiftSettings: swift6Features + swiftSettings: swift6Features, + linkerSettings: [.linkedLibrary("z", .when(platforms: [.android]))] ), .target(