From c3c31067a47b15b085d165f4cf7ef8aa8802d6e8 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Fri, 14 Nov 2025 10:32:28 -0800 Subject: [PATCH 1/3] [CI] GitHub Actions support for PR testing and automerger (#526) * [CI] GitHub Actions support for PR testing and automerger * Fix python lint failures * Drop License header check and unacceptable lang from GitHub Actions * Don't run linux test in parallel * Update the linux actions to build only for now. * Split up the line to avoid length issue with python linter * Only build for Windows and disable the static sdk for now --- .github/workflows/automerge.yml | 23 ++++++++++++++++++ .github/workflows/pull_request.yml | 39 ++++++++++++++++++++++++++++++ Utilities/build-script-helper.py | 38 +++++++++++++++++++++++------ 3 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/automerge.yml create mode 100644 .github/workflows/pull_request.yml diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 00000000..699967f7 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,23 @@ +name: Create PR to merge release into main branch +# In the first period after branching the release branch, +# we typically want to include many changes from `main` in the release branch. +# This workflow automatically creates a PR to merge the release branch into the main. +# Later in the release cycle we should stop this practice to avoid landing risky changes by disabling this workflow. +# To do so, disable the workflow as described in https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/disabling-and-enabling-a-workflow +permissions: + contents: read +on: + schedule: + - cron: '0 9 * * MON' + workflow_dispatch: +jobs: + create_merge_pr: + name: Create PR to merge release into main branch + uses: swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml@main + with: + head_branch: release/6.3 + base_branch: main + permissions: + contents: write + pull-requests: write + if: (github.event_name == 'schedule' && github.repository == 'swiftlang/swift-tools-support-core') || (github.event_name != 'schedule') # Ensure that we don't run this on a schedule in a fork diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000..c81ce761 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,39 @@ +name: Pull request + +permissions: + contents: read + +on: + pull_request: + types: [opened, reopened, synchronize] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + tests: + name: Test + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + with: + linux_os_versions: '["amazonlinux2", "bookworm", "noble", "jammy", "rhel-ubi9"]' + linux_swift_versions: '["nightly-main", "nightly-6.2"]' + linux_build_command: 'swift build' + windows_swift_versions: '["nightly-main"]' + windows_build_command: 'Invoke-Program swift build' + enable_android_sdk_build: true + android_sdk_build_command: "swift build --build-tests" + android_ndk_versions: '["r27d", "r29"]' + enable_ios_checks: true + enable_macos_checks: true + macos_exclude_xcode_versions: "[{\"xcode_version\": \"16.3\"}, {\"xcode_version\": \"16.4\"}]" + + soundness: + name: Soundness + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + license_header_check_project_name: "Swift.org" + license_header_check_enabled: false + unacceptable_language_check_enabled: false + api_breakage_check_enabled: false + format_check_enabled: false diff --git a/Utilities/build-script-helper.py b/Utilities/build-script-helper.py index f1357871..3bc4f5aa 100755 --- a/Utilities/build-script-helper.py +++ b/Utilities/build-script-helper.py @@ -15,25 +15,24 @@ from __future__ import print_function import argparse -import json +import errno import os import platform -import re -import shutil -import subprocess import subprocess import sys -import errno + def note(message): print("--- %s: note: %s" % (os.path.basename(sys.argv[0]), message)) sys.stdout.flush() + def error(message): print("--- %s: error: %s" % (os.path.basename(sys.argv[0]), message)) sys.stdout.flush() raise SystemExit(1) + def mkdir_p(path): """Create the given directory, if it does not exist.""" try: @@ -43,6 +42,7 @@ def mkdir_p(path): if e.errno != errno.EEXIST: raise + def call(cmd, cwd=None, verbose=False): """Calls a subprocess.""" if verbose: @@ -54,17 +54,22 @@ def call(cmd, cwd=None, verbose=False): print(' '.join(cmd)) error(str(e)) + def call_output(cmd, cwd=None, stderr=False, verbose=False): """Calls a subprocess for its return data.""" if verbose: print(' '.join(cmd)) try: - return subprocess.check_output(cmd, cwd=cwd, stderr=stderr, universal_newlines=True).strip() + return subprocess.check_output(cmd, + cwd=cwd, + stderr=stderr, + universal_newlines=True).strip() except Exception as e: if not verbose: print(' '.join(cmd)) error(str(e)) + def main(): parser = argparse.ArgumentParser(description=""" This script will build a TSC using CMake. @@ -84,6 +89,7 @@ def main(): # Argument parsing # ----------------------------------------------------------- + def add_global_args(parser): """Configures the parser with the arguments necessary for all actions.""" parser.add_argument( @@ -100,6 +106,7 @@ def add_global_args(parser): action="store_true", help="whether to always reconfigure cmake") + def add_build_args(parser): """Configures the parser with the arguments necessary for build-related actions.""" add_global_args(parser) @@ -116,16 +123,22 @@ def add_build_args(parser): metavar='PATH', help='path to the ninja binary to use for building with CMake') + def parse_global_args(args): """Parses and cleans arguments necessary for all actions.""" args.build_dir = os.path.abspath(args.build_dir) args.project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if platform.system() == 'Darwin': - args.sysroot = call_output(["xcrun", "--sdk", "macosx", "--show-sdk-path"], verbose=args.verbose) + args.sysroot = call_output(["xcrun", + "--sdk", + "macosx", + "--show-sdk-path"], + verbose=args.verbose) else: args.sysroot = None + def parse_build_args(args): """Parses and cleans arguments necessary for build-related actions.""" parse_global_args(args) @@ -134,6 +147,7 @@ def parse_build_args(args): args.cmake_path = get_cmake_path(args) args.ninja_path = get_ninja_path(args) + def get_swiftc_path(args): """Returns the path to the Swift compiler.""" if args.swiftc_path: @@ -154,6 +168,7 @@ def get_swiftc_path(args): return swiftc_path + def get_cmake_path(args): """Returns the path to CMake.""" if args.cmake_path: @@ -167,6 +182,7 @@ def get_cmake_path(args): else: return call_output(["which", "cmake"], verbose=args.verbose) + def get_ninja_path(args): """Returns the path to Ninja.""" if args.ninja_path: @@ -184,6 +200,7 @@ def get_ninja_path(args): # Actions # ----------------------------------------------------------- + def build(args): parse_build_args(args) build_tsc(args) @@ -192,10 +209,13 @@ def build(args): # Build functions # ----------------------------------------------------------- + def build_with_cmake(args, cmake_args, source_path, build_dir): """Runs CMake if needed, then builds with Ninja.""" cache_path = os.path.join(build_dir, "CMakeCache.txt") - if args.reconfigure or not os.path.isfile(cache_path) or not args.swiftc_path in open(cache_path).read(): + if args.reconfigure or \ + not os.path.isfile(cache_path) \ + or args.swiftc_path not in open(cache_path).read(): swift_flags = "" if args.sysroot: swift_flags = "-sdk %s" % args.sysroot @@ -222,6 +242,7 @@ def build_with_cmake(args, cmake_args, source_path, build_dir): call(ninja_cmd, cwd=build_dir, verbose=args.verbose) + def build_tsc(args): cmake_flags = [] if platform.system() == 'Darwin': @@ -230,5 +251,6 @@ def build_tsc(args): build_with_cmake(args, cmake_flags, args.project_root, args.build_dir) + if __name__ == '__main__': main() From ce3979d5303244719b5877b2493ae6e02ad23588 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Mon, 17 Nov 2025 17:49:18 -0800 Subject: [PATCH 2/3] Update automerge workflow to merge main into release (#528) * Update automerge workflow to merge main into release * Update .github/workflows/automerge.yml Co-authored-by: Owen Voorhees --------- Co-authored-by: Owen Voorhees --- .github/workflows/automerge.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 699967f7..d24b8173 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,7 +1,7 @@ -name: Create PR to merge release into main branch +name: Create PR to merge main into release branch # In the first period after branching the release branch, # we typically want to include many changes from `main` in the release branch. -# This workflow automatically creates a PR to merge the release branch into the main. +# This workflow automatically creates a PR to merge the main into the release branch. # Later in the release cycle we should stop this practice to avoid landing risky changes by disabling this workflow. # To do so, disable the workflow as described in https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/disabling-and-enabling-a-workflow permissions: @@ -12,11 +12,11 @@ on: workflow_dispatch: jobs: create_merge_pr: - name: Create PR to merge release into main branch + name: Create PR to merge main into release branch uses: swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml@main with: - head_branch: release/6.3 - base_branch: main + head_branch: main + base_branch: release/6.3 permissions: contents: write pull-requests: write From b157c62a8e2d4cc01089c222e8cd5c5a89be5728 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Wed, 19 Nov 2025 11:03:58 -0800 Subject: [PATCH 3/3] Add static linux SDK actions coverage (#527) --- .github/workflows/pull_request.yml | 2 ++ Package.swift | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c81ce761..fbbee69d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -19,6 +19,8 @@ jobs: linux_os_versions: '["amazonlinux2", "bookworm", "noble", "jammy", "rhel-ubi9"]' linux_swift_versions: '["nightly-main", "nightly-6.2"]' linux_build_command: 'swift build' + enable_linux_static_sdk_build: true + linux_static_sdk_build_command: SWIFTTOOLSSUPPORTCORE_STATIC_LINK=1 swift build windows_swift_versions: '["nightly-main"]' windows_build_command: 'Invoke-Program swift build' enable_android_sdk_build: true diff --git a/Package.swift b/Package.swift index 16a036b3..18ece6db 100644 --- a/Package.swift +++ b/Package.swift @@ -27,6 +27,8 @@ if let deploymentTarget = ProcessInfo.processInfo.environment["SWIFTTSC_IOS_DEPL iOSPlatform = .iOS(.v13) } +let isStaticBuild = ProcessInfo.processInfo.environment["SWIFTTOOLSSUPPORTCORE_STATIC_LINK"] != nil + let CMakeFiles = ["CMakeLists.txt"] let package = Package( @@ -115,3 +117,12 @@ let package = Package( exclude: ["pkgconfigInputs", "Inputs"]), ] ) + +if isStaticBuild { + package.targets = package.targets.filter { target in + target.type != .test && !target.name.hasSuffix("TestSupport") + } + package.products = package.products.filter { product in + !product.name.hasSuffix("TestSupport") && product.name != "SwiftToolsSupport" + } +}