Skip to content

Commit a65e158

Browse files
Wire Swift versioning and Linux-first CI
1 parent 9a7c1f4 commit a65e158

6 files changed

Lines changed: 167 additions & 16 deletions

File tree

.github/workflows/check-codegen.yml

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,17 @@ jobs:
3232
- name: Check existing swagger specification is up-to-date
3333
run: curl https://api.aspose.cloud/v4.0/barcode/swagger/spec | diff --strip-trailing-cr -y --suppress-common-lines spec/aspose-barcode-cloud.json -
3434

35-
check-swift-codegen:
36-
runs-on: macos-latest
35+
check-swift-codegen-linux:
36+
runs-on: ubuntu-latest
37+
needs: [check-submodules]
38+
container:
39+
image: swift:6.0
3740
steps:
3841
- uses: actions/checkout@v6
3942

43+
- name: Install Linux CI tools
44+
run: apt-get update && apt-get install -y make openssh-client python3
45+
4046
- name: Checkout submodules
4147
env:
4248
SWIFT_SUBMODULE_DEPLOY_KEY: ${{ secrets.SWIFT_SUBMODULE_DEPLOY_KEY }}
@@ -56,12 +62,38 @@ jobs:
5662
- name: Check Swift SDK generation is reproducible
5763
run: git diff --exit-code
5864

59-
- name: Run Swift tests
65+
- name: Build Swift example
6066
working-directory: submodules/swift
61-
run: make test
67+
run: swift build --product GenerateAndScanExample
6268

6369
- name: Run Swift live integration tests
6470
working-directory: submodules/swift
6571
run: make integration-test
6672
env:
6773
TEST_CONFIGURATION_ACCESS_TOKEN: ${{ secrets.TEST_CONFIGURATION_ACCESS_TOKEN }}
74+
75+
check-swift-macos:
76+
runs-on: macos-latest
77+
needs: [check-swift-codegen-linux]
78+
steps:
79+
- uses: actions/checkout@v6
80+
81+
- name: Checkout submodules
82+
env:
83+
SWIFT_SUBMODULE_DEPLOY_KEY: ${{ secrets.SWIFT_SUBMODULE_DEPLOY_KEY }}
84+
run: ./scripts/checkout-submodules.bash
85+
86+
- name: Show Swift version
87+
run: swift --version
88+
89+
- name: Build Swift SDK
90+
working-directory: submodules/swift
91+
run: make build
92+
93+
- name: Run Swift tests
94+
working-directory: submodules/swift
95+
run: make test
96+
97+
- name: Build Swift example
98+
working-directory: submodules/swift
99+
run: swift build --product GenerateAndScanExample
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import print_function
4+
5+
import json
6+
import re
7+
import sys
8+
from pathlib import Path
9+
10+
11+
def replace_once(path, old, new):
12+
text = path.read_text(encoding="utf-8")
13+
count = text.count(old)
14+
if count != 1:
15+
raise RuntimeError("Expected exactly one match in {0}, found {1}".format(path, count))
16+
path.write_text(text.replace(old, new), encoding="utf-8")
17+
18+
19+
def replace_regex_once(path, pattern, replacement):
20+
text = path.read_text(encoding="utf-8")
21+
text, count = re.subn(pattern, replacement, text, count=1)
22+
if count != 1:
23+
raise RuntimeError("Expected exactly one regex match in {0}, found {1}".format(path, count))
24+
path.write_text(text, encoding="utf-8")
25+
26+
27+
def append_once(path, marker, block):
28+
text = path.read_text(encoding="utf-8")
29+
if marker in text:
30+
return
31+
path.write_text(text.rstrip() + "\n\n" + block + "\n", encoding="utf-8")
32+
33+
34+
def patch_url_session(sources_dir):
35+
url_session = sources_dir / "URLSessionImplementations.swift"
36+
37+
replace_once(
38+
url_session,
39+
"import Foundation\n#if !os(macOS)\nimport MobileCoreServices\n#endif",
40+
"import Foundation\n"
41+
"#if canImport(FoundationNetworking)\n"
42+
"import FoundationNetworking\n"
43+
"#endif\n"
44+
"#if canImport(MobileCoreServices)\n"
45+
"import MobileCoreServices\n"
46+
"#endif",
47+
)
48+
49+
replace_once(
50+
url_session,
51+
" } else {\n"
52+
" if let uti = UTTypeCreatePreferredIdentifierForTag",
53+
" } else {\n"
54+
" #if canImport(MobileCoreServices)\n"
55+
" if let uti = UTTypeCreatePreferredIdentifierForTag",
56+
)
57+
58+
replace_once(
59+
url_session,
60+
" return mimetype as String\n"
61+
" }\n"
62+
" return \"application/octet-stream\"",
63+
" return mimetype as String\n"
64+
" }\n"
65+
" #endif\n"
66+
" return \"application/octet-stream\"",
67+
)
68+
69+
replace_regex_once(
70+
url_session,
71+
r"\n #else\n return \"application/octet-stream\"\s*\n #endif",
72+
"\n #endif",
73+
)
74+
75+
replace_once(url_session, "private class SessionDelegate", "private final class SessionDelegate")
76+
77+
78+
def patch_extensions(sources_dir):
79+
replace_once(
80+
sources_dir / "Extensions.swift",
81+
"extension String: CodingKey {",
82+
"extension Swift.String: Swift.CodingKey {",
83+
)
84+
85+
86+
def patch_date_formatter(sources_dir):
87+
append_once(
88+
sources_dir / "OpenISO8601DateFormatter.swift",
89+
"extension OpenISO8601DateFormatter: @unchecked Sendable",
90+
"#if compiler(>=5.5)\n"
91+
"extension OpenISO8601DateFormatter: @unchecked Sendable {}\n"
92+
"#endif",
93+
)
94+
95+
96+
def patch_client_version(sources_dir, package_version):
97+
replace_regex_once(
98+
sources_dir / "AsposeBarcodeCloudClient.swift",
99+
r'public static let defaultSdkVersion = "[^"]+"',
100+
'public static let defaultSdkVersion = "{0}"'.format(package_version),
101+
)
102+
103+
104+
def main(target_dir, config_path):
105+
config = json.loads(Path(config_path).read_text(encoding="utf-8"))
106+
package_version = config.get("packageVersion")
107+
if not package_version:
108+
raise RuntimeError("config-swift.json must define packageVersion")
109+
110+
sources_dir = Path(target_dir) / "Sources" / "AsposeBarcodeCloud"
111+
patch_url_session(sources_dir)
112+
patch_extensions(sources_dir)
113+
patch_date_formatter(sources_dir)
114+
patch_client_version(sources_dir, package_version)
115+
116+
117+
if __name__ == "__main__":
118+
if len(sys.argv) != 3:
119+
print("Usage: patch-swift-generated.py <target-dir> <config-swift.json>", file=sys.stderr)
120+
sys.exit(2)
121+
main(sys.argv[1], sys.argv[2])

