Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/actions/setup-tools/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Setup mise tools
description: >-
Restore (or build + save) the mise tool cache and put the binaries on PATH.
Implemented as a composite action so the cache scope is the caller job's
scope — reusable workflows scope caches separately, which silently breaks
hand-off between a setup job and a consumer lint job.

runs:
using: composite
steps:
- name: Cache mise tools
id: mise-cache
uses: actions/cache@v4
with:
path: ~/.local/share/mise/installs
key: mise-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('mise.toml') }}
restore-keys: |
mise-v2-${{ runner.os }}-${{ runner.arch }}-
- name: Install mise tools (cache miss)
if: steps.mise-cache.outputs.cache-hit != 'true'
uses: jdx/mise-action@v4
with:
cache: false
- name: Configure PATH for cached mise tools
if: steps.mise-cache.outputs.cache-hit == 'true'
uses: jdx/mise-action@v4
with:
install: false
cache: false
72 changes: 50 additions & 22 deletions .github/workflows/SyntaxKit.yml
Comment thread
leogdion marked this conversation as resolved.
Comment thread
leogdion marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,43 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' || !contains(github.event.head_commit.message, 'ci skip') }}
outputs:
full-matrix: ${{ steps.set-matrix.outputs.full-matrix }}
ubuntu-os: ${{ steps.set-matrix.outputs.ubuntu-os }}
ubuntu-swift: ${{ steps.set-matrix.outputs.ubuntu-swift }}
ubuntu-type: ${{ steps.set-matrix.outputs.ubuntu-type }}
full-matrix: ${{ steps.check.outputs.full }}
ubuntu-os: ${{ steps.matrix.outputs.ubuntu-os }}
ubuntu-swift: ${{ steps.matrix.outputs.ubuntu-swift }}
ubuntu-type: ${{ steps.matrix.outputs.ubuntu-type }}
steps:
- name: Determine build matrix
id: set-matrix
- id: check
name: Determine matrix scope
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" || "${{ github.event_name }}" == "pull_request" ]]; then
echo "full-matrix=true" >> "$GITHUB_OUTPUT"
FULL=false
REF="${{ github.ref }}"
EVENT="${{ github.event_name }}"
BASE_REF="${{ github.base_ref }}"

