diff --git a/.github/workflows/architecture.md b/.github/workflows/architecture.md index 0760c290..336aaed0 100644 --- a/.github/workflows/architecture.md +++ b/.github/workflows/architecture.md @@ -66,7 +66,7 @@ To test a change to the workflows or scripts, call the workflow at the branch or ## Swift version labels -A version list names toolchains with labels: a version such as `6.3`, `nightly-release`, `nightly-main`, or a position counted back from the current release, `current`, `current-1` and `current-2`. A job's name carries the label the caller wrote. Job names are required status checks, so the default lists use the relative labels: a new Swift release changes which versions they name and leaves the checks alone. A caller who writes versions out gets those names, and the two spellings can be mixed in one list. +A version list names toolchains with labels: a version such as `6.3`, `nightly-release`, `nightly-main`, or a position counted back from the current release, `current`, `current-1` and `current-2`. A job's name carries the label the caller wrote. Job names are required status checks, so the default lists use the relative labels: a new Swift release changes which versions they name and leaves the checks alone. A caller who writes versions out gets those names, and the two spellings can be mixed in one list. Since the name may show only the label, every job's first step is named for the version it resolved to, such as `Print Swift version (6.4)`, and prints the toolchain, container image or Xcode the entry asks for. The workflow supplies what the relative labels resolve against, in `swift_current_release` and `swift_nightly_release`. They are inputs with defaults in the workflow files rather than values in the generator, so a workflow pinned to a release tag keeps the versions it was released with. Setting `swift_current_release` holds a repository at an earlier release without changing its check names. diff --git a/.github/workflows/execute_matrix.yml b/.github/workflows/execute_matrix.yml index c2de8262..64668950 100644 --- a/.github/workflows/execute_matrix.yml +++ b/.github/workflows/execute_matrix.yml @@ -150,6 +150,47 @@ jobs: || matrix.config.freebsd.swift_version || '' }} steps: + # A job's name contains the alias, so print the resolved value as the name of this step. + # Makes it easier to check the Swift version without digging deep in the logs. + - name: >- + Print Swift version (${{ + matrix.config.swift_build.toolchain + || matrix.config.swift_build.swift_version + || matrix.config.xcode_build.swiftly_toolchain + || matrix.config.xcode_build.swift_version + || (matrix.config.xcode_build.xcode_version && format('Xcode {0}', matrix.config.xcode_build.xcode_version)) + || matrix.config.freebsd.swift_version + || 'none requested' }}) + id: swift_version + shell: bash + env: + JOB_NAME: ${{ matrix.config.name }} + MATRIX_SWIFT_VERSION: >- + ${{ matrix.config.swift_build.swift_version + || matrix.config.xcode_build.swift_version + || matrix.config.freebsd.swift_version }} + MATRIX_TOOLCHAIN: ${{ matrix.config.swift_build.toolchain }} + MATRIX_SWIFTLY: ${{ matrix.config.swift_build.swiftly || matrix.config.xcode_build.swiftly_toolchain }} + MATRIX_XCODE_VERSION: ${{ matrix.config.xcode_build.xcode_version }} + MATRIX_CONTAINER_IMAGE: ${{ matrix.config.swift_build.container.image }} + MATRIX_SDK_TYPE: ${{ matrix.config.swift_build.sdk.type }} + MATRIX_SWIFT_URL: ${{ matrix.config.freebsd.swift_url }} + run: | + # Print only the fields that are set. + print_field() { + if [ -n "$2" ]; then + printf '%-18s %s\n' "$1:" "$2" + fi + } + print_field "Job" "$JOB_NAME" + print_field "Swift version" "$MATRIX_SWIFT_VERSION" + print_field "Toolchain" "$MATRIX_TOOLCHAIN" + print_field "swiftly selector" "$MATRIX_SWIFTLY" + print_field "Xcode version" "$MATRIX_XCODE_VERSION" + print_field "Container image" "$MATRIX_CONTAINER_IMAGE" + print_field "Swift SDK" "$MATRIX_SDK_TYPE" + print_field "Toolchain URL" "$MATRIX_SWIFT_URL" + - name: Checkout repository uses: actions/checkout@v7 with: diff --git a/.github/workflows/scripts/matrix/job-runner-linux.sh b/.github/workflows/scripts/matrix/job-runner-linux.sh index a544350e..cd03a6e1 100755 --- a/.github/workflows/scripts/matrix/job-runner-linux.sh +++ b/.github/workflows/scripts/matrix/job-runner-linux.sh @@ -160,9 +160,11 @@ if [[ -n "$container_image" ]]; then docker_args+=("$actual_image") + # Print the Swift version as the first step. + inner_command="swift --version"$'\n' + # Check out linked PRs inside the container, where the toolchain under test is. # A failure must fail the job. - inner_command="" if [[ "${CROSS_PR_TESTING:-false}" == "true" && -n "${CROSS_PR_REPO:-}" ]]; then # Single-quoted deliberately: these must expand inside the container, from # the values passed with -e, not on the host where the paths differ. diff --git a/tests/execute-matrix-tests.sh b/tests/execute-matrix-tests.sh index f87383c7..a4b21d19 100755 --- a/tests/execute-matrix-tests.sh +++ b/tests/execute-matrix-tests.sh @@ -63,6 +63,7 @@ step_script() { } CONVERT_SCRIPT=$(step_script '.jobs.convert-matrix.steps[] | select(.id == "convert") | .run') +SWIFT_VERSION_SCRIPT=$(step_script '.jobs.execute-matrix.steps[] | select(.id == "swift_version") | .run') FREEBSD_ENV_SCRIPT=$(step_script '.jobs.execute-matrix.steps[] | select(.id == "freebsd_env") | .run') FREEBSD_ARGUMENTS_SCRIPT=$(step_script '.jobs.execute-matrix.steps[] | select(.id == "freebsd_arguments") | .run') FREEBSD_RUN_SCRIPT=$(step_script '.jobs.execute-matrix.steps[] | select(.name == "Run matrix job (FreeBSD)") | .with.run') @@ -87,6 +88,24 @@ run_convert() { echo "$?" } +# run_swift_version [toolchain] [container_image] - echoes the exit status; +# what the step printed is left in $STEP_LOG. +run_swift_version() { + ( + cd "$WORKDIR" || exit 1 + JOB_NAME="entry" \ + MATRIX_SWIFT_VERSION="$1" \ + MATRIX_TOOLCHAIN="${2:-}" \ + MATRIX_SWIFTLY="" \ + MATRIX_XCODE_VERSION="" \ + MATRIX_CONTAINER_IMAGE="${3:-}" \ + MATRIX_SDK_TYPE="" \ + MATRIX_SWIFT_URL="" \ + bash -eo pipefail -c "$SWIFT_VERSION_SCRIPT" >"$STEP_LOG" 2>&1 + ) + echo "$?" +} + # run_freebsd_env - echoes the exit status. run_freebsd_env() { : >"$STEP_OUTPUT" @@ -212,6 +231,20 @@ assert_status "an entry on an unsupported platform is refused" "1" \ "$(run_convert $'config:\n - platform: Solaris\n name: entry\n command: "true"\n')" assert_contains "the refusal names the platform" "Unsupported platform" "$(cat "$STEP_LOG")" +echo "== Requested Swift version" + +# GitHub runs a bash step under -e, so a field the entry leaves empty must not end the +# step with a failing status. +assert_status "a release with no toolchain or container is printed" "0" "$(run_swift_version "6.4")" +assert_contains "the resolved version is printed" "Swift version: 6.4" "$(cat "$STEP_LOG")" +assert_text "fields the entry does not set are left out" "" "$(grep -E '^(Toolchain|Container image):' "$STEP_LOG")" + +assert_status "a nightly in a container is printed" "0" \ + "$(run_swift_version "nightly-release" "nightly-6.4.x" "swiftlang/swift:nightly-6.4.x-noble")" +assert_contains "the nightly's toolchain is printed" "Toolchain: nightly-6.4.x" "$(cat "$STEP_LOG")" +assert_contains "the container image is printed" \ + "Container image: swiftlang/swift:nightly-6.4.x-noble" "$(cat "$STEP_LOG")" + echo "== FreeBSD environment" assert_status "the environments merge" "0" "$(run_freebsd_env "FROM_FREEBSD=1" '{"FROM_ENTRY":"2"}')" diff --git a/tests/runner-exit-code-tests.sh b/tests/runner-exit-code-tests.sh index b094251e..960789cb 100755 --- a/tests/runner-exit-code-tests.sh +++ b/tests/runner-exit-code-tests.sh @@ -160,6 +160,10 @@ assert_contains "a multi-line environment value reaches the container whole" \ $'MULTILINE_VALUE=first\nsecond' "$docker_args" assert_contains "an empty environment value reaches the container" \ $'\nEMPTY_VALUE=\n' "$docker_args" +# The image supplies the toolchain, so the container's command is the only place its +# version can be printed. +assert_contains "the container prints its Swift version first" \ + $'bash\n-ec\nswift --version\n' "$docker_args" # Every SDK type has to hand the caller's build command to the SDK script, which # otherwise builds with its own default and reports success for work nobody asked