diff --git a/.eslintrc.json b/.eslintrc.json
index f07f74f..d93bd9e 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -5,7 +5,7 @@
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
- "project": "./tsconfig.json"
+ "project": [ "./tsconfig.base.json", "./tsconfig.json"]
},
"rules": {
"i18n-text/no-en": "off",
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/pull_request_template.md
similarity index 100%
rename from .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
rename to .github/pull_request_template.md
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 6d939fe..c700109 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -169,6 +169,10 @@ jobs:
- os: windows-latest
swift: '5.3'
development: false
+ - os: ubuntu-22.04
+ swift: ${{ fromJSON(vars.SETUPSWIFT_CUSTOM_TOOLCHAINS).ubuntu2204 }}
+ development: true
+ noverify: true
steps:
- name: Checkout repository
@@ -201,10 +205,11 @@ jobs:
cache-snapshot: ${{ !matrix.development }}
- name: Verify Swift version in macos
- if: runner.os == 'macOS'
+ if: runner.os == 'macOS' && matrix.noverify != 'true'
run: xcrun --toolchain ${{ env.TOOLCHAINS || '""' }} swift --version | grep ${{ steps.setup-swift.outputs.swift-version }} || exit 1
- name: Verify Swift version
+ if: matrix.noverify != 'true'
run: swift --version | grep ${{ steps.setup-swift.outputs.swift-version }} || exit 1
dry-run:
diff --git a/README.md b/README.md
index f81c870..3c9e5e2 100644
--- a/README.md
+++ b/README.md
@@ -99,6 +99,16 @@ In other words specifying...
- `"4"` will resolve to latest minor and patch version (aka `4.2.4`)
- `"4.0.0"` will resolve to version `4.0`
+
+ Additionally, to use custom toolchains, download URL can be provided. The download URL must point to a `tar` archive for `Linux`, `pkg` file for `macOS` and `exe` file for `Windows`.
+
+ i.e. for `macOS`: https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.10-SNAPSHOT-2024-03-30-a/swift-wasm-5.10-SNAPSHOT-2024-03-30-a-macos_x86_64.pkg
+ for `Linux`: https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.10-SNAPSHOT-2024-03-30-a/swift-wasm-5.10-SNAPSHOT-2024-03-30-a-ubuntu22.04_x86_64.tar.gz
+
+ > [!IMPORTANT]
+ > When using custom toolchains, please ensure that the toolchain can be installed and used on the GitHub runner, this action won't be able to validate this for custom toolchains.
+
+
### Caveats
YAML interprets eg. `4.0` as a float, this action will then interpret that as `4` which will result in eg. Swift `4.2.4` being resolved. Quote your inputs! Thus surround version input with quotations:
diff --git a/__tests__/installer/linux.test.ts b/__tests__/installer/linux.test.ts
index 56d66d0..cb07e2c 100644
--- a/__tests__/installer/linux.test.ts
+++ b/__tests__/installer/linux.test.ts
@@ -1,11 +1,16 @@
+import os from 'os'
import * as path from 'path'
import {promises as fs} from 'fs'
+// @ts-ignore
+import {__setos as setos} from 'getos'
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as cache from '@actions/cache'
import * as toolCache from '@actions/tool-cache'
import {coerce as parseSemVer} from 'semver'
import {LinuxToolchainInstaller} from '../../src/installer/linux'
+import {ToolchainVersion} from '../../src/version'
+import {Platform} from '../../src/platform'
describe('linux toolchain installation verification', () => {
const env = process.env
@@ -17,7 +22,8 @@ describe('linux toolchain installation verification', () => {
dir: 'swift-5.8-RELEASE',
docker: '5.8-jammy',
platform: 'ubuntu2204',
- branch: 'swift-5.8-release'
+ branch: 'swift-5.8-release',
+ preventCaching: false
}
beforeEach(() => {
@@ -32,7 +38,7 @@ describe('linux toolchain installation verification', () => {
it('tests download', async () => {
const installer = new LinuxToolchainInstaller(toolchain)
expect(installer['version']).toStrictEqual(parseSemVer('5.8'))
- expect(installer['baseUrl']).toBe(
+ expect(installer['baseUrl'].href).toBe(
'https://download.swift.org/swift-5.8-release/ubuntu2204/swift-5.8-RELEASE'
)
@@ -127,4 +133,35 @@ describe('linux toolchain installation verification', () => {
const devVersion = await installer.installedSwiftVersion()
expect(devVersion).toBe('5.9-dev')
})
+
+ it('tests custom swift tool caching', async () => {
+ setos({os: 'linux', dist: 'Ubuntu', release: '22.04'})
+ jest.spyOn(os, 'arch').mockReturnValue('x64')
+ const swiftwasm = 'https://github.com/swiftwasm/swift/releases/download'
+ const name = 'swift-wasm-5.10-SNAPSHOT-2024-03-30-a'
+ const resource = `${name}-ubuntu22.04_x86_64.tar.gz`
+ const toolchainUrl = `${swiftwasm}/${name}/${resource}`
+ const cVer = ToolchainVersion.create(toolchainUrl, false)
+ const download = path.resolve('tool', 'download', 'path')
+ const extracted = path.resolve('tool', 'extracted', 'path')
+ const cached = path.resolve('tool', 'cached', 'path')
+ jest.spyOn(core, 'getBooleanInput').mockReturnValue(true)
+ jest.spyOn(cache, 'restoreCache').mockResolvedValue(undefined)
+ jest.spyOn(toolCache, 'find').mockReturnValue('')
+ jest.spyOn(fs, 'cp').mockResolvedValue()
+ jest.spyOn(toolCache, 'downloadTool').mockResolvedValue(download)
+ jest.spyOn(toolCache, 'extractTar').mockResolvedValue(extracted)
+ jest.spyOn(toolCache, 'cacheDir').mockResolvedValue(cached)
+ jest.spyOn(exec, 'exec').mockResolvedValue(0)
+ const cacheSpy = jest.spyOn(cache, 'saveCache')
+ 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)
+ expect(installer.data.name).toBe('Swift Custom Snapshot')
+ expect(installer.data.platform).toBe('ubuntu2204')
+ expect(installer.data.download).toBe(resource)
+ expect(installer.data.dir).toBe(name)
+ expect(installer.data.branch).toBe('swiftwasm')
+ })
})
diff --git a/__tests__/installer/windows.test.ts b/__tests__/installer/windows.test.ts
index f3aaaa0..a8c19e3 100644
--- a/__tests__/installer/windows.test.ts
+++ b/__tests__/installer/windows.test.ts
@@ -19,7 +19,8 @@ describe('windows toolchain installation verification', () => {
dir: 'swift-5.8-RELEASE',
platform: 'windows10',
branch: 'swift-5.8-release',
- windows: true
+ windows: true,
+ preventCaching: false
}
const visualStudio = VisualStudio.createFromJSON({
installationPath: path.join('C:', 'Visual Studio'),
@@ -61,7 +62,7 @@ describe('windows toolchain installation verification', () => {
it('tests download without caching', async () => {
const installer = new WindowsToolchainInstaller(toolchain)
expect(installer['version']).toStrictEqual(parseSemVer('5.8'))
- expect(installer['baseUrl']).toBe(
+ expect(installer['baseUrl'].href).toBe(
'https://download.swift.org/swift-5.8-release/windows10/swift-5.8-RELEASE'
)
diff --git a/__tests__/installer/xcode.test.ts b/__tests__/installer/xcode.test.ts
index e8782f7..885f984 100644
--- a/__tests__/installer/xcode.test.ts
+++ b/__tests__/installer/xcode.test.ts
@@ -16,12 +16,13 @@ describe('macOS toolchain installation verification', () => {
name: 'Xcode Swift 5.8.1',
date: new Date('2023-05-31T18:30:00.000Z'),
download: 'swift-5.8.1-RELEASE-osx.pkg',
- symbols: 'swift-5.8.1-RELEASE-osx-symbols.pkg',
+ debug_info: 'swift-5.8.1-RELEASE-osx-symbols.pkg',
dir: 'swift-5.8.1-RELEASE',
xcode: '14.3.1',
platform: 'xcode',
branch: 'swift-5.8.1-release',
- xcodePath: '/Applications/Xcode_14.3.1.app'
+ xcodePath: '/Applications/Xcode_14.3.1.app',
+ preventCaching: false
}
beforeEach(() => {
@@ -56,7 +57,7 @@ describe('macOS toolchain installation verification', () => {
it('tests download', async () => {
const installer = new XcodeToolchainInstaller(toolchain)
expect(installer['version']).toStrictEqual(parseSemVer('5.8.1'))
- expect(installer['baseUrl']).toBe(
+ expect(installer['baseUrl'].href).toBe(
'https://download.swift.org/swift-5.8.1-release/xcode/swift-5.8.1-RELEASE'
)
diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts
index c0f964b..d29167a 100644
--- a/__tests__/main.test.ts
+++ b/__tests__/main.test.ts
@@ -20,7 +20,8 @@ describe('setup-swift run validation', () => {
dir: 'swift-5.8-RELEASE',
docker: '5.8-jammy',
platform: 'ubuntu2204',
- branch: 'swift-5.8-release'
+ branch: 'swift-5.8-release',
+ preventCaching: false
}
it('tests dry run', async () => {
diff --git a/__tests__/snapshot/linux.test.ts b/__tests__/snapshot/linux.test.ts
index 51bbdd8..6aff2ef 100644
--- a/__tests__/snapshot/linux.test.ts
+++ b/__tests__/snapshot/linux.test.ts
@@ -1,4 +1,5 @@
import os from 'os'
+import {posix} from 'path'
// @ts-ignore
import {__setos as setos} from 'getos'
import {ToolchainVersion} from '../../src/version'
@@ -30,6 +31,7 @@ describe('fetch linux tool data based on options', () => {
'swift-4.2.4-RELEASE-ubuntu18.04.tar.gz.sig'
)
expect(lTool.docker).toBeUndefined()
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift 5.0 tool', async () => {
@@ -46,6 +48,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.0.3-RELEASE-ubuntu18.04.tar.gz.sig'
)
expect(lTool.docker).toBe('5.0.3-bionic')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift 5.5.0 tool', async () => {
@@ -62,6 +65,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.5-RELEASE-ubuntu18.04.tar.gz.sig'
)
expect(lTool.docker).toBe('5.5-bionic')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 20.04 arm64 latest swift 5.6.0 tool', async () => {
@@ -79,6 +83,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.6-RELEASE-ubuntu20.04-aarch64.tar.gz.sig'
)
expect(lTool.docker).toBe('5.6-focal')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift 5.5 tool', async () => {
@@ -95,6 +100,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.5.3-RELEASE-ubuntu18.04.tar.gz.sig'
)
expect(lTool.docker).toBe('5.5.3-bionic')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift 5.5 tool including dev snapshot', async () => {
@@ -111,6 +117,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.5.3-RELEASE-ubuntu18.04.tar.gz.sig'
)
expect(lTool.docker).toBe('5.5.3-bionic')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift tool', async () => {
@@ -124,6 +131,7 @@ describe('fetch linux tool data based on options', () => {
expect(lTool.platform).toBeTruthy()
expect(lTool.branch).toBeTruthy()
expect(lTool.download_signature).toBeTruthy()
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift tool including dev snapshot', async () => {
@@ -138,6 +146,7 @@ describe('fetch linux tool data based on options', () => {
expect(lTool.branch).toBeTruthy()
expect(lTool.download_signature).toBeTruthy()
expect(lTool.docker).toBeTruthy()
+ expect(lTool.preventCaching).toBe(false)
})
it('handles swift tool version not present by returning undefined', async () => {
@@ -163,6 +172,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.6.1-RELEASE-ubuntu20.04.tar.gz.sig'
)
expect(lTool.docker).toBe('5.6.1-focal')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 20.04 latest swift 5.2 tool', async () => {
@@ -180,6 +190,7 @@ describe('fetch linux tool data based on options', () => {
'swift-5.2.5-RELEASE-ubuntu20.04.tar.gz.sig'
)
expect(lTool.docker).toBe('5.2.5-focal')
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches centos 7 latest swift tool', async () => {
@@ -194,6 +205,7 @@ describe('fetch linux tool data based on options', () => {
expect(lTool.branch).toBeTruthy()
expect(lTool.download_signature).toBeTruthy()
expect(lTool.docker).toBeTruthy()
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 22.04 named swift tool', async () => {
@@ -213,6 +225,7 @@ describe('fetch linux tool data based on options', () => {
expect(lTool.download_signature).toBe(
'swift-DEVELOPMENT-SNAPSHOT-2023-09-02-a-ubuntu22.04.tar.gz.sig'
)
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 22.04 named versioned swift tool', async () => {
@@ -232,6 +245,7 @@ describe('fetch linux tool data based on options', () => {
expect(lTool.download_signature).toBe(
'swift-5.9-DEVELOPMENT-SNAPSHOT-2023-09-01-a-ubuntu22.04.tar.gz.sig'
)
+ expect(lTool.preventCaching).toBe(false)
})
it('fetches ubuntu 18.04 latest swift 5.5 tools', async () => {
@@ -271,4 +285,24 @@ describe('fetch linux tool data based on options', () => {
const tools = await Platform.toolchains(ver5_2)
expect(tools.length).toBe(2)
})
+
+ it('fetches ubuntu 22.04 custom swift tools', async () => {
+ setos({os: 'linux', dist: 'Ubuntu', release: '22.04'})
+ jest.spyOn(os, 'arch').mockReturnValue('x64')
+ const swiftwasm = 'https://github.com/swiftwasm/swift/releases/download'
+ const name = 'swift-wasm-5.10-SNAPSHOT-2024-03-30-a'
+ const resource = `${name}-ubuntu22.04_x86_64.tar.gz`
+ const toolchainUrl = `${swiftwasm}/${name}/${resource}`
+ const cVer = ToolchainVersion.create(toolchainUrl, false)
+ const tools = await Platform.toolchains(cVer)
+ expect(tools.length).toBe(1)
+ const tool = tools[0]
+ expect(tool.baseUrl?.href).toBe(posix.dirname(toolchainUrl))
+ expect(tool.preventCaching).toBe(true)
+ expect(tool.name).toBe('Swift Custom Snapshot')
+ expect(tool.platform).toBe('ubuntu2204')
+ expect(tool.download).toBe(resource)
+ expect(tool.dir).toBe(name)
+ expect(tool.branch).toBe('swiftwasm')
+ })
})
diff --git a/__tests__/snapshot/windows.test.ts b/__tests__/snapshot/windows.test.ts
index d0eac82..78dc882 100644
--- a/__tests__/snapshot/windows.test.ts
+++ b/__tests__/snapshot/windows.test.ts
@@ -1,4 +1,5 @@
import os from 'os'
+import {posix} from 'path'
// @ts-ignore
import {__setos as setos} from 'getos'
import {ToolchainVersion} from '../../src/version'
@@ -27,6 +28,7 @@ describe('fetch windows tool data based on options', () => {
expect(wTool.platform).toBe('windows10')
expect(wTool.branch).toBeTruthy()
expect(wTool.download_signature).toBeTruthy()
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 latest swift 5.0 tool', async () => {
@@ -47,6 +49,7 @@ describe('fetch windows tool data based on options', () => {
expect(wTool.platform).toBe('windows10')
expect(wTool.branch).toBe('swift-5.5-release')
expect(wTool.download_signature).toBe('swift-5.5-RELEASE-windows10.exe.sig')
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 latest swift 5.5 tool', async () => {
@@ -62,6 +65,7 @@ describe('fetch windows tool data based on options', () => {
expect(wTool.download_signature).toBe(
'swift-5.5.3-RELEASE-windows10.exe.sig'
)
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 latest swift 5.5 tool including dev snapshot', async () => {
@@ -77,6 +81,7 @@ describe('fetch windows tool data based on options', () => {
expect(wTool.download_signature).toBe(
'swift-5.5.3-RELEASE-windows10.exe.sig'
)
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 latest swift tool', async () => {
@@ -91,6 +96,7 @@ describe('fetch windows tool data based on options', () => {
expect(wTool.platform).toBeTruthy()
expect(wTool.branch).toBeTruthy()
expect(wTool.download_signature).toBeTruthy()
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 latest swift tool including dev snapshot', async () => {
@@ -103,6 +109,7 @@ describe('fetch windows tool data based on options', () => {
expect(wTool.dir).toBeTruthy()
expect(wTool.platform).toBeTruthy()
expect(wTool.branch).toBeTruthy()
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 named swift tool', async () => {
@@ -112,16 +119,17 @@ describe('fetch windows tool data based on options', () => {
const version = ToolchainVersion.create(name, false)
const tool = await Platform.toolchain(version)
expect(tool).toBeTruthy()
- const lTool = tool as WindowsToolchainSnapshot
- expect(lTool.download).toBe(
+ const wTool = tool as WindowsToolchainSnapshot
+ expect(wTool.download).toBe(
'swift-DEVELOPMENT-SNAPSHOT-2023-08-10-a-windows10.exe'
)
- expect(lTool.dir).toBe('swift-DEVELOPMENT-SNAPSHOT-2023-08-10-a')
- expect(lTool.platform).toBe('windows10')
- expect(lTool.branch).toBe('development')
- expect(lTool.download_signature).toBe(
+ expect(wTool.dir).toBe('swift-DEVELOPMENT-SNAPSHOT-2023-08-10-a')
+ expect(wTool.platform).toBe('windows10')
+ expect(wTool.branch).toBe('development')
+ expect(wTool.download_signature).toBe(
'swift-DEVELOPMENT-SNAPSHOT-2023-08-10-a-windows10.exe.sig'
)
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 named versioned swift tool', async () => {
@@ -131,16 +139,17 @@ describe('fetch windows tool data based on options', () => {
const version = ToolchainVersion.create(name, false)
const tool = await Platform.toolchain(version)
expect(tool).toBeTruthy()
- const lTool = tool as WindowsToolchainSnapshot
- expect(lTool.download).toBe(
+ const wTool = tool as WindowsToolchainSnapshot
+ expect(wTool.download).toBe(
'swift-5.9-DEVELOPMENT-SNAPSHOT-2023-05-11-a-windows10.exe'
)
- expect(lTool.dir).toBe('swift-5.9-DEVELOPMENT-SNAPSHOT-2023-05-11-a')
- expect(lTool.platform).toBe('windows10')
- expect(lTool.branch).toBe('swift-5.9-branch')
- expect(lTool.download_signature).toBe(
+ expect(wTool.dir).toBe('swift-5.9-DEVELOPMENT-SNAPSHOT-2023-05-11-a')
+ expect(wTool.platform).toBe('windows10')
+ expect(wTool.branch).toBe('swift-5.9-branch')
+ expect(wTool.download_signature).toBe(
'swift-5.9-DEVELOPMENT-SNAPSHOT-2023-05-11-a-windows10.exe.sig'
)
+ expect(wTool.preventCaching).toBe(false)
})
it('fetches windows 10 latest swift 5.5 tools', async () => {
@@ -156,4 +165,24 @@ describe('fetch windows tool data based on options', () => {
const tools = await Platform.toolchains(dev5_5)
expect(tools.length).toBe(34)
})
+
+ it('fetches windows 10 custom swift tools', async () => {
+ setos({os: 'win32', dist: 'Windows', release: '10.0.17063'})
+ jest.spyOn(os, 'arch').mockReturnValue('x64')
+ const swiftwasm = 'https://github.com/swiftwasm/swift/releases/download'
+ const name = 'swift-wasm-5.10-SNAPSHOT-2024-03-30-a'
+ const resource = `${name}-windows10.exe`
+ const toolchainUrl = `${swiftwasm}/${name}/${resource}`
+ const cVer = ToolchainVersion.create(toolchainUrl, false)
+ const tools = await Platform.toolchains(cVer)
+ expect(tools.length).toBe(1)
+ const tool = tools[0]
+ expect(tool.baseUrl?.href).toBe(posix.dirname(toolchainUrl))
+ expect(tool.preventCaching).toBe(true)
+ expect(tool.name).toBe('Swift Custom Snapshot')
+ expect(tool.platform).toBe('windows10')
+ expect(tool.download).toBe(resource)
+ expect(tool.dir).toBe(name)
+ expect(tool.branch).toBe('swiftwasm')
+ })
})
diff --git a/__tests__/snapshot/xcode.test.ts b/__tests__/snapshot/xcode.test.ts
index 115ec44..2581239 100644
--- a/__tests__/snapshot/xcode.test.ts
+++ b/__tests__/snapshot/xcode.test.ts
@@ -1,4 +1,5 @@
import os from 'os'
+import {posix} from 'path'
import {glob} from 'glob'
// @ts-ignore
import {__setos as setos} from 'getos'
@@ -28,6 +29,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.platform).toBe('xcode')
expect(xTool.branch).toBe('swift-4.2.4-release')
expect(xTool.xcode).toBe('10.1')
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift 5.0 tool', async () => {
@@ -41,6 +43,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.platform).toBe('xcode')
expect(xTool.branch).toBe('swift-5.0.3-release')
expect(xTool.xcode).toBe('10.2.1')
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift 5.5.0 tool', async () => {
@@ -54,6 +57,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.platform).toBe('xcode')
expect(xTool.branch).toBe('swift-5.5-release')
expect(xTool.xcode).toBe('13')
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift 5.5 tool', async () => {
@@ -67,6 +71,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.platform).toBe('xcode')
expect(xTool.branch).toBe('swift-5.5.3-release')
expect(xTool.xcode).toBe('13.2')
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift 5.5 tool including dev snapshot', async () => {
@@ -80,6 +85,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.platform).toBe('xcode')
expect(xTool.branch).toBe('swift-5.5.3-release')
expect(xTool.xcode).toBe('13.2')
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift tool', async () => {
@@ -93,6 +99,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.platform).toBeTruthy()
expect(xTool.branch).toBeTruthy()
expect(xTool.xcode).toBeTruthy()
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift tool including dev snapshot', async () => {
@@ -105,6 +112,7 @@ describe('fetch macos tool data based on options', () => {
expect(xTool.dir).toBeTruthy()
expect(xTool.platform).toBeTruthy()
expect(xTool.branch).toBeTruthy()
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift beta version tool', async () => {
@@ -135,6 +143,8 @@ describe('fetch macos tool data based on options', () => {
ToolchainVersion.create(betaVersion, false)
)
expect(tool).toBeTruthy()
+ const xTool = tool as XcodeToolchainSnapshot
+ expect(xTool.preventCaching).toBe(false)
}
})
@@ -145,13 +155,14 @@ describe('fetch macos tool data based on options', () => {
const version = ToolchainVersion.create(name, false)
const tool = await Platform.toolchain(version)
expect(tool).toBeTruthy()
- const lTool = tool as XcodeToolchainSnapshot
- expect(lTool.download).toBe(
+ const xTool = tool as XcodeToolchainSnapshot
+ expect(xTool.download).toBe(
'swift-DEVELOPMENT-SNAPSHOT-2023-09-02-a-osx.pkg'
)
- expect(lTool.dir).toBe('swift-DEVELOPMENT-SNAPSHOT-2023-09-02-a')
- expect(lTool.platform).toBe('xcode')
- expect(lTool.branch).toBe('development')
+ expect(xTool.dir).toBe('swift-DEVELOPMENT-SNAPSHOT-2023-09-02-a')
+ expect(xTool.platform).toBe('xcode')
+ expect(xTool.branch).toBe('development')
+ expect(xTool.preventCaching).toBe(false)
})
it('fetches macOS named versioned swift tool', async () => {
@@ -161,13 +172,14 @@ describe('fetch macos tool data based on options', () => {
const version = ToolchainVersion.create(name, false)
const tool = await Platform.toolchain(version)
expect(tool).toBeTruthy()
- const lTool = tool as XcodeToolchainSnapshot
- expect(lTool.download).toBe(
+ const xTool = tool as XcodeToolchainSnapshot
+ expect(xTool.download).toBe(
'swift-5.9-DEVELOPMENT-SNAPSHOT-2023-09-01-a-osx.pkg'
)
- expect(lTool.dir).toBe('swift-5.9-DEVELOPMENT-SNAPSHOT-2023-09-01-a')
- expect(lTool.platform).toBe('xcode')
- expect(lTool.branch).toBe('swift-5.9-branch')
+ expect(xTool.dir).toBe('swift-5.9-DEVELOPMENT-SNAPSHOT-2023-09-01-a')
+ expect(xTool.platform).toBe('xcode')
+ expect(xTool.branch).toBe('swift-5.9-branch')
+ expect(xTool.preventCaching).toBe(false)
})
it('detects earliest toolchains', async () => {
@@ -181,6 +193,7 @@ describe('fetch macos tool data based on options', () => {
expect(earliestTool.platform).toBe('xcode')
expect(earliestTool.branch).toBe('swift-2.2-release')
expect(earliestTool.download).toBe('swift-2.2-RELEASE-osx.pkg')
+ expect(earliestTool.preventCaching).toBe(false)
})
it('fetches macOS latest swift 5.5 tools', async () => {
@@ -196,4 +209,24 @@ describe('fetch macos tool data based on options', () => {
const tools = await Platform.toolchains(dev5_5)
expect(tools.length).toBe(103)
})
+
+ it('fetches macOS custom swift tools', async () => {
+ setos({os: 'darwin', dist: 'macOS', release: '21'})
+ jest.spyOn(os, 'arch').mockReturnValue('x64')
+ const swiftwasm = 'https://github.com/swiftwasm/swift/releases/download'
+ const name = 'swift-wasm-5.10-SNAPSHOT-2024-03-30-a'
+ const resource = `${name}-macos_arm64.pkg`
+ const toolchainUrl = `${swiftwasm}/${name}/${resource}`
+ const cVer = ToolchainVersion.create(toolchainUrl, false)
+ const tools = await Platform.toolchains(cVer)
+ expect(tools.length).toBe(1)
+ const tool = tools[0]
+ expect(tool.baseUrl?.href).toBe(posix.dirname(toolchainUrl))
+ expect(tool.preventCaching).toBe(true)
+ expect(tool.name).toBe('Swift Custom Snapshot')
+ expect(tool.platform).toBe('xcode')
+ expect(tool.download).toBe(resource)
+ expect(tool.dir).toBe(name)
+ expect(tool.branch).toBe('swiftwasm')
+ })
})
diff --git a/__tests__/swiftorg.test.ts b/__tests__/swiftorg.test.ts
index 86d0968..361e205 100644
--- a/__tests__/swiftorg.test.ts
+++ b/__tests__/swiftorg.test.ts
@@ -95,6 +95,23 @@ describe('swiftorg sync validation', () => {
])
})
+ it('tests without latest sync success with matadata fetch', async () => {
+ execSpy.mockResolvedValue(0)
+ process.env.SETUPSWIFT_SWIFTORG_METADATA = undefined
+ const commit = '74caef941bc8ed6a01b9572ab6149e1d1f8a2d69'
+ const swiftorg = new Swiftorg(false)
+ nock(SWIFTORG_METADATA)
+ .get(/.*/)
+ .reply(200, {commit}, {'content-type': 'application/json'})
+ await swiftorg.update()
+ expect(execSpy).toHaveBeenCalledTimes(3)
+ expect(execSpy.mock.calls[1]).toStrictEqual([
+ 'git',
+ ['fetch', SWIFTORG_ORIGIN, commit, '--depth=1', '--no-tags'],
+ {cwd: path.join(MODULE_DIR, SWIFTORG)}
+ ])
+ })
+
it('tests without latest sync failure with matadata fetch failure', async () => {
execSpy.mockResolvedValue(0)
process.env.SETUPSWIFT_SWIFTORG_METADATA = undefined
@@ -109,7 +126,7 @@ describe('swiftorg sync validation', () => {
expect(execSpy).toHaveBeenCalledTimes(0)
})
- it('tests without latest sync failure with invalid matadata', async () => {
+ it('tests without latest sync failure with invalid matadata content type', async () => {
execSpy.mockResolvedValue(0)
process.env.SETUPSWIFT_SWIFTORG_METADATA = undefined
const contentType = 'application/txt'
@@ -122,4 +139,15 @@ describe('swiftorg sync validation', () => {
)
expect(execSpy).toHaveBeenCalledTimes(0)
})
+
+ it('tests without latest sync failure with invalid matadata content', async () => {
+ execSpy.mockResolvedValue(0)
+ process.env.SETUPSWIFT_SWIFTORG_METADATA = undefined
+ const swiftorg = new Swiftorg(false)
+ nock(SWIFTORG_METADATA)
+ .get(/.*/)
+ .reply(200, 'invalid', {'content-type': 'application/json'})
+ await expect(swiftorg.update()).rejects.toBeInstanceOf(SyntaxError)
+ expect(execSpy).toHaveBeenCalledTimes(0)
+ })
})
diff --git a/__tests__/utils/gpg.test.ts b/__tests__/utils/gpg.test.ts
index ae53dea..b4c3583 100644
--- a/__tests__/utils/gpg.test.ts
+++ b/__tests__/utils/gpg.test.ts
@@ -14,7 +14,7 @@ describe('gpg setup validation', () => {
const execSpy = jest.spyOn(exec, 'exec')
execSpy.mockRejectedValueOnce(new Error())
execSpy.mockResolvedValue(0)
- await expect(gpg.setupKeys()).resolves
+ await gpg.setupKeys()
})
it('tests keys refresh retry', async () => {
@@ -22,7 +22,7 @@ describe('gpg setup validation', () => {
execSpy.mockResolvedValueOnce(0)
execSpy.mockRejectedValueOnce(new Error())
execSpy.mockResolvedValue(0)
- await expect(gpg.setupKeys()).resolves
+ await gpg.setupKeys()
})
it('tests keys refresh error', async () => {
diff --git a/__tests__/version.test.ts b/__tests__/version.test.ts
index 2c5c5e2..a27cfea 100644
--- a/__tests__/version.test.ts
+++ b/__tests__/version.test.ts
@@ -2,7 +2,8 @@ import {
ToolchainVersion,
SemanticToolchainVersion,
LatestToolchainVersion,
- ToolchainSnapshotName
+ ToolchainSnapshotName,
+ ToolchainSnapshotLocation
} from '../src/version'
describe('parse version from provided string', () => {
@@ -10,11 +11,13 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('latest', false)
expect(version).toBeInstanceOf(LatestToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
expect(`${version}`).toBe('latest version')
const devVersion = ToolchainVersion.create('latest', true)
expect(devVersion).toBeInstanceOf(LatestToolchainVersion)
expect(devVersion.dev).toBe(true)
+ expect(version.requiresSwiftOrg).toBe(true)
expect(`${devVersion}`).toBe('latest dev version')
})
@@ -22,11 +25,13 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('current', false)
expect(version).toBeInstanceOf(LatestToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
expect(`${version}`).toBe('latest version')
const devVersion = ToolchainVersion.create('current', true)
expect(devVersion).toBeInstanceOf(LatestToolchainVersion)
expect(devVersion.dev).toBe(true)
+ expect(version.requiresSwiftOrg).toBe(true)
expect(`${devVersion}`).toBe('latest dev version')
})
@@ -34,6 +39,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('5', false)
expect(version).toBeInstanceOf(SemanticToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
expect(`${version}`).toBe('version: 5.0.0, dev: false')
const sVersion = version as SemanticToolchainVersion
expect(sVersion['dirGlob']).toBe('swift-5*')
@@ -44,6 +50,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('5.0', false)
expect(version).toBeInstanceOf(SemanticToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
const sVersion = version as SemanticToolchainVersion
expect(sVersion['dirGlob']).toBe('swift-5_0*')
expect(sVersion['dirRegex']).toStrictEqual(/swift-5.0/)
@@ -53,6 +60,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('5.0.0', false)
expect(version).toBeInstanceOf(SemanticToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
const sVersion = version as SemanticToolchainVersion
expect(sVersion['dirGlob']).toBe('swift-5_0-*')
expect(sVersion['dirRegex']).toStrictEqual(/swift-5.0-/)
@@ -62,6 +70,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('5.5', false)
expect(version).toBeInstanceOf(SemanticToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
const sVersion = version as SemanticToolchainVersion
expect(sVersion['dirGlob']).toBe('swift-5_5*')
expect(sVersion['dirRegex']).toStrictEqual(/swift-5.5/)
@@ -71,6 +80,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('5.5.0', false)
expect(version).toBeInstanceOf(SemanticToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
const sVersion = version as SemanticToolchainVersion
expect(sVersion['dirGlob']).toBe('swift-5_5-*')
expect(sVersion['dirRegex']).toStrictEqual(/swift-5.5-/)
@@ -80,6 +90,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create('5.5.1', false)
expect(version).toBeInstanceOf(SemanticToolchainVersion)
expect(version.dev).toBe(false)
+ expect(version.requiresSwiftOrg).toBe(true)
const sVersion = version as SemanticToolchainVersion
expect(sVersion['dirGlob']).toBe('swift-5_5_1*')
expect(sVersion['dirRegex']).toStrictEqual(/swift-5.5.1/)
@@ -90,6 +101,7 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create(name, false)
expect(version).toBeInstanceOf(ToolchainSnapshotName)
expect(version.dev).toBe(true)
+ expect(version.requiresSwiftOrg).toBe(true)
const lVersion = version as ToolchainSnapshotName
expect(lVersion['dirGlob']).toBe('*')
expect(lVersion['dirRegex']).toStrictEqual(new RegExp(name))
@@ -101,11 +113,25 @@ describe('parse version from provided string', () => {
const version = ToolchainVersion.create(input, false)
expect(version).toBeInstanceOf(ToolchainSnapshotName)
expect(version.dev).toBe(true)
+ expect(version.requiresSwiftOrg).toBe(true)
const lVersion = version as ToolchainSnapshotName
expect(lVersion['dirGlob']).toBe('swift-5_9-*')
expect(lVersion['dirRegex']).toStrictEqual(new RegExp(name))
})
+ it('parses toolchain URL', async () => {
+ const swiftwasm = 'https://github.com/swiftwasm/swift/releases/download'
+ const name = 'swift-wasm-5.10-SNAPSHOT-2024-03-30-a'
+ const toolchainUrl = `${swiftwasm}/${name}/${name}-ubuntu22.04_x86_64.tar.gz`
+ const version = ToolchainVersion.create(toolchainUrl, false)
+ expect(version).toBeInstanceOf(ToolchainSnapshotLocation)
+ const lVersion = version as ToolchainSnapshotLocation
+ expect(lVersion['dirGlob']).toBe('')
+ expect(lVersion['dirRegex']).toStrictEqual(/a^/)
+ expect(lVersion.requiresSwiftOrg).toBe(false)
+ expect(lVersion.url.href).toBe(toolchainUrl)
+ })
+
it('parses invalid input', async () => {
const creation = () => ToolchainVersion.create('invalid', false)
expect(creation).toThrow()
diff --git a/action.yml b/action.yml
index 370997e..9f8009f 100644
--- a/action.yml
+++ b/action.yml
@@ -9,6 +9,9 @@ inputs:
i.e. configures 5.1.1 for 5.1, configures 4.2.4 for 4.
Provide exact semantic version to configure the same version,
i.e. configures 5.1 for 5.1.0, configures 5.0 for 5.0.0.
+ Provide toolchain download URL to configure custom toolchains,
+ i.e. https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.10-SNAPSHOT-2024-03-30-a/swift-wasm-5.10-SNAPSHOT-2024-03-30-a-ubuntu22.04_x86_64.tar.gz,
+ https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.10-SNAPSHOT-2024-03-30-a/swift-wasm-5.10-SNAPSHOT-2024-03-30-a-macos_x86_64.pkg
required: false
default: 'latest'
development:
diff --git a/dist/index.js b/dist/index.js
index 1f9c5fe..75513c3 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -81,6 +81,7 @@ exports.ToolchainInstaller = void 0;
const os = __importStar(__nccwpck_require__(2037));
const path = __importStar(__nccwpck_require__(1017));
const fs_1 = __nccwpck_require__(7147);
+const url_1 = __nccwpck_require__(7310);
const core = __importStar(__nccwpck_require__(2186));
const exec_1 = __nccwpck_require__(1514);
const cache = __importStar(__nccwpck_require__(7799));
@@ -96,7 +97,12 @@ class ToolchainInstaller {
return match && match.length > 1 ? (0, semver_1.coerce)(match[1]) : undefined;
}
get baseUrl() {
- return `https://download.swift.org/${this.data.branch}/${this.data.platform}/${this.data.dir}`;
+ const data = this.data;
+ if (data.baseUrl) {
+ return data.baseUrl;
+ }
+ const base = 'https://download.swift.org';
+ return new url_1.URL(path.posix.join(base, data.branch, data.platform, data.dir));
}
swiftVersionCommand() {
return {
@@ -138,7 +144,9 @@ class ToolchainInstaller {
tool = yield toolCache.cacheDir(tool, key, version, arch);
core.debug(`Added to tool cache at "${tool}"`);
}
- if (core.getBooleanInput('cache-snapshot') && !cacheHit) {
+ if (core.getBooleanInput('cache-snapshot') &&
+ !cacheHit &&
+ !this.data.preventCaching) {
yield fs_1.promises.cp(tool, restore, { recursive: true });
yield cache.saveCache([restore], key);
core.debug(`Saved to cache with key "${key}"`);
@@ -148,7 +156,8 @@ class ToolchainInstaller {
}
download() {
return __awaiter(this, void 0, void 0, function* () {
- const url = `${this.baseUrl}/${this.data.download}`;
+ var _a;
+ const url = path.posix.join((_a = this.baseUrl) === null || _a === void 0 ? void 0 : _a.href, this.data.download);
core.debug(`Downloading snapshot from "${url}"`);
return yield toolCache.downloadTool(url);
});
@@ -400,6 +409,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.VerifyingToolchainInstaller = void 0;
+const path_1 = __nccwpck_require__(1017);
const core = __importStar(__nccwpck_require__(2186));
const toolCache = __importStar(__nccwpck_require__(7784));
const gpg = __importStar(__nccwpck_require__(9787));
@@ -407,18 +417,19 @@ const base_1 = __nccwpck_require__(5686);
class VerifyingToolchainInstaller extends base_1.ToolchainInstaller {
get signatureUrl() {
const signature = this.data.download_signature;
- return signature ? `${this.baseUrl}/${signature}` : undefined;
+ return signature ? path_1.posix.join(this.baseUrl.href, signature) : undefined;
}
downloadSignature() {
return __awaiter(this, void 0, void 0, function* () {
try {
- if (this.signatureUrl) {
- return yield toolCache.downloadTool(this.signatureUrl);
- }
+ return this.signatureUrl
+ ? yield toolCache.downloadTool(this.signatureUrl)
+ : undefined;
}
catch (error) {
if (error instanceof toolCache.HTTPError &&
error.httpStatusCode === 404) {
+ core.warning(`No signature at "${this.signatureUrl}"`);
return undefined;
}
throw error;
@@ -541,16 +552,24 @@ class WindowsToolchainInstaller extends verify_1.VerifyingToolchainInstaller {
return __awaiter(this, void 0, void 0, function* () {
function env() {
return __awaiter(this, void 0, void 0, function* () {
- const { stdout } = yield (0, exec_1.getExecOutput)('cmd', ['/c', 'set'], {
- failOnStdErr: true
- });
- return stdout;
+ for (const target of ['Machine', 'User']) {
+ const { stdout } = yield (0, exec_1.getExecOutput)('powershell', [
+ '-NoProfile',
+ '-Command',
+ `& {[Environment]::GetEnvironmentVariables('${target}') | ConvertTo-Json}`
+ ], { failOnStdErr: true });
+ core.debug(`${target} variables: "${stdout}"`);
+ }
});
}
core.debug(`Installing toolchain from "${exe}"`);
- core.debug(`Environment variables before installation: ${yield env()}`);
+ core.startGroup('Environment variables before installation');
+ yield env();
+ core.endGroup();
yield (0, exec_1.exec)(`"${exe}"`, ['-q']);
- core.debug(`Environment variables after installation: ${yield env()}`);
+ core.startGroup('Environment variables after installation');
+ yield env();
+ core.endGroup();
const installation = yield installation_1.Installation.detect();
return installation.location;
});
@@ -903,11 +922,13 @@ function run() {
const requestedVersion = (_a = core.getInput('swift-version')) !== null && _a !== void 0 ? _a : 'latest';
const development = core.getBooleanInput('development');
const version = version_1.ToolchainVersion.create(requestedVersion, development);
- core.startGroup('Syncing swift.org data');
- const checkLatest = core.getInput('check-latest');
- const submodule = new swiftorg_1.Swiftorg(checkLatest);
- yield submodule.update();
- core.endGroup();
+ if (version.requiresSwiftOrg) {
+ core.startGroup('Syncing swift.org data');
+ const checkLatest = core.getInput('check-latest');
+ const submodule = new swiftorg_1.Swiftorg(checkLatest);
+ yield submodule.update();
+ core.endGroup();
+ }
const dryRun = core.getBooleanInput('dry-run');
let snapshot;
let installedVersion;
@@ -1035,6 +1056,10 @@ class Platform {
}
tools(version) {
return __awaiter(this, void 0, void 0, function* () {
+ const verSnapshot = version.toolchainSnapshot(this.file);
+ if (verSnapshot) {
+ return [this.snapshotFor(verSnapshot)];
+ }
const snapshots = yield this.releasedTools(version);
if (snapshots.length && !version.dev) {
return this.sortSnapshots(snapshots);
@@ -1055,7 +1080,7 @@ class Platform {
const devSnapshots = snapshotsCollection
.flatMap(collection => {
return collection.data.map(data => {
- return Object.assign(Object.assign({}, data), { platform: collection.platform, branch: collection.branch });
+ return Object.assign(Object.assign({}, data), { platform: collection.platform, branch: collection.branch, preventCaching: false });
});
})
.filter(item => version.satisfiedBy(item.dir));
@@ -1251,6 +1276,9 @@ class LinuxPlatform extends versioned_1.VersionedPlatform {
return content;
});
}
+ snapshotFor(snapshot) {
+ return Object.assign(Object.assign({}, snapshot), { download_signature: `${snapshot.download}.sig` });
+ }
tools(version) {
const _super = Object.create(null, {
tools: { get: () => super.tools }
@@ -1457,7 +1485,8 @@ class VersionedPlatform extends base_1.Platform {
platform: pName + this.archSuffix,
branch: release.tag.toLocaleLowerCase(),
docker: platform.docker,
- windows: pName.startsWith('windows')
+ windows: pName.startsWith('windows'),
+ preventCaching: false
}
: [];
});
@@ -1507,6 +1536,9 @@ class WindowsPlatform extends versioned_1.VersionedPlatform {
get downloadExtension() {
return 'exe';
}
+ snapshotFor(snapshot) {
+ return Object.assign(Object.assign({}, snapshot), { download_signature: `${snapshot.download}.sig`, windows: true });
+ }
install(data) {
return __awaiter(this, void 0, void 0, function* () {
const installer = new installer_1.WindowsToolchainInstaller(data);
@@ -1525,6 +1557,29 @@ exports.WindowsPlatform = WindowsPlatform;
"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
@@ -1536,6 +1591,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.XcodePlatform = void 0;
+const path = __importStar(__nccwpck_require__(1017));
const base_1 = __nccwpck_require__(1568);
const installer_1 = __nccwpck_require__(8979);
class XcodePlatform extends base_1.Platform {
@@ -1552,6 +1608,11 @@ class XcodePlatform extends base_1.Platform {
get fileGlob() {
return this.name;
}
+ snapshotFor(snapshot) {
+ const fileExt = path.extname(snapshot.download);
+ const fileName = path.basename(snapshot.download, fileExt);
+ return Object.assign(Object.assign({}, snapshot), { debug_info: `${fileName}-symbols.${fileExt}` });
+ }
releasedTools(version) {
return __awaiter(this, void 0, void 0, function* () {
const releases = yield this.releases();
@@ -1563,11 +1624,12 @@ class XcodePlatform extends base_1.Platform {
name: `Xcode Swift ${release.name}`,
date: release.date,
download: `${release.tag}-osx.pkg`,
- symbols: `${release.tag}-osx-symbols.pkg`,
+ debug_info: `${release.tag}-osx-symbols.pkg`,
dir: release.tag,
xcode: xMatch && xMatch.length > 1 ? xMatch[1] : undefined,
platform: this.name,
- branch: release.tag.toLocaleLowerCase()
+ branch: release.tag.toLocaleLowerCase(),
+ preventCaching: false
};
});
});
@@ -1916,7 +1978,7 @@ class VisualStudio {
this.catalog = catalog;
this.properties = properties;
}
- // eslint-disable-next-line no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
static createFromJSON(json) {
return new VisualStudio(json.installationPath, json.installationVersion, json.catalog, json.properties);
}
@@ -2295,12 +2357,20 @@ const glob_1 = __nccwpck_require__(8211);
const const_1 = __nccwpck_require__(6695);
exports.SWIFT_RELEASE_REGEX = /swift-(.*)-release/;
class ToolchainVersion {
+ get requiresSwiftOrg() {
+ return true;
+ }
constructor(dev) {
this.dev = dev;
}
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ toolchainSnapshot(platform) {
+ return undefined;
+ }
toolFiles(fileGlob) {
return __awaiter(this, void 0, void 0, function* () {
- const pattern = `swiftorg/_data/builds/${this.dirGlob}/${fileGlob}.yml`;
+ const builds = 'swiftorg/_data/builds';
+ const pattern = path.posix.join(builds, this.dirGlob, `${fileGlob}.yml`);
core.debug(`Searching for glob "${pattern}"`);
let files = yield (0, glob_1.glob)(pattern, { absolute: true, cwd: const_1.MODULE_DIR });
core.debug(`Retrieved files "${files}" for glob "${pattern}"`);
@@ -2356,13 +2426,22 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
+const url_1 = __nccwpck_require__(7310);
const core = __importStar(__nccwpck_require__(2186));
const semver_1 = __nccwpck_require__(1383);
const base_1 = __nccwpck_require__(2120);
const latest_1 = __nccwpck_require__(8363);
const semver_2 = __nccwpck_require__(916);
const name_1 = __nccwpck_require__(3987);
+const location_1 = __nccwpck_require__(9785);
base_1.ToolchainVersion.create = (requested, dev = false) => {
+ try {
+ const toolchainUrl = new url_1.URL(requested);
+ return new location_1.ToolchainSnapshotLocation(toolchainUrl, dev);
+ }
+ catch (_a) {
+ core.debug(`Input "${requested}" not an URL`);
+ }
if (requested === 'latest' || requested === 'current') {
core.debug(`Using latest ${dev ? 'development ' : ''}toolchain requirement`);
return new latest_1.LatestToolchainVersion(dev);
@@ -2391,6 +2470,7 @@ __exportStar(__nccwpck_require__(2120), exports);
__exportStar(__nccwpck_require__(8363), exports);
__exportStar(__nccwpck_require__(916), exports);
__exportStar(__nccwpck_require__(3987), exports);
+__exportStar(__nccwpck_require__(9785), exports);
/***/ }),
@@ -2417,6 +2497,57 @@ class LatestToolchainVersion extends base_1.ToolchainVersion {
exports.LatestToolchainVersion = LatestToolchainVersion;
+/***/ }),
+
+/***/ 9785:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
+
+"use strict";
+
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.ToolchainSnapshotLocation = void 0;
+const url_1 = __nccwpck_require__(7310);
+const path_1 = __nccwpck_require__(1017);
+const base_1 = __nccwpck_require__(2120);
+class ToolchainSnapshotLocation extends base_1.ToolchainVersion {
+ constructor(url, dev) {
+ super(dev);
+ this.url = url;
+ }
+ get dirGlob() {
+ return '';
+ }
+ get dirRegex() {
+ return /a^/;
+ }
+ get requiresSwiftOrg() {
+ return false;
+ }
+ toolchainSnapshot(platform) {
+ try {
+ const baseUrl = path_1.posix.dirname(this.url.href);
+ return {
+ name: 'Swift Custom Snapshot',
+ date: new Date(),
+ download: path_1.posix.basename(this.url.href),
+ dir: path_1.posix.basename(baseUrl),
+ platform,
+ branch: this.url.pathname.split(path_1.posix.sep)[1],
+ baseUrl: new url_1.URL(baseUrl),
+ preventCaching: true
+ };
+ }
+ catch (e) {
+ throw new Error(`Swift resource: "${this.url}" failed with error ${e}`);
+ }
+ }
+ toString() {
+ return `url: "${this.url}", dev: ${this.dev}`;
+ }
+}
+exports.ToolchainSnapshotLocation = ToolchainSnapshotLocation;
+
+
/***/ }),
/***/ 3987:
@@ -74588,35 +74719,43 @@ const coerce = (version, options) => {
let match = null
if (!options.rtl) {
- match = version.match(re[t.COERCE])
+ match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE])
} else {
// Find the right-most coercible string that does not share
// a terminus with a more left-ward coercible string.
// Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
+ // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4'
//
// Walk through the string checking with a /g regexp
// Manually set the index so as to pick up overlapping matches.
// Stop when we get a match that ends at the string end, since no
// coercible string can be more right-ward without the same terminus.
+ const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]
let next
- while ((next = re[t.COERCERTL].exec(version)) &&
+ while ((next = coerceRtlRegex.exec(version)) &&
(!match || match.index + match[0].length !== version.length)
) {
if (!match ||
next.index + next[0].length !== match.index + match[0].length) {
match = next
}
- re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length
+ coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length
}
// leave it in a clean state
- re[t.COERCERTL].lastIndex = -1
+ coerceRtlRegex.lastIndex = -1
}
if (match === null) {
return null
}
- return parse(`${match[2]}.${match[3] || '0'}.${match[4] || '0'}`, options)
+ const major = match[2]
+ const minor = match[3] || '0'
+ const patch = match[4] || '0'
+ const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : ''
+ const build = options.includePrerelease && match[6] ? `+${match[6]}` : ''
+
+ return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options)
}
module.exports = coerce
@@ -75308,12 +75447,17 @@ createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)
// Coercion.
// Extract anything that could conceivably be a part of a valid semver
-createToken('COERCE', `${'(^|[^\\d])' +
+createToken('COERCEPLAIN', `${'(^|[^\\d])' +
'(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
- `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
+ `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)
+createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`)
+createToken('COERCEFULL', src[t.COERCEPLAIN] +
+ `(?:${src[t.PRERELEASE]})?` +
+ `(?:${src[t.BUILD]})?` +
`(?:$|[^\\d])`)
createToken('COERCERTL', src[t.COERCE], true)
+createToken('COERCERTLFULL', src[t.COERCEFULL], true)
// Tilde ranges.
// Meaning is "reasonably at or greater than"
diff --git a/src/installer/base.ts b/src/installer/base.ts
index fa18418..098c3cd 100644
--- a/src/installer/base.ts
+++ b/src/installer/base.ts
@@ -1,6 +1,7 @@
import * as os from 'os'
import * as path from 'path'
import {promises as fs} from 'fs'
+import {URL} from 'url'
import * as core from '@actions/core'
import {getExecOutput} from '@actions/exec'
import * as cache from '@actions/cache'
@@ -23,7 +24,12 @@ export abstract class ToolchainInstaller {
}
protected get baseUrl() {
- return `https://download.swift.org/${this.data.branch}/${this.data.platform}/${this.data.dir}`
+ const data = this.data
+ if (data.baseUrl) {
+ return data.baseUrl
+ }
+ const base = 'https://download.swift.org'
+ return new URL(path.posix.join(base, data.branch, data.platform, data.dir))
}
protected swiftVersionCommand() {
@@ -67,7 +73,11 @@ export abstract class ToolchainInstaller {
tool = await toolCache.cacheDir(tool, key, version, arch)
core.debug(`Added to tool cache at "${tool}"`)
}
- if (core.getBooleanInput('cache-snapshot') && !cacheHit) {
+ if (
+ core.getBooleanInput('cache-snapshot') &&
+ !cacheHit &&
+ !this.data.preventCaching
+ ) {
await fs.cp(tool, restore, {recursive: true})
await cache.saveCache([restore], key)
core.debug(`Saved to cache with key "${key}"`)
@@ -76,7 +86,7 @@ export abstract class ToolchainInstaller {
}
protected async download() {
- const url = `${this.baseUrl}/${this.data.download}`
+ const url = path.posix.join(this.baseUrl?.href, this.data.download)
core.debug(`Downloading snapshot from "${url}"`)
return await toolCache.downloadTool(url)
}
diff --git a/src/installer/verify.ts b/src/installer/verify.ts
index bec8b25..1153508 100644
--- a/src/installer/verify.ts
+++ b/src/installer/verify.ts
@@ -1,3 +1,4 @@
+import {posix} from 'path'
import * as core from '@actions/core'
import * as toolCache from '@actions/tool-cache'
import * as gpg from '../utils/gpg'
@@ -9,19 +10,20 @@ export abstract class VerifyingToolchainInstaller<
> extends ToolchainInstaller {
private get signatureUrl() {
const signature = this.data.download_signature
- return signature ? `${this.baseUrl}/${signature}` : undefined
+ return signature ? posix.join(this.baseUrl.href, signature) : undefined
}
private async downloadSignature() {
try {
- if (this.signatureUrl) {
- return await toolCache.downloadTool(this.signatureUrl)
- }
+ return this.signatureUrl
+ ? await toolCache.downloadTool(this.signatureUrl)
+ : undefined
} catch (error) {
if (
error instanceof toolCache.HTTPError &&
error.httpStatusCode === 404
) {
+ core.warning(`No signature at "${this.signatureUrl}"`)
return undefined
}
throw error
diff --git a/src/installer/windows/index.ts b/src/installer/windows/index.ts
index 9cf222f..226ef45 100644
--- a/src/installer/windows/index.ts
+++ b/src/installer/windows/index.ts
@@ -41,15 +41,27 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller
+
private sortSnapshots(snapshots: SnapshotForInstaller[]) {
return snapshots.sort((item1, item2) => {
const t1 = item1 as ToolchainSnapshot
@@ -65,6 +69,11 @@ export abstract class Platform<
async tools(
version: ToolchainVersion
): Promise[]> {
+ const verSnapshot = version.toolchainSnapshot(this.file)
+ if (verSnapshot) {
+ return [this.snapshotFor(verSnapshot)]
+ }
+
const snapshots = await this.releasedTools(version)
if (snapshots.length && !version.dev) {
return this.sortSnapshots(snapshots)
@@ -92,7 +101,8 @@ export abstract class Platform<
return {
...data,
platform: collection.platform,
- branch: collection.branch
+ branch: collection.branch,
+ preventCaching: false
} as SnapshotForInstaller
})
})
diff --git a/src/platform/linux.ts b/src/platform/linux.ts
index 0ea5c18..c67ae8f 100644
--- a/src/platform/linux.ts
+++ b/src/platform/linux.ts
@@ -2,7 +2,7 @@ import * as path from 'path'
import {promises as fs} from 'fs'
import {VersionedPlatform} from './versioned'
import {ToolchainVersion, SWIFT_BRANCH_REGEX} from '../version'
-import {LinuxToolchainSnapshot} from '../snapshot'
+import {LinuxToolchainSnapshot, ToolchainSnapshot} from '../snapshot'
import {LinuxToolchainInstaller} from '../installer'
import {MODULE_DIR} from '../const'
@@ -17,6 +17,10 @@ export class LinuxPlatform extends VersionedPlatform {
return content
}
+ snapshotFor(snapshot: ToolchainSnapshot) {
+ return {...snapshot, download_signature: `${snapshot.download}.sig`}
+ }
+
async tools(version: ToolchainVersion) {
let html: string
const tools = await super.tools(version)
diff --git a/src/platform/versioned.ts b/src/platform/versioned.ts
index ac8344e..212722c 100644
--- a/src/platform/versioned.ts
+++ b/src/platform/versioned.ts
@@ -119,7 +119,8 @@ export abstract class VersionedPlatform<
platform: pName + this.archSuffix,
branch: release.tag.toLocaleLowerCase(),
docker: platform.docker,
- windows: pName.startsWith('windows')
+ windows: pName.startsWith('windows'),
+ preventCaching: false
} as ToolchainSnapshot)
: []
})
diff --git a/src/platform/windows.ts b/src/platform/windows.ts
index e7a847b..8417991 100644
--- a/src/platform/windows.ts
+++ b/src/platform/windows.ts
@@ -1,12 +1,20 @@
import {VersionedPlatform} from './versioned'
import {WindowsToolchainInstaller} from '../installer'
-import {WindowsToolchainSnapshot} from '../snapshot'
+import {WindowsToolchainSnapshot, ToolchainSnapshot} from '../snapshot'
export class WindowsPlatform extends VersionedPlatform {
protected get downloadExtension() {
return 'exe'
}
+ snapshotFor(snapshot: ToolchainSnapshot) {
+ return {
+ ...snapshot,
+ download_signature: `${snapshot.download}.sig`,
+ windows: true
+ }
+ }
+
async install(data: WindowsToolchainSnapshot) {
const installer = new WindowsToolchainInstaller(data)
await installer.install(this.arch)
diff --git a/src/platform/xcode.ts b/src/platform/xcode.ts
index 7c79028..2b041f9 100644
--- a/src/platform/xcode.ts
+++ b/src/platform/xcode.ts
@@ -1,6 +1,7 @@
+import * as path from 'path'
import {Platform} from './base'
import {ToolchainVersion} from '../version'
-import {XcodeToolchainSnapshot} from '../snapshot'
+import {XcodeToolchainSnapshot, ToolchainSnapshot} from '../snapshot'
import {XcodeToolchainInstaller} from '../installer'
export class XcodePlatform extends Platform {
@@ -18,6 +19,15 @@ export class XcodePlatform extends Platform {
return this.name
}
+ snapshotFor(snapshot: ToolchainSnapshot) {
+ const fileExt = path.extname(snapshot.download)
+ const fileName = path.basename(snapshot.download, fileExt)
+ return {
+ ...snapshot,
+ debug_info: `${fileName}-symbols.${fileExt}`
+ }
+ }
+
protected async releasedTools(version: ToolchainVersion) {
const releases = await this.releases()
return releases
@@ -28,11 +38,12 @@ export class XcodePlatform extends Platform {
name: `Xcode Swift ${release.name}`,
date: release.date,
download: `${release.tag}-osx.pkg`,
- symbols: `${release.tag}-osx-symbols.pkg`,
+ debug_info: `${release.tag}-osx-symbols.pkg`,
dir: release.tag,
xcode: xMatch && xMatch.length > 1 ? xMatch[1] : undefined,
platform: this.name,
- branch: release.tag.toLocaleLowerCase()
+ branch: release.tag.toLocaleLowerCase(),
+ preventCaching: false
} as XcodeToolchainSnapshot
})
}
diff --git a/src/snapshot/base.ts b/src/snapshot/base.ts
index 07bb2db..6042f7b 100644
--- a/src/snapshot/base.ts
+++ b/src/snapshot/base.ts
@@ -1,3 +1,5 @@
+import {URL} from 'url'
+
export interface ToolchainSnapshot {
readonly name: string
readonly date: Date
@@ -5,4 +7,6 @@ export interface ToolchainSnapshot {
readonly dir: string
readonly platform: string
readonly branch: string
+ readonly baseUrl?: URL
+ readonly preventCaching: boolean
}
diff --git a/src/snapshot/xcode.ts b/src/snapshot/xcode.ts
index 4d66d2b..30cc427 100644
--- a/src/snapshot/xcode.ts
+++ b/src/snapshot/xcode.ts
@@ -1,6 +1,6 @@
import {ToolchainSnapshot} from './base'
export interface XcodeToolchainSnapshot extends ToolchainSnapshot {
- readonly symbols?: string
+ readonly debug_info?: string
readonly xcode?: string
}
diff --git a/src/utils/visual_studio/base.ts b/src/utils/visual_studio/base.ts
index a2598ce..c456690 100644
--- a/src/utils/visual_studio/base.ts
+++ b/src/utils/visual_studio/base.ts
@@ -10,7 +10,7 @@ export class VisualStudio {
readonly properties: VisualStudioProperties
) {}
- // eslint-disable-next-line no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
static createFromJSON(json: any) {
return new VisualStudio(
json.installationPath,
diff --git a/src/version/base.ts b/src/version/base.ts
index 2f69e87..d45586c 100644
--- a/src/version/base.ts
+++ b/src/version/base.ts
@@ -2,6 +2,7 @@ import * as path from 'path'
import * as core from '@actions/core'
import {glob} from 'glob'
import {MODULE_DIR} from '../const'
+import {ToolchainSnapshot} from '../snapshot'
export const SWIFT_RELEASE_REGEX = /swift-(.*)-release/
@@ -9,10 +10,20 @@ export abstract class ToolchainVersion {
protected abstract readonly dirGlob: string
protected abstract readonly dirRegex: RegExp
+ get requiresSwiftOrg() {
+ return true
+ }
+
constructor(readonly dev: boolean) {}
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ toolchainSnapshot(platform: string): ToolchainSnapshot | undefined {
+ return undefined
+ }
+
async toolFiles(fileGlob: string) {
- const pattern = `swiftorg/_data/builds/${this.dirGlob}/${fileGlob}.yml`
+ const builds = 'swiftorg/_data/builds'
+ const pattern = path.posix.join(builds, this.dirGlob, `${fileGlob}.yml`)
core.debug(`Searching for glob "${pattern}"`)
let files = await glob(pattern, {absolute: true, cwd: MODULE_DIR})
core.debug(`Retrieved files "${files}" for glob "${pattern}"`)
diff --git a/src/version/index.ts b/src/version/index.ts
index c01e8a9..a928e96 100644
--- a/src/version/index.ts
+++ b/src/version/index.ts
@@ -1,9 +1,11 @@
+import {URL} from 'url'
import * as core from '@actions/core'
import {SemVer, coerce as parseSemVer} from 'semver'
import {ToolchainVersion} from './base'
import {LatestToolchainVersion} from './latest'
import {SemanticToolchainVersion} from './semver'
import {ToolchainSnapshotName, DEVELOPMENT_SNAPSHOT} from './name'
+import {ToolchainSnapshotLocation} from './location'
declare module './base' {
// eslint-disable-next-line no-shadow
@@ -13,6 +15,13 @@ declare module './base' {
}
ToolchainVersion.create = (requested: string, dev = false) => {
+ try {
+ const toolchainUrl = new URL(requested)
+ return new ToolchainSnapshotLocation(toolchainUrl, dev)
+ } catch {
+ core.debug(`Input "${requested}" not an URL`)
+ }
+
if (requested === 'latest' || requested === 'current') {
core.debug(`Using latest ${dev ? 'development ' : ''}toolchain requirement`)
return new LatestToolchainVersion(dev)
@@ -47,3 +56,4 @@ export * from './base'
export * from './latest'
export * from './semver'
export * from './name'
+export * from './location'
diff --git a/src/version/location.ts b/src/version/location.ts
new file mode 100644
index 0000000..c02e8b4
--- /dev/null
+++ b/src/version/location.ts
@@ -0,0 +1,46 @@
+import {URL} from 'url'
+import {posix} from 'path'
+import {ToolchainVersion} from './base'
+
+export class ToolchainSnapshotLocation extends ToolchainVersion {
+ constructor(
+ readonly url: URL,
+ dev: boolean
+ ) {
+ super(dev)
+ }
+
+ protected get dirGlob() {
+ return ''
+ }
+
+ protected get dirRegex() {
+ return /a^/
+ }
+
+ get requiresSwiftOrg() {
+ return false
+ }
+
+ toolchainSnapshot(platform: string) {
+ try {
+ const baseUrl = posix.dirname(this.url.href)
+ return {
+ name: 'Swift Custom Snapshot',
+ date: new Date(),
+ download: posix.basename(this.url.href),
+ dir: posix.basename(baseUrl),
+ platform,
+ branch: this.url.pathname.split(posix.sep)[1],
+ baseUrl: new URL(baseUrl),
+ preventCaching: true
+ }
+ } catch (e) {
+ throw new Error(`Swift resource: "${this.url}" failed with error ${e}`)
+ }
+ }
+
+ toString() {
+ return `url: "${this.url}", dev: ${this.dev}`
+ }
+}
diff --git a/tsconfig.base.json b/tsconfig.base.json
new file mode 100644
index 0000000..e7634c5
--- /dev/null
+++ b/tsconfig.base.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "strict": true,
+ "noImplicitAny": true,
+ "esModuleInterop": true,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noImplicitReturns": true,
+ "lib": [
+ "ES2021.String",
+ ]
+ },
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/tsconfig.json b/tsconfig.json
index 3baa27a..8516854 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,19 +1,10 @@
{
+ "extends": "./tsconfig.base.json",
"compilerOptions": {
- "target": "es6",
- "module": "nodenext",
- "moduleResolution": "nodenext",
"outDir": "lib",
- "rootDir": "src",
- "strict": true,
- "noImplicitAny": true,
- "esModuleInterop": true,
- "lib": [
- "ES2021.String",
- ]
+ "rootDir": "src"
},
"exclude": [
- "node_modules",
"**/*.test.ts",
"**/__mocks__/*",
"lib",