# Full matrix on main
if [[ "$REF" == "refs/heads/main" ]]; then
FULL=true
# Full matrix on semver branches (v1.0.0, 1.2.3-alpha.1, etc.)
elif [[ "$REF" =~ ^refs/heads/v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then
FULL=true
# Full matrix on PRs targeting main or semver branches
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"
echo "Full matrix: $FULL (ref=$REF, event=$EVENT, base_ref=$BASE_REF)"

- id: matrix
name: Build matrix values
run: |
if [[ "${{ steps.check.outputs.full }}" == "true" ]]; then
echo 'ubuntu-os=["noble","jammy"]' >> "$GITHUB_OUTPUT"
echo 'ubuntu-swift=[{"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"
Expand Down Expand Up @@ -86,6 +108,9 @@ jobs:
run: |
apt-get update -q
apt-get install -y curl
- name: Install coverage.py (silences codecov-cli probe warning)
if: steps.build.outputs.contains-code-coverage == 'true'
run: pip3 install --quiet --user coverage 2>/dev/null || true
- uses: sersoft-gmbh/swift-coverage-action@v5
id: coverage-files
if: steps.build.outputs.contains-code-coverage == 'true'
Expand Down Expand Up @@ -151,7 +176,7 @@ jobs:
include:
# SPM Build — no platform type; matrix.type evaluates to '' by design
- runs-on: macos-26
xcode: "/Applications/Xcode_26.4.app"
xcode: "/Applications/Xcode_26.5.app"

steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -202,38 +227,38 @@ jobs:
# macOS Build
- type: macos
runs-on: macos-26
xcode: "/Applications/Xcode_26.4.app"
xcode: "/Applications/Xcode_26.5.app"

# iOS Build Matrix
- type: ios
runs-on: macos-26
xcode: "/Applications/Xcode_26.4.app"
xcode: "/Applications/Xcode_26.5.app"
deviceName: "iPhone 17 Pro"
osVersion: "26.4"
osVersion: "26.5"
download-platform: true

# watchOS Build Matrix
- type: watchos
runs-on: macos-26
xcode: "/Applications/Xcode_26.4.app"
xcode: "/Applications/Xcode_26.5.app"
deviceName: "Apple Watch Ultra 3 (49mm)"
osVersion: "26.4"
osVersion: "26.5"
download-platform: true

# tvOS Build Matrix
- type: tvos
runs-on: macos-26
xcode: "/Applications/Xcode_26.4.app"
xcode: "/Applications/Xcode_26.5.app"
deviceName: "Apple TV"
osVersion: "26.4"
osVersion: "26.5"
download-platform: true

# visionOS Build Matrix
- type: visionos
runs-on: macos-26
xcode: "/Applications/Xcode_26.4.app"
xcode: "/Applications/Xcode_26.5.app"
deviceName: "Apple Vision Pro"
osVersion: "26.4"
osVersion: "26.5"
download-platform: true

steps:
Expand Down Expand Up @@ -310,11 +335,14 @@ jobs:
if: ${{ !cancelled() && !failure() && (github.event_name == 'pull_request' || !contains(github.event.head_commit.message, 'ci skip')) }}
runs-on: ubuntu-latest
needs: [build-ubuntu, build-macos, build-windows, build-macos-full, build-android]
# Serialize lint runs across workflows so a cold cache on a mise.toml
# bump only triggers one rebuild, not a race.
concurrency:
group: lint-tools-${{ github.head_ref || github.ref }}
cancel-in-progress: false
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v4
with:
cache: true
- uses: ./.github/actions/setup-tools
- name: Lint
run: ./Scripts/lint.sh

Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/check-unsafe-flags.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Check for unsafeFlags

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
dump-package-check:
name: Dump Swift package (authoritative) and scan JSON
runs-on: ubuntu-latest
container:
image: swift:latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install jq
run: |
apt-get update && apt-get install -y jq

- name: Dump package JSON and check for unsafeFlags
shell: bash
run: |
set -euo pipefail
# Compute unsafeFlags array directly from the dump (don't store the full dump variable)
unsafe_flags=$(swift package dump-package | jq -c '[.. | objects | .unsafeFlags? // empty]')
# Check array length to decide failure
if [ "$(echo "$unsafe_flags" | jq 'length')" -gt 0 ]; then
echo "ERROR: unsafeFlags found in resolved package JSON:"
echo "$unsafe_flags" | jq '.' || true
echo "--- resolved package dump (first 200 lines) ---"
# Print a sample of the authoritative dump (re-run dump-package for the sample)
swift package dump-package | sed -n '1,200p' || true
exit 1
else
echo "No unsafeFlags in resolved package JSON."
fi
12 changes: 6 additions & 6 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ on:
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
# CodeQL Swift analysis requires macOS runners — Linux is not supported
# ("Swift analysis is only supported on macOS runner images"). Other languages
# can run on Linux, hence the conditional.
runs-on: ${{ (matrix.language == 'swift' && 'macos-26') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
Expand All @@ -60,9 +58,11 @@ jobs:
uses: actions/checkout@v6

- name: Setup Xcode
run: sudo xcode-select -s /Applications/Xcode_26.4.app/Contents/Developer
if: matrix.language == 'swift'
run: sudo xcode-select -s /Applications/Xcode_26.5.app/Contents/Developer

- name: Verify Swift Version
if: matrix.language == 'swift'
run: |
swift --version
swift package --version
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/swift-source-compat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Swift Source Compatibility

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

jobs:
swift-source-compat-suite:
name: Test Swift ${{ matrix.container }} For Source Compatibility Suite
runs-on: ubuntu-latest
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}

strategy:
fail-fast: false
matrix:
container:
- swift:6.0
- swift:6.1
Comment thread
leogdion marked this conversation as resolved.
- swift:6.2
- swift:6.3

container: ${{ matrix.container }}

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Test Swift 6.x For Source Compatibility
run: swift build --disable-sandbox --verbose --configuration release
6 changes: 0 additions & 6 deletions .mise.toml

This file was deleted.

10 changes: 5 additions & 5 deletions .swift-format
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NeverForceUnwrap" : true,
"NeverUseForceTry" : true,
"NeverUseImplicitlyUnwrappedOptionals" : true,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoAssignmentInExpressions" : true,
"NoBlockComments" : true,
Expand All @@ -56,13 +56,13 @@
"TypeNamesShouldBeCapitalized" : true,
"UseEarlyExits" : false,
"UseExplicitNilCheckInConditions" : true,
"UseLetInEveryBoundCaseVariable" : false,
"UseLetInEveryBoundCaseVariable" : true,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : true,
"UseSynthesizedInitializer" : true,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : true,
"ValidateDocumentationComments" : false
"ValidateDocumentationComments" : true
},
"spacesAroundRangeFormationOperators" : false,
"tabWidth" : 2,
Expand Down
13 changes: 12 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ opt_in_rules:
- contains_over_range_nil_comparison
- convenience_type
- discouraged_object_literal
- discouraged_optional_boolean
- empty_collection_literal
- empty_count
- empty_string
Expand Down Expand Up @@ -52,11 +53,11 @@ opt_in_rules:
- nslocalizedstring_require_bundle
- number_separator
- object_literal
- one_declaration_per_file
- operator_usage_whitespace
- optional_enum_case_matching
- overridden_super_call
- override_in_extension
- pattern_matching_keywords
- prefer_self_type_over_type_of_self
- prefer_zero_over_explicit_init
- private_action
Expand Down Expand Up @@ -114,6 +115,10 @@ type_name:
excluded:
- If
- Do
min_length: 3
max_length:
warning: 50
error: 60
excluded:
- DerivedData
- .build
Expand All @@ -138,3 +143,9 @@ disabled_rules:
- opening_brace
- optional_data_string_conversion
- todo
custom_rules:
no_unchecked_sendable:
name: "No Unchecked Sendable"
regex: '@unchecked\s+Sendable'
message: "Use proper Sendable conformance instead of @unchecked Sendable to maintain strict concurrency safety"
severity: error
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ let package = Package(
.product(name: "SwiftOperators", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax")
],
exclude: ["README.md"],
swiftSettings: swiftSettings
),
.target(
Expand Down
Loading