-
Notifications
You must be signed in to change notification settings - Fork 34
Add CI for example projects #37
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
base: main
Are you sure you want to change the base?
Changes from 19 commits
b9b0d7f
41f902a
040c718
0c20f0b
37bf3da
6466620
49da231
0fbc79f
e10dd0d
270fef1
63f4b89
7db51f6
eb07553
5b2f022
571da46
cfecb38
f8ab14d
9b4ba79
6a59d5f
e0258fa
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,211 @@ | ||
| name: ci | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| pull_request: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| build-examples: | ||
| name: Build ${{ matrix.os }} ${{ matrix.swift_version }} | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| #swift_version: ['nightly-main', '6.3'] | ||
|
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. commented-out nightly matrix is gonna rot if we forget about it (which... we will). either rip it out or promote it to a |
||
| swift_version: ['6.3'] | ||
| sdk_triple: ['aarch64-unknown-linux-android28'] | ||
| ndk_version: ['r27d'] | ||
| os: ['ubuntu-latest', 'macos-latest'] | ||
| runs-on: ${{ matrix.os }} | ||
| env: | ||
| SDK_TRIPLE: ${{ matrix.sdk_triple }} | ||
| NDK_VERSION: ${{ matrix.ndk_version }} | ||
| SWIFT_VERSION: ${{ matrix.swift_version }} | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
|
|
||
| - name: Set up JDK 25 | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: temurin | ||
| java-version: '25' | ||
|
|
||
| - name: Install swiftly | ||
| run: | | ||
| set -euxo pipefail | ||
| if [[ "${RUNNER_OS}" == "Linux" ]]; then | ||
| sudo apt-get -yq install curl jq gpg unzip libcurl4-openssl-dev | ||
| ARCH="$(uname -m)" | ||
| curl -L -O --retry 3 "https://download.swift.org/swiftly/linux/swiftly-${ARCH}.tar.gz" | ||
| tar -xzf "swiftly-${ARCH}.tar.gz" | ||
| ./swiftly init \ | ||
| --assume-yes \ | ||
| --skip-install \ | ||
| --no-modify-profile \ | ||
| --quiet-shell-followup | ||
| rm -f "swiftly-${ARCH}.tar.gz" swiftly | ||
| # The example projects' Gradle scripts look for swiftly under | ||
| # $HOME/.local/share/swiftly/bin, which is also where the official | ||
| # installer puts it. Add it to PATH for subsequent steps. | ||
| echo "$HOME/.local/share/swiftly/bin" >> "$GITHUB_PATH" | ||
| "$HOME/.local/share/swiftly/bin/swiftly" --version | ||
| elif [[ "${RUNNER_OS}" == "macOS" ]]; then | ||
| curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg && \ | ||
|
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. tiny style nit: you've got |
||
| installer -pkg swiftly.pkg -target CurrentUserHomeDirectory && \ | ||
| ~/.swiftly/bin/swiftly init --quiet-shell-followup && \ | ||
| . "${SWIFTLY_HOME_DIR:-$HOME/.swiftly}/env.sh" && \ | ||
| hash -r | ||
|
|
||
| echo "$HOME/.swiftly/bin" >> "$GITHUB_PATH" | ||
| "$HOME/.swiftly/bin/swiftly" --version | ||
| else | ||
| echo "Unknown OS: ${RUNNER_OS}" | ||
| exit 1 | ||
| fi | ||
|
|
||
|
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. nit: quoting on |
||
| - name: Install Android NDK | ||
|
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. no caching = every run re-downloads the NDK (~1GB) and the android swift SDK. that's a lot of bytes off download.swift.org and a couple of minutes off every CI run across both OSes. |
||
| run: | | ||
| set -euxo pipefail | ||
| OS="$(uname -s | tr '[A-Z]' '[a-z]')" | ||
| curl -L -o ndk.zip --retry 3 "https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-${OS}.zip" | ||
| unzip -q ndk.zip -d "$HOME" | ||
| rm ndk.zip | ||
| echo "ANDROID_NDK_HOME=$HOME/android-ndk-${NDK_VERSION}" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Install Android Swift SDK and matching host toolchain | ||
| # Looks up the Android Swift SDK URL and checksum from the swift.org | ||
| # install API and installs it via `swift sdk install`. | ||
| run: | | ||
| set -euxo pipefail | ||
| case "$SWIFT_VERSION" in | ||
| nightly-*) | ||
| nightly_version="${SWIFT_VERSION#nightly-}" | ||
| sdk_json=$(curl -fsSL "https://www.swift.org/api/v1/install/dev/${nightly_version}/android-sdk.json") | ||
| snapshot_tag=$(echo "$sdk_json" | jq -r '.[0].dir') | ||
| sdk_checksum=$(echo "$sdk_json" | jq -r '.[0].checksum') | ||
| if [ "$nightly_version" = "main" ]; then | ||
| branch="development" | ||
| else | ||
| branch="swift-${nightly_version}-branch" | ||
| fi | ||
| sdk_url="https://download.swift.org/${branch}/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" | ||
| ;; | ||
| *) | ||
| releases_json=$(curl -fsSL "https://www.swift.org/api/v1/install/releases.json") | ||
| # Pick the highest patch release whose name starts with the | ||
| # requested version (e.g. "6.3" -> "6.3.1" if it exists). | ||
| latest_version=$(echo "$releases_json" | jq -r --arg v "$SWIFT_VERSION" \ | ||
| '[.[] | select(.name | startswith($v))] | ||
| | sort_by(.name | split(".") | map(tonumber? // 0)) | ||
| | last | ||
| | .name') | ||
| if [ -z "$latest_version" ] || [ "$latest_version" = "null" ]; then | ||
| echo "Error: no Swift release matching '$SWIFT_VERSION' found in releases.json" >&2 | ||
| exit 1 | ||
| fi | ||
| sdk_checksum=$(echo "$releases_json" | jq -r --arg v "$latest_version" \ | ||
| '.[] | select(.name == $v) | .platforms[] | select(.platform == "android-sdk") | .checksum') | ||
| snapshot_tag="swift-${latest_version}-RELEASE" | ||
| sdk_url="https://download.swift.org/swift-${latest_version}-release/android-sdk/${snapshot_tag}/${snapshot_tag}_android.artifactbundle.tar.gz" | ||
| ;; | ||
| esac | ||
|
|
||
| swift_install=${snapshot_tag} | ||
| # trim leading "swift-" and trailing "-RELEASE" | ||
| swift_install=${swift_install#swift-} | ||
| swift_install=${swift_install/-RELEASE/} | ||
|
|
||
| echo "Installing Android Swift SDK and host toolchain" | ||
| echo " tag: $swift_install" | ||
| echo " url: $sdk_url" | ||
| echo " checksum: $sdk_checksum" | ||
| swiftly install "${swift_install}" | ||
| swift sdk install "$sdk_url" --checksum "$sdk_checksum" | ||
| swift sdk list | ||
|
|
||
| # set environment variables used by swift-android.gradle.kts | ||
| echo "SWIFT_VERSION=${swift_install}" >> $GITHUB_ENV | ||
|
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. worth a one-liner comment here explaining that you're deliberately overwriting the matrix |
||
| echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag#swift-}_android" >> $GITHUB_ENV | ||
|
|
||
| - name: Configure Swift Android SDK | ||
| run: | | ||
| set -euo pipefail | ||
| cd $HOME/.swiftpm/swift-sdks/*android*.artifactbundle || cd $HOME/.config/swiftpm/swift-sdks/*android*.artifactbundle || cd $HOME/Library/org.swift.swiftpm/swift-sdks/*android*.artifactbundle | ||
|
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. this safer pattern would be something like: shopt -s nullglob
candidates=(
"$HOME"/.swiftpm/swift-sdks/*android*.artifactbundle
"$HOME"/.config/swiftpm/swift-sdks/*android*.artifactbundle
"$HOME"/Library/org.swift.swiftpm/swift-sdks/*android*.artifactbundle
)
[[ ${#candidates[@]} -gt 0 ]] || { echo "no android SDK bundle found"; exit 1; }
cd "${candidates[0]}"or just parse |
||
| # Link the SDK against the NDK we installed in the previous step. | ||
| # Someday we might not need this script, so gracefully skip it | ||
| # if it does not exist. | ||
| if [[ -x "./swift-android/scripts/setup-android-sdk.sh" ]]; then | ||
| "./swift-android/scripts/setup-android-sdk.sh" | ||
| fi | ||
|
|
||
| - name: Publish swift-java packages to local Maven | ||
| # The hashing-lib, weather-lib, and hello-cpp-swift/swift-lib modules | ||
| # depend on org.swift.swiftkit:swiftkit-core:1.0-SNAPSHOT, which is not | ||
| # published to a public Maven repo. The hashing-lib README documents | ||
| # publishing it to mavenLocal from the swift-java checkout that | ||
| # SwiftPM resolves into .build/checkouts/swift-java. | ||
| working-directory: hello-swift-java/hashing-lib | ||
| run: | | ||
| set -euxo pipefail | ||
| swift package resolve | ||
| ./.build/checkouts/swift-java/gradlew \ | ||
| --project-dir .build/checkouts/swift-java \ | ||
| :SwiftKitCore:publishToMavenLocal | ||
|
|
||
| - name: Build hello-swift-raw-jni APK | ||
| run: ./gradlew :hello-swift-raw-jni:assembleDebug --stacktrace | ||
|
|
||
| - name: Build hello-swift-raw-jni-callback APK | ||
| run: ./gradlew :hello-swift-raw-jni-callback:assembleDebug --stacktrace | ||
|
|
||
| - name: Build hello-swift-raw-jni-library | ||
| run: ./gradlew :hello-swift-raw-jni-library:assembleDebug --stacktrace | ||
|
|
||
| - name: Build native-activity APK | ||
| run: ./gradlew :native-activity:assembleDebug --stacktrace | ||
|
|
||
| - name: Build hello-swift-java APK | ||
| run: ./gradlew :hello-swift-java-hashing-app:assembleDebug --stacktrace | ||
|
|
||
| - name: Build swift-java-weather-app APK | ||
| run: ./gradlew :swift-java-weather-app-weather-app:assembleDebug --stacktrace | ||
|
|
||
| - name: Build hello-cpp-swift APK | ||
| run: | | ||
| cd hello-cpp-swift/cpp-lib | ||
|
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. micro-nit: |
||
| ./build-android-static.sh | ||
| cd - | ||
| ./gradlew :hello-cpp-swift:app:assembleDebug --stacktrace | ||
|
|
||
| - name: Summarize APK artifacts | ||
| if: always() | ||
| run: | | ||
| echo "## APK Artifacts (${{ matrix.os }} / swift:${{ matrix.swift_version }} / ${{ matrix.sdk_triple }})" >> "$GITHUB_STEP_SUMMARY" | ||
| echo "" >> "$GITHUB_STEP_SUMMARY" | ||
| echo "| Project | APK | Size |" >> "$GITHUB_STEP_SUMMARY" | ||
| echo "|---------|-----|------|" >> "$GITHUB_STEP_SUMMARY" | ||
| found=0 | ||
| while IFS= read -r apk; do | ||
| found=1 | ||
| # Derive a human-readable project name from the path | ||
| project=$(echo "$apk" | sed -E 's#^\./##; s#/build/outputs/.*##') | ||
| name=$(basename "$apk") | ||
| # Human-readable size (du -h works on both Linux and macOS) | ||
| size=$(du -h "$apk" | cut -f1 | tr -d '[:space:]') | ||
| echo "| \`$project\` | \`$name\` | $size |" >> "$GITHUB_STEP_SUMMARY" | ||
| done < <(find . -path '*/build/outputs/apk/*.apk' -type f | sort) | ||
| if [ "$found" -eq 0 ]; then | ||
| echo "| _(none)_ | — | — |" >> "$GITHUB_STEP_SUMMARY" | ||
| fi | ||
|
|
||
| - name: Upload APK artifacts | ||
| if: always() | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: apks-${{ matrix.os }}-${{ matrix.swift_version }}-${{ matrix.sdk_triple }}-${{ matrix.ndk_version }} | ||
| path: '**/build/outputs/apk/**/*.apk' | ||
| if-no-files-found: warn | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,8 +99,15 @@ def swiftRuntimeLibs = [ | |
| "swiftSynchronization" | ||
| ] | ||
|
|
||
| def sdkName = "swift-6.3-RELEASE_android.artifactbundle" | ||
| def swiftVersion = "6.3" | ||
| // Swift toolchain version passed to swiftly (e.g. "6.3", "main-snapshot"). | ||
| // Can be overridden via the SWIFT_VERSION environment variable, which is | ||
| // useful for CI matrices that test multiple toolchains. | ||
| def swiftVersion = System.getenv("SWIFT_VERSION") ?: "6.3" | ||
|
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. not your fault, but worth calling out: this exact 6-line block is now duplicated across three |
||
| // Android Swift SDK artifactbundle suffix. Substituted into the bundle | ||
| // directory name as "swift-${androidSdkVersion}.artifactbundle". Can be | ||
| // overridden via the SWIFT_ANDROID_SDK_VERSION environment variable. | ||
| def androidSdkVersion = System.getenv("SWIFT_ANDROID_SDK_VERSION") ?: "${swiftVersion}-RELEASE_android" | ||
| def sdkName = "swift-${androidSdkVersion}.artifactbundle" | ||
| def minSdk = android.defaultConfig.minSdkVersion.apiLevel | ||
| /** | ||
| * Android ABIs and their Swift triple mappings | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,8 +14,14 @@ data class SwiftConfig( | |
| var releaseExtraBuildFlags: List<String> = emptyList(), | ||
| var swiftlyPath: String? = null, // Optional custom swiftly path | ||
| var swiftSDKPath: String? = null, // Optional custom Swift SDK path | ||
| var swiftVersion: String = "6.3", // Swift version | ||
| var androidSdkVersion: String = "6.3-RELEASE_android" // SDK version | ||
| // Swift toolchain version passed to swiftly (e.g. "6.3", "main-snapshot"). | ||
| // Can be overridden via the SWIFT_VERSION environment variable, which is | ||
| // useful for CI matrices that test multiple toolchains. | ||
| var swiftVersion: String = System.getenv("SWIFT_VERSION")?.takeIf { it.isNotEmpty() } ?: "6.3", | ||
|
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. subtle behavior mismatch with the three groovy files: here you do |
||
| // Android Swift SDK artifactbundle suffix. Substituted into the bundle | ||
| // directory name as "swift-${androidSdkVersion}.artifactbundle". Can be | ||
| // overridden via the SWIFT_ANDROID_SDK_VERSION environment variable. | ||
| var androidSdkVersion: String = System.getenv("SWIFT_ANDROID_SDK_VERSION")?.takeIf { it.isNotEmpty() } ?: "${swiftVersion}-RELEASE_android" | ||
| ) | ||
|
|
||
| // Architecture definitions | ||
|
|
@@ -296,4 +302,4 @@ project.afterEvaluate { | |
| } else { | ||
| throw GradleException("Android extension not found. Make sure to apply this script after the Android plugin.") | ||
| } | ||
| } | ||
| } | ||
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.
no
concurrency:group means rapid pushes to a PR branch queue up N redundant matrix runs. usual pattern for this repo would be something like:at the top of the workflow