codegen/config-swift.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"enumUnknownDefaultCase": true,
44
"hideGenerationTimestamp": true,
55
"mapFileBinaryToData": true,
6+
"packageVersion": "26.4.0",
67
"projectName": "AsposeBarcodeCloud",
78
"swiftPackagePath": "Sources/AsposeBarcodeCloud",
89
"useClasses": true,

codegen/generate-swift.bash

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,8 @@ mkdir -p "$targetDir/Sources"
1919
rm -rf "$targetDir/Sources/AsposeBarcodeCloud"
2020
mv "$tempDir/Sources/AsposeBarcodeCloud" "$targetDir/Sources/AsposeBarcodeCloud"
2121

22-
# OpenAPI Generator 7.8.0 emits Apple-only imports for the URLSession client
23-
# when compiling on Linux. Keep the generated client SwiftPM-compatible in WSL.
24-
perl -0pi -e 's/import Foundation\n#if !os\(macOS\)\nimport MobileCoreServices\n#endif/import Foundation\n#if canImport(FoundationNetworking)\nimport FoundationNetworking\n#endif\n#if canImport(MobileCoreServices)\nimport MobileCoreServices\n#endif/' "$targetDir/Sources/AsposeBarcodeCloud/URLSessionImplementations.swift"
25-
perl -0pi -e 's/ } else {\n if let uti = UTTypeCreatePreferredIdentifierForTag/ } else {\n #if canImport(MobileCoreServices)\n if let uti = UTTypeCreatePreferredIdentifierForTag/' "$targetDir/Sources/AsposeBarcodeCloud/URLSessionImplementations.swift"
26-
perl -0pi -e 's/ return mimetype as String\n }\n return "application\/octet-stream"/ return mimetype as String\n }\n #endif\n return "application\/octet-stream"/' "$targetDir/Sources/AsposeBarcodeCloud/URLSessionImplementations.swift"
27-
28-
# Keep the generated runtime warning-free under current Swift toolchains.
29-
perl -0pi -e 's/extension String: CodingKey \{/extension Swift.String: Swift.CodingKey {/' "$targetDir/Sources/AsposeBarcodeCloud/Extensions.swift"
30-
perl -0pi -e 's/}\s*\z/}\n\n#if compiler(>=5.5)\nextension OpenISO8601DateFormatter: \@unchecked Sendable {}\n#endif\n/' "$targetDir/Sources/AsposeBarcodeCloud/OpenISO8601DateFormatter.swift"
31-
perl -0pi -e 's/\n #else\n return "application\/octet-stream"\s*\n #endif/\n #endif/' "$targetDir/Sources/AsposeBarcodeCloud/URLSessionImplementations.swift"
32-
perl -0pi -e 's/private class SessionDelegate/private final class SessionDelegate/' "$targetDir/Sources/AsposeBarcodeCloud/URLSessionImplementations.swift"
3322
cp Support/swift/*.swift "$targetDir/Sources/AsposeBarcodeCloud/"
23+
python3 Tools/patch-swift-generated.py "$targetDir" config-swift.json
3424

3525
rm -rf "$targetDir/docs"
3626
mv "$tempDir/docs" "$targetDir/docs"

scripts/new-version.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ def set_python_version(new_version, filename=os.path.join(BASE_CONFIG_DIR, "conf
6666
save_config(config, filename)
6767

6868

69+
def set_swift_version(new_version, filename=os.path.join(BASE_CONFIG_DIR, "config-swift.json")):
70+
config = read_config(filename)
71+
config["packageVersion"] = str.join(".", map(str, new_version))
72+
save_config(config, filename)
73+
74+
6975
def read_config(filename):
7076
with open(filename, "rb") as rf:
7177
config = json.load(rf)
@@ -90,6 +96,7 @@ def main(new_versions):
9096
set_node_version(new_version)
9197
set_php_version(new_version)
9298
set_python_version(new_version)
99+
set_swift_version(new_version)
93100

94101

95102
def parse_args():

0 commit comments

Comments
 (0)