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
3 changes: 0 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
"image": "mcr.microsoft.com/devcontainers/universal:2",
"customizations": {
"vscode": {
"settings": {
"jest.runMode": "on-demand"
},
"extensions": [
"eamodio.gitlens",
"ms-vscode.vscode-typescript-next",
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ jobs:
uses: ./
with:
check-latest: ${{ needs.ci.outputs.check_latest }}
sdks: static-sdk
dry-run: true

- name: Verify Swift version
Expand Down Expand Up @@ -381,7 +382,8 @@ jobs:
with: {
'swift-version': 'latest',
'check-latest': '${{ needs.ci.outputs.check_latest }}',
'visual-studio-components': '${{ matrix.os }}'.includes('arm') ? 'Microsoft.VisualStudio.Component.Windows11SDK.22000' : ''
'visual-studio-components': '${{ matrix.os }}'.includes('arm') ? 'Microsoft.VisualStudio.Component.Windows11SDK.22000' : '',
'sdks': '${{ runner.os }}' != 'Windows' ? 'static-sdk' : ''
}
}
]
Expand Down Expand Up @@ -414,6 +416,10 @@ jobs:
if: runner.os == 'Windows'
run: which link | grep "Microsoft Visual Studio" || exit 1

- name: Verify Swift SDKs
if: runner.os != 'Windows'
run: swift sdk list | grep ${{ steps.setup-swift.outputs.swift-version }}-RELEASE_static-linux || exit 1

- name: Test Swift package
run: |
swift package init --type library --name SetupLib
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"jest.jestCommandLine": "npm run test -- ",
"jest.runMode": "on-demand",
"files.exclude": {
"**/node_modules": true
},
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This action supports the following functionalities:

- Works on Linux, macOS and Windows across all architectures.
- Supports [installing latest major/minor/patch](#specifying-version).
- Supports installing official Swift SDKs from cross platform developments.
- Provides snapshots as soon as published in `swift.org`.
- Verifies toolchain snapshots before installation (`gpg` for Linux and Windows, `pkgutil` for macOS) .
- Allows development snapshots by enabling `development` flag and optional version.
Expand Down Expand Up @@ -43,6 +44,14 @@ Or use the latest development snapshots by enabling the `development` flag:
development: true
```

Install additional SDKs as part of toolchain setup, i.e. install static Linux SDK:

```yml
- uses: SwiftyLab/setup-swift@latest
with:
sdks: static-sdk
```

After the environment is configured you can run swift and xcode commands using the standard [`run`](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsrun) step:

```yml
Expand Down
2 changes: 1 addition & 1 deletion __tests__/installer/linux.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ describe('linux toolchain installation verification', () => {
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue(cached)
jest.spyOn(exec, 'exec').mockResolvedValue(0)
const cacheSpy = jest.spyOn(cache, 'saveCache')
const installer = await Platform.install(cVer)
const {installer} = await Platform.install(cVer)
expect(cacheSpy).not.toHaveBeenCalled()
expect(installer.data.baseUrl?.href).toBe(path.posix.dirname(toolchainUrl))
expect(installer.data.preventCaching).toBe(true)
Expand Down
111 changes: 109 additions & 2 deletions __tests__/installer/windows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,115 @@ describe('windows toolchain installation verification', () => {
const installer = new WindowsToolchainInstaller(toolchain)
const installation = path.resolve('tool', 'installed', 'path')
jest.spyOn(VisualStudio, 'setup').mockResolvedValue(visualStudio)
jest.spyOn(fs, 'access').mockRejectedValueOnce(new Error())
jest.spyOn(fs, 'access').mockResolvedValue()
jest
.spyOn(fs, 'access')
.mockRejectedValueOnce(new Error())
.mockResolvedValue()
jest.spyOn(fs, 'copyFile').mockResolvedValue()
jest.spyOn(exec, 'exec').mockResolvedValue(0)
jest.spyOn(exec, 'getExecOutput').mockResolvedValue({
exitCode: 0,
stdout: vsEnvs.join(os.EOL),
stderr: ''
})
const toolPath = path.join(
installation,
'Developer',
'Toolchains',
'unknown-Asserts-development.xctoolchain'
)
const sdkroot = path.join(
installation,
'Developer',
'Platforms',
'Windows.platform',
'Developer',
'SDKs',
'Windows.sdk'
)
const swiftLibs = path.join(sdkroot, 'usr', 'lib', 'swift')
const swiftPath = path.join(toolPath, 'usr', 'bin')
const swiftDev = path.join(installation, 'Swift-development', 'bin')
const icu67 = path.join(installation, 'icu-67', 'usr', 'bin')
await installer['add'](installation, 'x86_64')
expect(process.env.PATH?.includes(swiftPath)).toBeTruthy()
expect(process.env.PATH?.includes(swiftDev)).toBeTruthy()
expect(process.env.PATH?.includes(icu67)).toBeTruthy()
expect(process.env.SDKROOT).toBe(sdkroot)
expect(process.env.SWIFTFLAGS).toContain(`-sdk ${sdkroot}`)
expect(process.env.SWIFTFLAGS).toContain(`-I ${swiftLibs}`)
expect(process.env.SWIFTFLAGS).toContain(
`-L ${path.join(swiftLibs, 'windows')}`
)
})

it('tests add to PATH with fallback SDK copying', async () => {
const installer = new WindowsToolchainInstaller(toolchain)
const installation = path.resolve('tool', 'installed', 'path')
jest.spyOn(VisualStudio, 'setup').mockResolvedValue(visualStudio)
jest
.spyOn(fs, 'access')
.mockRejectedValueOnce(new Error())
.mockImplementation(async p => {
if (typeof p === 'string' && p.endsWith('vcruntime.modulemap')) {
return Promise.reject(new Error())
}
return Promise.resolve()
})
jest.spyOn(fs, 'copyFile').mockResolvedValue()
jest.spyOn(exec, 'exec').mockResolvedValue(0)
jest.spyOn(exec, 'getExecOutput').mockResolvedValue({
exitCode: 0,
stdout: vsEnvs.join(os.EOL),
stderr: ''
})
const toolPath = path.join(
installation,
'Developer',
'Toolchains',
'unknown-Asserts-development.xctoolchain'
)
const sdkroot = path.join(
installation,
'Developer',
'Platforms',
'Windows.platform',
'Developer',
'SDKs',
'Windows.sdk'
)
const swiftLibs = path.join(sdkroot, 'usr', 'lib', 'swift')
const swiftPath = path.join(toolPath, 'usr', 'bin')
const swiftDev = path.join(installation, 'Swift-development', 'bin')
const icu67 = path.join(installation, 'icu-67', 'usr', 'bin')
await installer['add'](installation, 'x86_64')
expect(process.env.PATH?.includes(swiftPath)).toBeTruthy()
expect(process.env.PATH?.includes(swiftDev)).toBeTruthy()
expect(process.env.PATH?.includes(icu67)).toBeTruthy()
expect(process.env.SDKROOT).toBe(sdkroot)
expect(process.env.SWIFTFLAGS).toContain(`-sdk ${sdkroot}`)
expect(process.env.SWIFTFLAGS).toContain(`-I ${swiftLibs}`)
expect(process.env.SWIFTFLAGS).toContain(
`-L ${path.join(swiftLibs, 'windows')}`
)
})

it('tests add to PATH without SDK copying', async () => {
const installer = new WindowsToolchainInstaller(toolchain)
const installation = path.resolve('tool', 'installed', 'path')
jest.spyOn(VisualStudio, 'setup').mockResolvedValue(visualStudio)
jest
.spyOn(fs, 'access')
.mockRejectedValueOnce(new Error())
.mockImplementation(async p => {
if (
typeof p === 'string' &&
(p.endsWith('ucrt.modulemap') || p.endsWith('winsdk.modulemap'))
) {
return Promise.reject(new Error())
}
return Promise.resolve()
})
jest.spyOn(fs, 'copyFile').mockResolvedValue()
jest.spyOn(exec, 'exec').mockResolvedValue(0)
jest.spyOn(exec, 'getExecOutput').mockResolvedValue({
Expand Down
44 changes: 42 additions & 2 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as core from '@actions/core'
import * as main from '../src/main'
import {Swiftorg} from '../src/swiftorg'
import {Platform} from '../src/platform'
import {LinuxToolchainInstaller} from '../src/installer'
import {SdkSupportedVersion} from '../src/version'
import {LinuxToolchainInstaller, SdkToolchainInstaller} from '../src/installer'

describe('setup-swift run validation', () => {
const swiftorgSpy = jest
Expand All @@ -23,11 +24,27 @@ describe('setup-swift run validation', () => {
branch: 'swift-5.8-release',
preventCaching: false
}
const sdkToolchains = [
{
name: 'Static SDK',
date: new Date('2023-03-30 10:28:49.000000000 -05:00'),
download: 'swift-5.8-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz',
checksum:
'df0b40b9b582598e7e3d70c82ab503fd6fbfdff71fd17e7f1ab37115a0665b3b',
dir: 'swift-5.8-RELEASE',
platform: 'static-sdk',
branch: 'swift-5.8-release',
preventCaching: true
}
]

it('tests dry run', async () => {
toolchainSpy.mockResolvedValue(toolchain)
jest.spyOn(core, 'getBooleanInput').mockReturnValue(true)
jest.spyOn(core, 'getInput').mockReturnValue('latest')
jest
.spyOn(SdkSupportedVersion.prototype, 'sdkSnapshots')
.mockResolvedValue(sdkToolchains)
await main.run()
expect(failedSpy).not.toHaveBeenCalled()
expect(installSpy).not.toHaveBeenCalled()
Expand All @@ -45,13 +62,26 @@ describe('setup-swift run validation', () => {
expect(obj).toStrictEqual(toolchain)
break
}
case 'sdks': {
const objs = JSON.parse(call[1])
for (let i = 0; i < objs.length; i++) {
const obj = objs[i]
const sdkToolchain = sdkToolchains[i]
obj.date = new Date(obj.date)
expect(obj).toStrictEqual(sdkToolchain)
}
break
}
}
}
})

it('tests install', async () => {
const installer = new LinuxToolchainInstaller(toolchain)
installSpy.mockResolvedValue(installer)
const sdkInstallers = sdkToolchains.map(
toolchain => new SdkToolchainInstaller(toolchain)
)
installSpy.mockResolvedValue({installer, sdkInstallers})
jest.spyOn(core, 'getBooleanInput').mockReturnValue(false)
jest.spyOn(core, 'getInput').mockReturnValue('latest')
jest.spyOn(installer, 'installedSwiftVersion').mockResolvedValue('5.8')
Expand All @@ -72,6 +102,16 @@ describe('setup-swift run validation', () => {
expect(obj).toStrictEqual(toolchain)
break
}
case 'sdks': {
const objs = JSON.parse(call[1])
for (let i = 0; i < objs.length; i++) {
const obj = objs[i]
const sdkToolchain = sdkToolchains[i]
obj.date = new Date(obj.date)
expect(obj).toStrictEqual(sdkToolchain)
}
break
}
}
}
})
Expand Down
Loading
Loading