Add FreeBSD platform support #993
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Pull Request | |
| permissions: | |
| contents: read | |
| on: | |
| pull_request: | |
| types: [opened, reopened, synchronize] | |
| push: | |
| branches: [main, 'release/*'] | |
| jobs: | |
| soundness: | |
| name: Soundness | |
| uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main | |
| with: | |
| license_header_check_enabled: false | |
| license_header_check_project_name: "Swift.org" | |
| api_breakage_check_enabled: false | |
| docs_check_enabled: false | |
| format_check_enabled: false | |
| shell_check_enabled: false | |
| unacceptable_language_check_enabled: true | |
| freebsd-aarch64-tests: | |
| name: Test / FreeBSD aarch64 | |
| runs-on: ubuntu-latest | |
| if: ${{ github.repository == 'networkextension/swiftly' || github.repository == 'swiftlang/swiftly' }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Install cloudflared | |
| run: | | |
| curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null | |
| echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list | |
| sudo apt-get update && sudo apt-get install -y cloudflared | |
| - name: Set up SSH key and known hosts | |
| env: | |
| FREEBSD_SSH_KEY: ${{ secrets.FREEBSD_SSH_KEY }} | |
| FREEBSD_CF_HOSTNAME: ${{ secrets.FREEBSD_CF_HOSTNAME }} | |
| run: | | |
| mkdir -p "$HOME/.ssh" | |
| printf '%s\n' "$FREEBSD_SSH_KEY" > "$HOME/.ssh/freebsd_ci_key" | |
| chmod 600 "$HOME/.ssh/freebsd_ci_key" | |
| printf '%s ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFqpy2Vs6oX1K5khxWW7INHC8a6meSaSvNDVXpCSv1Gj\n' \ | |
| "$FREEBSD_CF_HOSTNAME" >> "$HOME/.ssh/known_hosts" | |
| chmod 600 "$HOME/.ssh/known_hosts" | |
| printf 'Host freebsd-ci\n HostName %s\n User swift\n IdentityFile %s/.ssh/freebsd_ci_key\n ProxyCommand cloudflared access tcp --hostname %%h\n' \ | |
| "$FREEBSD_CF_HOSTNAME" "$HOME" > "$HOME/.ssh/config" | |
| chmod 600 "$HOME/.ssh/config" | |
| - name: Sync source to board | |
| run: | | |
| ssh -F "$HOME/.ssh/config" freebsd-ci 'mkdir -p /home/swift/ci/swiftly' | |
| rsync -avz --delete \ | |
| --exclude='.build' --exclude='.git' \ | |
| -e "ssh -F $HOME/.ssh/config" \ | |
| . freebsd-ci:/home/swift/ci/swiftly/ | |
| - name: Build and Test on FreeBSD aarch64 | |
| run: | | |
| ssh -F "$HOME/.ssh/config" freebsd-ci /bin/sh << 'ENDSSH' | |
| set -e | |
| . "$HOME/swift632-env.sh" | |
| cd "$HOME/ci/swiftly" | |
| swift package resolve 2>&1 | |
| # CNIOBoringSSL: FreeBSD sys/time.h guards gettimeofday behind __XSI_VISIBLE, | |
| # which is 0 unless _XOPEN_SOURCE>=500. BoringSSL doesn't define it. | |
| # Inject _XOPEN_SOURCE 600 + sys/time.h unconditionally at line 1. | |
| # Also strip any prior v1 patch (2-line) before applying the new 5-line one. | |
| SSL_LIB=$(find .build/checkouts -path "*/CNIOBoringSSL*/ssl/ssl_lib.cc" 2>/dev/null | head -1) | |
| if [ -n "$SSL_LIB" ]; then | |
| grep -qF 'FreeBSD-gettimeofday-xsi' "$SSL_LIB" || { | |
| grep -q 'FreeBSD-gettimeofday' "$SSL_LIB" && sed -i '' '1,2d' "$SSL_LIB" | |
| awk 'NR==1{print "/* FreeBSD-gettimeofday-xsi */\n#ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 600\n#endif\n#include <sys/time.h>"}1' "$SSL_LIB" > /tmp/_ssl.cc | |
| mv /tmp/_ssl.cc "$SSL_LIB" | |
| echo "Patched $SSL_LIB" | |
| } | |
| fi | |
| # CNIOBoringSSL: getentropy in unistd.h is behind __BSD_VISIBLE on FreeBSD. | |
| # Forward-declare it directly so no feature macros are needed. | |
| GE=$(find .build/checkouts -path "*/CNIOBoringSSL*/crypto/rand/getentropy.cc" 2>/dev/null | head -1) | |
| if [ -n "$GE" ]; then | |
| grep -qF 'FreeBSD-getentropy-fix' "$GE" || { | |
| awk 'NR==1{print "/* FreeBSD-getentropy-fix */\n#if defined(__FreeBSD__)\nextern \"C\" int getentropy(void*, __SIZE_TYPE__);\n#endif"}1' "$GE" > /tmp/_ge.cc | |
| mv /tmp/_ge.cc "$GE" | |
| echo "Patched $GE" | |
| } | |
| fi | |
| # All NIO-style lock files: FreeBSD pthread types are opaque pointers like OpenBSD | |
| find .build/checkouts \( -name "Locks.swift" -o -name "NIOLock.swift" \) 2>/dev/null | while read LOCKS; do | |
| grep -qF "pthread" "$LOCKS" || continue | |
| grep -qF "os(OpenBSD) || os(FreeBSD)" "$LOCKS" || \ | |
| sed -i '' 's/os(OpenBSD)/os(OpenBSD) || os(FreeBSD)/g' "$LOCKS" | |
| grep -qF "pthread_rwlock_t?>" "$LOCKS" || \ | |
| sed -i '' 's/pthread_rwlock_t> =/pthread_rwlock_t?> =/' "$LOCKS" | |
| grep -qF "LockPrimitive = pthread_mutex_t?" "$LOCKS" || \ | |
| sed -i '' 's/typealias LockPrimitive = pthread_mutex_t$/typealias LockPrimitive = pthread_mutex_t?/' "$LOCKS" | |
| grep -qF "pthread_mutexattr_t(bitPattern:" "$LOCKS" || \ | |
| sed -i '' 's/var attr = pthread_mutexattr_t()/var attr: pthread_mutexattr_t? = pthread_mutexattr_t(bitPattern: 0)/' "$LOCKS" | |
| echo "Patched $LOCKS" | |
| done | |
| # swift-log Logging.swift: Glibc.stdout/stderr non-optional on FreeBSD (unlike Linux) | |
| LOGGING=$(find .build/checkouts -path "*/swift-log*/Logging.swift" 2>/dev/null | head -1) | |
| if [ -n "$LOGGING" ]; then | |
| grep -qF "Glibc.stdout!" "$LOGGING" && \ | |
| sed -i '' 's/Glibc\.stdout!/Glibc.stdout/g; s/Glibc\.stderr!/Glibc.stderr/g' "$LOGGING" && \ | |
| echo "Patched $LOGGING" | |
| fi | |
| # swift-subprocess Thread.swift: two FreeBSD fixes — | |
| # 1) MutexType/ConditionType need optional typealiases (opaque pthread types) | |
| # 2) pthread_t() has no default init on FreeBSD; use unsafeBitCast placeholder | |
| # (_subprocess_pthread_create takes _Nonnull ptr so must stay non-optional) | |
| SUBTHREAD=$(find .build/checkouts -path "*/swift-subprocess*/Thread.swift" 2>/dev/null | head -1) | |
| if [ -n "$SUBTHREAD" ]; then | |
| grep -qF "pthread_mutex_t?" "$SUBTHREAD" || { | |
| awk '/^private typealias MutexType = pthread_mutex_t$/{ | |
| print "#if os(FreeBSD) || os(OpenBSD)\nprivate typealias MutexType = pthread_mutex_t?\nprivate typealias ConditionType = pthread_cond_t?\n#else\n" $0; next} | |
| /^private typealias ConditionType = pthread_cond_t$/{print $0 "\n#endif"; next}1' \ | |
| "$SUBTHREAD" > /tmp/_th.swift | |
| mv /tmp/_th.swift "$SUBTHREAD" | |
| echo "Patched $SUBTHREAD (typealiases)" | |
| } | |
| grep -qF 'unsafeBitCast(0 as UInt' "$SUBTHREAD" || { | |
| awk '/^ var thread = pthread_t\(\)$/{ | |
| print "#if os(FreeBSD) || os(OpenBSD)" | |
| print " var thread: pthread_t = unsafeBitCast(0 as UInt, to: pthread_t.self)" | |
| print "#else" | |
| print $0 | |
| print "#endif" | |
| next}1' "$SUBTHREAD" > /tmp/_th.swift | |
| mv /tmp/_th.swift "$SUBTHREAD" | |
| echo "Patched $SUBTHREAD (pthread_t init)" | |
| } | |
| fi | |
| swift build 2>&1 | |
| swift test --filter SwiftlyTests 2>&1 | |
| ENDSSH | |
| timeout-minutes: 60 | |
| macos-tests-selfhosted: | |
| name: Test (Self Hosted) / macOS Tahoe ARM64 | |
| runs-on: [self-hosted, macos, tahoe, ARM64] | |
| if: ${{ github.repository == 'swiftlang/swiftly' }} | |
| strategy: | |
| fail-fast: false | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh --install-swiftly | |
| - name: Build and Test | |
| run: swift test | |
| timeout-minutes: 60 | |
| tests-selfhosted: | |
| name: Test (Self Hosted) / ${{ matrix.container }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| container: ["ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12", "fedora:39"] | |
| container: | |
| image: ${{ matrix.container }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh --install-swiftly | |
| - name: Build and Test | |
| # UBI 9 - See https://github.com/swiftlang/swift/issues/80908 | |
| # UBI 9 - See https://github.com/swiftlang/swift/issues/80909 | |
| run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swift build --build-tests; else swift test; fi' | |
| # Verify new platforms without a released Swiftly build | |
| tests-bootstrapped: | |
| name: Test (Bootstrapped) / ${{ matrix.container }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| container: ["swiftlang/swift:nightly-6.3-fedora41"] | |
| container: | |
| image: ${{ matrix.container }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh | |
| - name: Build and Test | |
| run: swift test | |
| releasebuildcheck: | |
| name: Release Build Check / Linux | |
| runs-on: ubuntu-latest | |
| container: | |
| image: "redhat/ubi9" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh --install-swiftly | |
| - name: Build Artifact | |
| run: swift run build-swiftly-release --test --skip "999.0.0" | |
| - name: Upload Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: swiftly-release-x86_64 | |
| path: .build/release/swiftly-*.tar.gz | |
| if-no-files-found: error | |
| retention-days: 1 | |
| - name: Upload Tests | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-swiftly-linux-x86_64 | |
| path: .build/debug/test-swiftly-linux-x86_64.tar.gz | |
| if-no-files-found: error | |
| retention-days: 1 | |
| releasebuildcheckmacos: | |
| name: Release Build Check / macOS | |
| runs-on: [self-hosted, macos, tahoe, ARM64] | |
| if: ${{ github.repository == 'swiftlang/swiftly' }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh --install-swiftly | |
| - name: Build Artifact | |
| run: swift run build-swiftly-release --test --skip "999.0.0" | |
| - name: Upload Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: swiftly-release-darwin | |
| path: .build/release/swiftly-*.pkg | |
| if-no-files-found: error | |
| retention-days: 1 | |
| - name: Upload Tests | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-swiftly-macos | |
| path: .build/release/test-swiftly-macos.tar.gz | |
| if-no-files-found: error | |
| retention-days: 1 | |
| releasetest: | |
| name: Test Release / ${{matrix.shell.pkg}} | |
| needs: releasebuildcheck | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shell: [ | |
| {"pkg": "bash", "bin": "/bin/bash"}, | |
| {"pkg": "zsh", "bin": "/bin/zsh"}, | |
| {"pkg": "fish", "bin": "/bin/fish"} | |
| ] | |
| container: | |
| image: "ubuntu:24.04" | |
| steps: | |
| - name: Prepare System | |
| run: apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install ca-certificates gpg tzdata ${{matrix.shell.pkg}} && chsh -s ${{matrix.shell.bin}} | |
| - name: Download Release | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: swiftly-release-x86_64 | |
| - name: Download Tests | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: test-swiftly-linux-x86_64 | |
| - name: Extract and Run Workflow Tests | |
| run: cp swiftly-*.tar.gz /root/swiftly.tar.gz && cp test-swiftly-*.tar.gz /root && cd /root && tar zxf test-swiftly-*.tar.gz && ./test-swiftly -y ./swiftly.tar.gz | |
| release-custom-install-test: | |
| name: Test Release - Custom Install Location | |
| needs: releasebuildcheck | |
| runs-on: ubuntu-latest | |
| container: | |
| image: "ubuntu:24.04" | |
| steps: | |
| - name: Prepare System | |
| run: apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install ca-certificates gpg tzdata | |
| - name: Download Release | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: swiftly-release-x86_64 | |
| - name: Download Tests | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: test-swiftly-linux-x86_64 | |
| - name: Extract and Run Workflow Tests | |
| run: cp swiftly-*.tar.gz /root/swiftly.tar.gz && cp test-swiftly-*.tar.gz /root && cd /root && tar zxf test-swiftly-*.tar.gz && ./test-swiftly -y --custom-location ./swiftly.tar.gz | |
| formatcheck: | |
| name: Format Check | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ubuntu:22.04 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh --install-swiftly | |
| - name: Check format | |
| run: swift run swiftformat --lint --dryrun . || (echo "Please run 'swift run swiftformat .' to format the source code."; exit 1) | |
| docscheck: | |
| name: Documentation Check | |
| runs-on: ubuntu-latest | |
| container: | |
| image: ubuntu:24.04 | |
| steps: | |
| - name: Install git | |
| run: apt-get update && apt-get -y install git | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Prepare the action | |
| run: ./scripts/prep-gh-action.sh --install-swiftly | |
| - name: Generate Swiftly CLI Reference and Check for Differences | |
| run: swift package plugin --allow-writing-to-package-directory generate-docs-reference && bash -c 'git config --global --add safe.directory $(pwd)' && git diff --exit-code Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md || (echo "The documentation hasn't been updated with the latest swiftly command-line reference. Please run 'swift package plugin generate-docs-reference' and commit/push the changes."; exit 1) | |
| - name: Generate Documentation Set | |
| run: swift package --allow-writing-to-directory .build/docs generate-documentation --target SwiftlyDocs --output-path .build/docs | |
| - name: Upload Documentation Artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: swiftly-docs | |
| path: .build/docs/** | |
| if-no-files-found: error | |
| retention-days: 1 |