-
Notifications
You must be signed in to change notification settings - Fork 38
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
Changes from 36 commits
b9b0d7f
41f902a
040c718
0c20f0b
37bf3da
6466620
49da231
0fbc79f
e10dd0d
270fef1
63f4b89
7db51f6
eb07553
5b2f022
571da46
cfecb38
f8ab14d
9b4ba79
6a59d5f
e0258fa
32dcffd
75f826b
6f7c435
1f48004
1e6c8ee
6e2724d
167291e
85f163a
8fa1aac
0ae7fcb
262aef8
c0471be
6796614
0b2a09c
98a34bf
ededcfb
7de27b9
874cb5b
a0f1132
c3a3862
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,246 @@ | ||
| name: ci | ||
|
|
||
| on: | ||
| push: | ||
| pull_request: | ||
| schedule: | ||
| - cron: '0 0 * * *' | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: ci-${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | ||
|
|
||
| jobs: | ||
| soundness: | ||
| name: Soundness | ||
| uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main | ||
| with: | ||
| license_header_check_project_name: "Swift.org" | ||
|
|
||
| build-examples: | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| swift_version: ["6.3", "nightly-main"] | ||
|
Member
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. nightly-6.3?
Contributor
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. That would expand the matrix from 2⁴ to 2⁵ entries, which is already pushing the limits given that GH actions can only have 5 concurrent macOS runners for public repos (and so it is already taking a very long time to run the CI). I'm not entirely opposed to adding it if you think that it is valuable, but I personally think that if the projects build with 27 and 30, then we are probably also good for the in-betweens.
Member
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. Your math is off: you currently have 8 jobs running on macOS, this would add 4 more, ie 12. Adding another NDK version on top of this would get us up to 18 jobs. Considering how rarely we update this repo, this would really only be run once daily, so I think the extra coverage is worth it. Once the LTS NDK 30 releases, we can drop all the older unsupported NDKs, and the nightly 6.3 snapshots too once they stop around the same time, in a month or two.
Contributor
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. OK, I've added nightly-6.3 and ndk29 (since 28 is no longer listed at https://developer.android.com/ndk/downloads/) to the mix. |
||
| ndk_version: ['r27d', 'r30-beta1'] | ||
|
Member
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. 28c would be good too, until 30 is out.
Contributor
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. Same as #37 (comment) |
||
| os: ['ubuntu-latest', 'macos-latest'] | ||
| configuration: ['Debug', 'Release'] | ||
| runs-on: ${{ matrix.os }} | ||
| env: | ||
| 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 update | ||
| 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 | ||
| 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 | ||
|
|
||
|
marcprux marked this conversation as resolved.
|
||
| - name: Cache Android NDK | ||
| id: cache-ndk | ||
| uses: actions/cache@v5 | ||
| with: | ||
| path: ~/android-ndk-${{ matrix.ndk_version }} | ||
| key: android-ndk-${{ runner.os }}-${{ runner.arch }}-${{ matrix.ndk_version }} | ||
|
|
||
| - name: Install Android NDK | ||
|
marcprux marked this conversation as resolved.
|
||
| if: steps.cache-ndk.outputs.cache-hit != 'true' | ||
| 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 | ||
|
|
||
| - name: Set ANDROID_NDK_HOME | ||
| run: 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 | ||
|
|
||
| # Override the matrix-supplied SWIFT_VERSION (e.g. "6.3") with the | ||
| # resolved patch version (e.g. "6.3.1") so the gradle scripts pick up | ||
| # the actual artifactbundle directory name produced by `swift sdk | ||
| # install`. SWIFT_ANDROID_SDK_VERSION pins the bundle suffix for the | ||
| # same reason. | ||
| echo "SWIFT_VERSION=${swift_install}" >> "$GITHUB_ENV" | ||
| echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag#swift-}_android" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Configure Swift Android SDK | ||
| run: | | ||
| set -euo pipefail | ||
| # Locate the installed Android SDK artifactbundle. Its parent | ||
| # directory varies by OS / swiftpm version, so try the known | ||
| # candidates and pick the first one that actually matches. | ||
| 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 | ||
| ) | ||
| if [[ ${#candidates[@]} -eq 0 ]]; then | ||
| echo "No android SDK artifactbundle found in any known location" >&2 | ||
| exit 1 | ||
| fi | ||
| cd "${candidates[0]}" | ||
| # 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:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Build hello-swift-raw-jni-callback APK | ||
| run: ./gradlew :hello-swift-raw-jni-callback:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Build hello-swift-raw-jni-library | ||
| run: ./gradlew :hello-swift-raw-jni-library:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Build native-activity APK | ||
| run: ./gradlew :native-activity:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Build hello-swift-java APK | ||
| run: ./gradlew :hello-swift-java-hashing-app:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Build swift-java-weather-app APK | ||
| run: ./gradlew :swift-java-weather-app-weather-app:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Build hello-cpp-swift cpp-lib | ||
| working-directory: hello-cpp-swift/cpp-lib | ||
| run: ./build-android-static.sh | ||
|
|
||
| - name: Build hello-cpp-swift APK | ||
| run: ./gradlew :hello-cpp-swift:app:assemble${{ matrix.configuration }} --stacktrace | ||
|
|
||
| - name: Summarize APK artifacts | ||
| if: always() | ||
| run: | | ||
| echo "## APK Artifacts (os:${{ matrix.os }} / swift:${{ matrix.swift_version }} / ndk:${{ matrix.ndk_version }}) / configuration:${{ matrix.configuration }}" >> "$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.ndk_version }} | ||
| path: '**/build/outputs/apk/**/*.apk' | ||
| if-no-files-found: warn | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| .gitignore | ||
| **/.gitignore | ||
| .licenseignore | ||
| .unacceptablelanguageignore | ||
| .swiftformatignore | ||
| .gitattributes | ||
| .mailfilter | ||
| .mailmap | ||
| .spi.yml | ||
| .swift-format | ||
| .editorconfig | ||
| .github/* | ||
| .idea/icon.svg | ||
| gradle/libs.versions.toml | ||
| **/gradle-wrapper.properties | ||
| **/gradle.properties | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| **/proguard-rules.pro | ||
| *.xml | ||
| *.webp | ||
| *.png | ||
| *.config | ||
| *.jar | ||
| *.md | ||
| *.txt | ||
| *.yml | ||
| *.yaml | ||
| *.json | ||
| Package.swift | ||
| **/Package.swift | ||
| Package@-*.swift | ||
| **/Package@-*.swift | ||
| Package.resolved | ||
| **/Package.resolved | ||
| Makefile | ||
| *.modulemap | ||
| **/*.modulemap | ||
| **/*.docc/* | ||
| *.xcprivacy | ||
| **/*.xcprivacy | ||
| *.symlink | ||
| **/*.symlink | ||
| Dockerfile | ||
| **/Dockerfile | ||
| Snippets/* | ||
| dev/git.commit.template | ||
| *.crt | ||
| **/*.crt | ||
| *.pem | ||
| **/*.pem | ||
| *.der | ||
| **/*.der | ||
| native-app-glue/Sources/AndroidNativeAppGlue/android_native_app_glue.c | ||
| native-app-glue/Sources/AndroidNativeAppGlue/include/android_native_app_glue.h |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| version: 1 | ||
| external_links: | ||
| documentation: "https://docs.swift.org/android/documentation/android" | ||
| builder: | ||
| configs: | ||
| - documentation_targets: [SwiftAndroid] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "rules": { | ||
| "AlwaysUseLowerCamelCase": false | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,15 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This source file is part of the Swift.org open source project | ||
| // | ||
| // Copyright (c) 2026 Apple Inc. and the Swift.org project authors | ||
| // Licensed under Apache License v2.0 | ||
| // | ||
| // See LICENSE.txt for license information | ||
| // See CONTRIBUTORS.txt for the list of Swift.org project authors | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // This file is included so SwiftPM considers the target to be a Swift target. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,20 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This source file is part of the Swift.org open source project | ||
| // | ||
| // Copyright (c) 2026 Apple Inc. and the Swift.org project authors | ||
| // Licensed under Apache License v2.0 | ||
| // | ||
| // See LICENSE.txt for license information | ||
| // See CONTRIBUTORS.txt for the list of Swift.org project authors | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // Top-level build file where you can add configuration options common to all sub-projects/modules. | ||
| plugins { | ||
| alias(libs.plugins.android.application) apply false | ||
| alias(libs.plugins.kotlin.android) apply false | ||
| alias(libs.plugins.android.library) apply false | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.