From 39ee6a2efda73fb89ee6019f4ec356e8a3bb6db5 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 24 Oct 2024 06:59:26 -0700 Subject: [PATCH 1/6] Run Windows tests before tagging a release The GitHub workflows enabled Windows in the testing matrix. We needed to port the pre-build commands that apply the release commits to Windows to make the Windows checks pass. --- .github/workflows/create-release-commits.sh | 28 ------ .github/workflows/publish_release.yml | 99 +++++++++++++++++---- 2 files changed, 81 insertions(+), 46 deletions(-) delete mode 100755 .github/workflows/create-release-commits.sh diff --git a/.github/workflows/create-release-commits.sh b/.github/workflows/create-release-commits.sh deleted file mode 100755 index 81fa8eba..00000000 --- a/.github/workflows/create-release-commits.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -SWIFT_SYNTAX_TAG="$1" -SWIFT_FORMAT_VERSION="$2" - -if [[ -z "$SWIFT_SYNTAX_TAG" || -z "$SWIFT_FORMAT_VERSION" ]]; then - echo "Update the Package manifest to reference a specific version of swift-syntax and embed the given version in the swift-format --version command" - echo "Usage create-release-commits.sh " - echo " SWIFT_SYNTAX_TAG: The tag of swift-syntax to depend on" - echo " SWIFT_FORMAT_VERSION: The version of swift-format that is about to be released" - exit 1 -fi - -# Without this, we can't perform git operations in GitHub actions. -git config --global --add safe.directory "$(realpath .)" - -git config --local user.name 'swift-ci' -git config --local user.email 'swift-ci@users.noreply.github.com' - -sed -E -i "s#branch: \"(main|release/[0-9]+\.[0-9]+)\"#from: \"$SWIFT_SYNTAX_TAG\"#" Package.swift -git add Package.swift -git commit -m "Change swift-syntax dependency to $SWIFT_SYNTAX_TAG" - -sed -E -i "s#print\(\".*\"\)#print\(\"$SWIFT_FORMAT_VERSION\"\)#" Sources/swift-format/PrintVersion.swift -git add Sources/swift-format/PrintVersion.swift -git commit -m "Change version to $SWIFT_FORMAT_VERSION" diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 2528ebf6..2081696e 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -34,12 +34,12 @@ jobs: echo "${{ github.triggering_actor }} is not allowed to create a release" exit 1 fi - define_tags: - name: Determine dependent swift-syntax version and prerelease date + create_release_commits: + name: Create release commits runs-on: ubuntu-latest outputs: - swift_syntax_tag: ${{ steps.swift_syntax_tag.outputs.swift_syntax_tag }} swift_format_version: ${{ steps.swift_format_version.outputs.swift_format_version }} + release_commit_patch: ${{ steps.create_release_commits.outputs.release_commit_patch }} steps: - name: Determine swift-syntax tag to depend on id: swift_syntax_tag @@ -65,37 +65,100 @@ jobs: fi echo "Using swift-format version: $SWIFT_FORMAT_VERSION" echo "swift_format_version=$SWIFT_FORMAT_VERSION" >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@v4 + - name: Create release commits + id: create_release_commits + run: | + # Without this, we can't perform git operations in GitHub actions. + git config --global --add safe.directory "$(realpath .)" + git config --local user.name 'swift-ci' + git config --local user.email 'swift-ci@users.noreply.github.com' + + BASE_COMMIT=$(git rev-parse HEAD) + + sed -E -i "s#branch: \"(main|release/[0-9]+\.[0-9]+)\"#from: \"${{ steps.swift_syntax_tag.outputs.swift_syntax_tag }}\"#" Package.swift + git add Package.swift + git commit -m "Change swift-syntax dependency to ${{ steps.swift_syntax_tag.outputs.swift_syntax_tag }}" + + sed -E -i "s#print\(\".*\"\)#print\(\"${{ steps.swift_format_version.outputs.swift_format_version }}\"\)#" Sources/swift-format/PrintVersion.swift + git add Sources/swift-format/PrintVersion.swift + git commit -m "Change version to ${{ steps.swift_format_version.outputs.swift_format_version }}" + + { + echo 'release_commit_patch<> "$GITHUB_OUTPUT" test_debug: name: Test in Debug configuration - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main - needs: define_tags + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@windows-pre-build + needs: create_release_commits with: - pre_build_command: bash .github/workflows/create-release-commits.sh '${{ needs.define_tags.outputs.swift_syntax_tag }}' '${{ needs.define_tags.outputs.swift_format_version }}' + linux_pre_build_command: | + git config --global --add safe.directory "$(realpath .)" + git config --local user.name 'swift-ci' + git config --local user.email 'swift-ci@users.noreply.github.com' + git am << EOF + ${{ needs.create_release_commits.outputs.release_commit_patch }} + EOF + windows_pre_build_command: | + git config --local user.name "swift-ci" + git config --local user.email "swift-ci@users.noreply.github.com" + echo @" + ${{ needs.create_release_commits.outputs.release_commit_patch }} + "@ > $env:TEMP\patch.diff + # For some reason `git am` fails in Powershell with the following error. Executing it in cmd works... + # fatal: empty ident name (for <>) not allowed + cmd /c "type $env:TEMP\patch.diff | git am || (exit /b 1)" # We require that releases of swift-format build without warnings - build_command: swift test -Xswiftc -warnings-as-errors + linux_build_command: swift test -Xswiftc -warnings-as-errors + windows_build_command: swift test -Xswiftc -warnings-as-errors test_release: name: Test in Release configuration - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main - needs: define_tags + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@windows-pre-build + needs: create_release_commits with: - pre_build_command: bash .github/workflows/create-release-commits.sh '${{ needs.define_tags.outputs.swift_syntax_tag }}' '${{ needs.define_tags.outputs.swift_format_version }}' + linux_pre_build_command: | + git config --global --add safe.directory "$(realpath .)" + git config --local user.name 'swift-ci' + git config --local user.email 'swift-ci@users.noreply.github.com' + git am << EOF + ${{ needs.create_release_commits.outputs.release_commit_patch }} + EOF + windows_pre_build_command: | + git config --local user.name "swift-ci" + git config --local user.email "swift-ci@users.noreply.github.com" + echo @" + ${{ needs.create_release_commits.outputs.release_commit_patch }} + "@ > $env:TEMP\patch.diff + # For some reason `git am` fails in Powershell with the following error. Executing it in cmd works... + # fatal: empty ident name (for <>) not allowed + cmd /c "type $env:TEMP\patch.diff | git am || (exit /b 1)" # We require that releases of swift-format build without warnings - build_command: swift test -c release -Xswiftc -warnings-as-errors + linux_build_command: swift test -Xswiftc -warnings-as-errors + windows_build_command: swift test -Xswiftc -warnings-as-errors create_tag: name: Create Tag runs-on: ubuntu-latest - needs: [check_triggering_actor, test_debug, test_release, define_tags] + needs: [check_triggering_actor, test_debug, create_release_commits] permissions: contents: write steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Create release commits - run: bash .github/workflows/create-release-commits.sh '${{ needs.define_tags.outputs.swift_syntax_tag }}' '${{ needs.define_tags.outputs.swift_format_version }}' + - name: Apply release commits + run: | + git config --global --add safe.directory "$(realpath .)" + git config --local user.name 'swift-ci' + git config --local user.email 'swift-ci@users.noreply.github.com' + git am << EOF + ${{ needs.create_release_commits.outputs.release_commit_patch }} + EOF - name: Tag release run: | - git tag "${{ needs.define_tags.outputs.swift_format_version }}" - git push origin "${{ needs.define_tags.outputs.swift_format_version }}" + git tag "${{ needs.create_release_commits.outputs.swift_format_version }}" + git push origin "${{ needs.create_release_commits.outputs.swift_format_version }}" - name: Create release env: GH_TOKEN: ${{ github.token }} @@ -104,6 +167,6 @@ jobs: # Only create a release automatically for prereleases. For real releases, release notes should be crafted by hand. exit fi - gh release create "${{ needs.define_tags.outputs.swift_format_version }}" \ - --title "${{ needs.define_tags.outputs.swift_format_version }}" \ + gh release create "${{ needs.create_release_commits.outputs.swift_format_version }}" \ + --title "${{ needs.create_release_commits.outputs.swift_format_version }}" \ --prerelease From ce212cab75d84524c66757d597b165a7d353c36d Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 24 Oct 2024 08:42:44 -0700 Subject: [PATCH 2/6] Use matrix to run debug and release --- .github/workflows/publish_release.yml | 40 +++++++-------------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 2081696e..03c4f04f 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -90,10 +90,14 @@ jobs: git format-patch "$BASE_COMMIT"..HEAD --stdout echo EOF } >> "$GITHUB_OUTPUT" - test_debug: - name: Test in Debug configuration - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@windows-pre-build + test: + name: Test in ${{ matrix.release && 'Release' || 'Debug' }} configuration + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main needs: create_release_commits + strategy: + fail-fast: false + matrix: + release: [true, false] with: linux_pre_build_command: | git config --global --add safe.directory "$(realpath .)" @@ -112,36 +116,12 @@ jobs: # fatal: empty ident name (for <>) not allowed cmd /c "type $env:TEMP\patch.diff | git am || (exit /b 1)" # We require that releases of swift-format build without warnings - linux_build_command: swift test -Xswiftc -warnings-as-errors - windows_build_command: swift test -Xswiftc -warnings-as-errors - test_release: - name: Test in Release configuration - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@windows-pre-build - needs: create_release_commits - with: - linux_pre_build_command: | - git config --global --add safe.directory "$(realpath .)" - git config --local user.name 'swift-ci' - git config --local user.email 'swift-ci@users.noreply.github.com' - git am << EOF - ${{ needs.create_release_commits.outputs.release_commit_patch }} - EOF - windows_pre_build_command: | - git config --local user.name "swift-ci" - git config --local user.email "swift-ci@users.noreply.github.com" - echo @" - ${{ needs.create_release_commits.outputs.release_commit_patch }} - "@ > $env:TEMP\patch.diff - # For some reason `git am` fails in Powershell with the following error. Executing it in cmd works... - # fatal: empty ident name (for <>) not allowed - cmd /c "type $env:TEMP\patch.diff | git am || (exit /b 1)" - # We require that releases of swift-format build without warnings - linux_build_command: swift test -Xswiftc -warnings-as-errors - windows_build_command: swift test -Xswiftc -warnings-as-errors + linux_build_command: swift test -Xswiftc -warnings-as-errors ${{ matrix.release && '-c release' }} + windows_build_command: swift test -Xswiftc -warnings-as-errors ${{ matrix.release && '-c release' }} create_tag: name: Create Tag runs-on: ubuntu-latest - needs: [check_triggering_actor, test_debug, create_release_commits] + needs: [check_triggering_actor, test, create_release_commits] permissions: contents: write steps: From e671366565f9c30456fbb06524fa31e6460a146f Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 24 Oct 2024 14:30:41 -0700 Subject: [PATCH 3/6] Use my fork --- .github/workflows/publish_release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 03c4f04f..4ac97ecd 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -92,12 +92,12 @@ jobs: } >> "$GITHUB_OUTPUT" test: name: Test in ${{ matrix.release && 'Release' || 'Debug' }} configuration - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: ahoppen/github-workflows/.github/workflows/swift_package_test.yml@windows-5.10 needs: create_release_commits strategy: fail-fast: false matrix: - release: [true, false] + release: [false] with: linux_pre_build_command: | git config --global --add safe.directory "$(realpath .)" From d82d73657756d05a3bda25da79842b8acc7eca6b Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 25 Oct 2024 12:59:59 -0700 Subject: [PATCH 4/6] Prepare for integer generics with new generic argument node --- .../Rules/UseShorthandTypeNames.swift | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift b/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift index dc101a01..67a8d8aa 100644 --- a/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift +++ b/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift @@ -47,24 +47,28 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { switch node.name.text { case "Array": - guard let typeArgument = genericArgumentList.firstAndOnly else { + guard let argument = genericArgumentList.firstAndOnly, + case .type(let typeArgument) = argument else { newNode = nil break } + newNode = shorthandArrayType( - element: typeArgument.argument, + element: typeArgument, leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia ) case "Dictionary": - guard let typeArguments = exactlyTwoChildren(of: genericArgumentList) else { + guard let arguments = exactlyTwoChildren(of: genericArgumentList), + case .type(let type0Argument) = arguments.0.argument, + caes .type(let type1Argument) = arguments.1.argument else { newNode = nil break } newNode = shorthandDictionaryType( - key: typeArguments.0.argument, - value: typeArguments.1.argument, + key: type0Argument, + value: type1Argument, leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia ) @@ -74,12 +78,13 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { newNode = nil break } - guard let typeArgument = genericArgumentList.firstAndOnly else { + guard let argument = genericArgumentList.firstAndOnly, + case .type(let typeArgument) = argument else { newNode = nil break } newNode = shorthandOptionalType( - wrapping: typeArgument.argument, + wrapping: typeArgument, leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia ) @@ -137,25 +142,28 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { switch expression.baseName.text { case "Array": - guard let typeArgument = genericArgumentList.firstAndOnly else { + guard let argument = genericArgumentList.firstAndOnly, + case .type(let typeArgument) = argument else { newNode = nil break } let arrayTypeExpr = makeArrayTypeExpression( - elementType: typeArgument.argument, + elementType: typeArgument, leftSquare: TokenSyntax.leftSquareToken(leadingTrivia: leadingTrivia), rightSquare: TokenSyntax.rightSquareToken(trailingTrivia: trailingTrivia) ) newNode = ExprSyntax(arrayTypeExpr) case "Dictionary": - guard let typeArguments = exactlyTwoChildren(of: genericArgumentList) else { + guard let arguments = exactlyTwoChildren(of: genericArgumentList), + case .type(let type0Argument) = arguments.0.argument, + case .type(let type1Argument) = arguments.1.argument else { newNode = nil break } let dictTypeExpr = makeDictionaryTypeExpression( - keyType: typeArguments.0.argument, - valueType: typeArguments.1.argument, + keyType: type0Argument, + valueType: type1Argument, leftSquare: TokenSyntax.leftSquareToken(leadingTrivia: leadingTrivia), colon: TokenSyntax.colonToken(trailingTrivia: .spaces(1)), rightSquare: TokenSyntax.rightSquareToken(trailingTrivia: trailingTrivia) @@ -163,12 +171,13 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { newNode = ExprSyntax(dictTypeExpr) case "Optional": - guard let typeArgument = genericArgumentList.firstAndOnly else { + guard let argument = genericArgumentList.firstAndOnly, + case .type(let typeArgument) = argument else { newNode = nil break } let optionalTypeExpr = makeOptionalTypeExpression( - wrapping: typeArgument.argument, + wrapping: typeArgument, leadingTrivia: leadingTrivia, questionMark: TokenSyntax.postfixQuestionMarkToken(trailingTrivia: trailingTrivia) ) From 5985355028536093bf30fa94d895ac83c7514ba7 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 28 Oct 2024 17:16:28 -0700 Subject: [PATCH 5/6] Fix build issues --- Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift b/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift index 67a8d8aa..a0c32241 100644 --- a/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift +++ b/Sources/SwiftFormat/Rules/UseShorthandTypeNames.swift @@ -48,7 +48,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { switch node.name.text { case "Array": guard let argument = genericArgumentList.firstAndOnly, - case .type(let typeArgument) = argument else { + case .type(let typeArgument) = argument.argument else { newNode = nil break } @@ -62,7 +62,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { case "Dictionary": guard let arguments = exactlyTwoChildren(of: genericArgumentList), case .type(let type0Argument) = arguments.0.argument, - caes .type(let type1Argument) = arguments.1.argument else { + case .type(let type1Argument) = arguments.1.argument else { newNode = nil break } @@ -79,7 +79,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { break } guard let argument = genericArgumentList.firstAndOnly, - case .type(let typeArgument) = argument else { + case .type(let typeArgument) = argument.argument else { newNode = nil break } @@ -143,7 +143,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { switch expression.baseName.text { case "Array": guard let argument = genericArgumentList.firstAndOnly, - case .type(let typeArgument) = argument else { + case .type(let typeArgument) = argument.argument else { newNode = nil break } @@ -172,7 +172,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { case "Optional": guard let argument = genericArgumentList.firstAndOnly, - case .type(let typeArgument) = argument else { + case .type(let typeArgument) = argument.argument else { newNode = nil break } From c0a04211d4efa1c61f7bdac20d91b6bc1d35bb4a Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 28 Oct 2024 17:17:23 -0700 Subject: [PATCH 6/6] Use cross-pr-testing from github-workflows --- .github/workflows/pull_request.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d49113a8..e86a4adc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -7,10 +7,12 @@ on: jobs: tests: name: Test - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main - soundness: - name: Soundness - uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + uses: ahoppen/github-workflows/.github/workflows/swift_package_test.yml@cross-pr-testing with: - license_header_check_enabled: false - license_header_check_project_name: "Swift.org" + enable_cross_pr_testing: true + # soundness: + # name: Soundness + # uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + # with: + # license_header_check_enabled: false + # license_header_check_project_name: "Swift.org"