Feb 7, 2025

swift version + github actions (update)

Github Actions is great for automating coding tasks and the Ubuntu runners come with a ton of preinstalled tools. At the time of this writing the ubuntu-latest runner is version 24.04.

While tons of preinstalled tools is super handy, what if the version of the tool is incompatible with the code you are working with? This is the scenario I ran in to when attempting to build a Swift project that depends on an outdated package which fails to build with Swift 6.

solution

While there are a couple of actions that seek to solve this problem, they don't strike me as having widespread use or being kept current, so I don't want to rely on those. That is just me though, maybe they are actually viable options.

Instead, I decided to use the official Swift toolchain manager Swiftly. This is a relatively new project, but I like that it is sponsored by the SSWG. It should be noted that it does not officially support Ubuntu 24.04 at the moment, but I'm sure that will change.

!! Important Note:
The below solution (for version 0.3.0) has been deprecated and fails the install.
An update for installing version 1.0 is provided below.

So, here's the documented install command:

curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash

Easy enough but after executing that, there is a series of confirmation questions, so this not good for a headless environment like Github Actions. The readme does not mention it but, this is a flag that can be passed to the script that will help, --disable-confirmation.

But how to pass that flag on execution of the script? Well I didn't know so I asked AI. Here's how it is done:

curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash -s -- --disable-confirmation

And the helpful AI explanation:

Explanation:
	•	-s tells bash to read from standard input (the script from curl).
	•	-- separates bash options from script arguments.
	•	--disable-confirmation is passed as a flag to the script.

Fantastic! Now with that we can update the Github Action config file to get the desired version of Swift on the runner:

name: Swift

on:
  push:
    branches:
    - main

jobs:
  gh-pages:
    runs-on: ubuntu-22.04
    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Setup Swift
      run: |
        curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash -s -- --disable-confirmation
        swiftly install 5.10.1
        swiftly use 5.10.1

    - name: Build Swift
      run: swift build

Boom, we're back in business.

update 4.11.25

Swiftly recently released version 1.0 and the above install method using a shell script has been deprecated. Given that, I dug in to figure out how to install 1.0.

installing 1.0

The recommended install command is found on swift.org:

curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \
tar zxf swiftly-$(uname -m).tar.gz && \
./swiftly init --quiet-shell-followup && \
. ~/.local/share/swiftly/env.sh && \
hash -r

This will work great for an interactive login session, but I found that PATH isn't set up the same way as it was pre-1.0 and ran in to issues in subsequent steps. Looking at the swiftly source, I see that the swift install path is set when the shell profile is loaded.

Unfortunately Github Actions runs in a non-interactive shell so the path is not set up automatically and swift cannot be found in subsequent steps. This can be resolved by sourcing env.sh with . ~/.local/share/swiftly/env.sh.

The problem here is each step in a workflow runs in its own shell session, sourcing env.sh is only good for the current step. It is a bummer to have to source every step where swift is executed.

Here I can leverage $GITHUB_ENV. GitHub Actions provides a special file called $GITHUB_ENV. If I write environment variables to that file, they’ll be available to all subsequent steps in the same job.

Here is the updated config file to install 1.0+ of Swift on a runner:

name: Swift

on:
  push:
    branches:
    - main

jobs:
  gh-pages:
    runs-on: ubuntu-22.04
    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Install Dependencies
      run: sudo apt-get -y install libcurl4-openssl-dev pkg-config python3-lldb-13

    - name: Install Swiftly
      run: |
        curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \
        tar zxf swiftly-$(uname -m).tar.gz && \
        ./swiftly init --skip-install --assume-yes

        . ~/.local/share/swiftly/env.sh
        echo "PATH=$PATH" >> $GITHUB_ENV

    - name: Install Swift
      run: |
        swiftly install 5.10.1

    - name: Build Swift
      run: |
        swift --version
        swift build

A couple things to point out:

  • Dependencies are now being installed with Install Dependencies. This wasn't necessary pre-1.0
  • By default Swiftly now installs the latest version of Swift. This can be disabled with --skip-install
  • The --disable-confirmation flag has been renamed to --assume-yes

1.0 thoughts

So far Swiftly 1.0 appears to stable and feature packed. The install method is a bit more tedious than before, but I like that some of the set up is done with the swiftly executable (swiftly init) rather than a shell script. Further, I appreciate that there is now complete documentation.