Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3cf5be1
Pipeline for building static linux binaries
bradleymackey Nov 27, 2024
1def7a2
Build for arm and amd
bradleymackey Nov 27, 2024
202395a
Update swift linux sdk in dockerfile
bradleymackey Mar 8, 2025
87df6b6
Fix Dockerfile
bradleymackey Mar 8, 2025
5625f42
Ensure that linux arm binary is uploaded as an artifact
bradleymackey Mar 8, 2025
d48533a
Add arm64 to arifact bundle
bradleymackey Mar 8, 2025
a3454cb
Hook up installables in makefile
bradleymackey Mar 8, 2025
d351022
Fix triple in artifact bundle
bradleymackey Mar 8, 2025
7ec8765
Update build steps
SimplyDanny Aug 14, 2025
d983d4c
Build in PR
SimplyDanny Aug 14, 2025
0abcd82
Build without SDK
SimplyDanny Aug 14, 2025
7a73615
Separate runtime and builder image
SimplyDanny Aug 14, 2025
93d3472
Link to specific binary
SimplyDanny Aug 14, 2025
c1cd18a
Use Swift 6.0.3
SimplyDanny Aug 14, 2025
2731dce
Run `tree` command to check output
SimplyDanny Aug 15, 2025
6ecfebd
Fix artifact pattern
SimplyDanny Aug 15, 2025
5d674b3
Move artifacts for simpler archive structure
SimplyDanny Aug 15, 2025
2ff42b8
Remove traces of Swift SDK
SimplyDanny Aug 15, 2025
35f8313
Run regularly per schedule only
SimplyDanny Aug 15, 2025
2b6e7d5
Build in PR if Docker-related files have changed
SimplyDanny Aug 15, 2025
e387a81
Use swiftlint_linux_* as Linux binary names
SimplyDanny Aug 15, 2025
16e6089
Add changelog entry
SimplyDanny Aug 15, 2025
a01ccaa
Avoid explicit PR HEAD ref in workflow
SimplyDanny Aug 15, 2025
de0702f
Shorter workflow/job names
SimplyDanny Aug 15, 2025
1409470
Try to build on ARM
SimplyDanny Aug 16, 2025
273b499
Use PRs checkout ref
SimplyDanny Aug 16, 2025
5b102f3
Reduce scheduled build and trigger on push
SimplyDanny Aug 16, 2025
2669ac6
Simplify condition
SimplyDanny Aug 16, 2025
d63859a
Make both binaries executable
SimplyDanny Aug 16, 2025
89032dd
Revert "Use PRs checkout ref"
SimplyDanny Aug 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
!Source
!Tests
!Package.*
!tools/build-linux-release.sh
48 changes: 37 additions & 11 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
name: Docker Build
name: Docker

on:
schedule:
- cron: '0 3 * * 3' # Every Wednesday at 03:00 UTC
push:
branches:
- main
paths:
- '.github/workflows/docker.yml'
- 'Dockerfile'
- 'tools/build-linux-release.sh'
release:
types: published
workflow_call:
Expand All @@ -16,18 +22,23 @@ on:
description: 'Docker tag'
required: true
type: string
pull_request:
paths:
- '.github/workflows/docker.yml'
- 'Dockerfile'
- 'tools/build-linux-release.sh'

permissions:
contents: read
packages: write

jobs:
build:
name: Build Docker Image
runs-on: ubuntu-24.04
name: Build Images
runs-on: ubuntu-24.04-arm
steps:
- name: Define variables on push to `main`
if: github.event_name == 'push'
if: github.event_name == 'schedule' || github.event_name == 'push'
run: |
{
echo "CHECKOUT_REF=main"
Expand All @@ -42,21 +53,36 @@ jobs:
echo "DOCKER_TAG=${{ github.event.release.tag_name }}"
echo "OUTPUT_TYPE=type=registry"
} >> "$GITHUB_ENV"
- name: Define variables on pull request
if: github.event_name == 'pull_request'
run: |
{
echo "CHECKOUT_REF=pr"
echo "DOCKER_TAG=pr-${{ github.event.pull_request.number }}"
echo "OUTPUT_TYPE=type=local,dest=artifacts"
} >> "$GITHUB_ENV"
- name: Define variables on workflow call
if: github.event_name != 'push' && github.event_name != 'release'
if: env.DOCKER_TAG == null
run: |
{
echo "CHECKOUT_REF=${{ inputs.ref }}"
echo "DOCKER_TAG=${{ inputs.tag }}"
echo "OUTPUT_TYPE=type=local,dest=artifacts"
} >> "$GITHUB_ENV"
- uses: actions/checkout@v4
if: env.CHECKOUT_REF == 'pr'
- uses: actions/checkout@v4
if: env.CHECKOUT_REF != 'pr'
with:
ref: ${{ env.CHECKOUT_REF }}
- name: Set lowercase repository name
run: echo "REPOSITORY_LC=${REPOSITORY,,}" >> "$GITHUB_ENV"
env:
REPOSITORY: ${{ github.repository }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: amd64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub registry
Expand All @@ -69,16 +95,16 @@ jobs:
with:
context: .
tags: ghcr.io/${{ env.REPOSITORY_LC }}:${{ env.DOCKER_TAG }}
platforms: linux/amd64
platforms: linux/amd64, linux/arm64
outputs: ${{ env.OUTPUT_TYPE }}
- name: Rename binary artifact
- name: Move binary artifacts
if: contains(env.OUTPUT_TYPE, 'local')
run: mv artifacts/usr/bin/swiftlint artifacts/usr/bin/swiftlint_linux_amd64
- name: Upload binary artifact
run: mv artifacts/linux_*/usr/bin/swiftlint_linux_* .
- name: Upload binary artifacts
if: contains(env.OUTPUT_TYPE, 'local')
uses: actions/upload-artifact@v4
with:
name: swiftlint_linux_amd64
path: artifacts/usr/bin/swiftlint_linux_amd64
name: swiftlint_linux
path: swiftlint_linux_*
if-no-files-found: error
retention-days: 2
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,12 @@ jobs:
- name: Download binary artifact for Linux
uses: actions/download-artifact@v4
with:
name: swiftlint_linux_amd64
name: swiftlint_linux
path: ${{ env.LINUX_BUILD_DIR }}
- name: Move Bazel release
run: mv -f ${{ env.MACOS_BUILD_DIR }}/bazel.tar.gz ${{ env.MACOS_BUILD_DIR }}/bazel.tar.gz.sha256 .
- name: Make binaries executable
run: chmod +x ${{ env.MACOS_BUILD_DIR }}/swiftlint ${{ env.LINUX_BUILD_DIR }}/swiftlint_linux_amd64
run: chmod +x ${{ env.MACOS_BUILD_DIR }}/swiftlint ${{ env.LINUX_BUILD_DIR }}/swiftlint_linux_*
- name: Create artifacts
run: |
make --debug spm_artifactbundle
Expand Down
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,27 @@
`redundant_optional_initialization` rule by default. `redundant_optional_initialization`
is now an alias for `implicit_optional_initialization`.
[leo-lem](https://github.com/leo-lem)
[#1940](https://github.com/realm/SwiftLint/issues/1940)
[#1940](https://github.com/realm/SwiftLint/issues/1940)

* The `x86_64`/`amd64` binary in the `swiftlint_linux.zip` release archive has been renamed to
`swiftlint_amd64` from just `swiftlint` to avoid confusion with the new `swiftlint_arm64` binary.
[Bradley Mackey](https://github.com/bradleymackey)
[SimplyDanny](https://github.com/SimplyDanny)

### Experimental

* None.

### Enhancements

* Support for ARM64 Linux binaries has been added. The `swiftlint_linux.zip` release archive
now contains both `swiftlint_amd64` and `swiftlint_arm64` binaries. The `swiftlint_amd64`
binary was formerly named `swiftlint`. `SwiftLintBinary.artifactbundle.zip` now also provides
the new binary, making the [binary plugins](https://github.com/SimplyDanny/SwiftLintPlugins)
work on ARM64 Linux as well.
[Bradley Mackey](https://github.com/bradleymackey)
[SimplyDanny](https://github.com/SimplyDanny)

* Add `include_variables` configuration option to `non_optional_string_data_conversion` rule.
When enabled, the rule will trigger on variables, properties, and function calls in addition
to string literals. Defaults to `false` for backward compatibility.
Expand Down
42 changes: 20 additions & 22 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
# Explicitly specify `noble` to keep the Swift & Ubuntu images in sync.
ARG BUILDER_IMAGE=swift:6.0-noble
ARG RUNTIME_IMAGE=ubuntu:noble
# syntax=docker/dockerfile:1

# Base image and static SDK have to be updated together.
ARG SWIFT_VERSION=6.0.3
ARG UBUNTU_VERSION=noble

# Builder image
FROM ${BUILDER_IMAGE} AS builder
RUN apt-get update && apt-get install -y \
libcurl4-openssl-dev \
libxml2-dev \
&& rm -r /var/lib/apt/lists/*
WORKDIR /workdir/
FROM swift:${SWIFT_VERSION}-${UBUNTU_VERSION} AS builder
WORKDIR /workspace
COPY Plugins Plugins/
COPY Source Source/
COPY Tests Tests/
COPY Package.* ./

RUN swift package update
ARG SWIFT_FLAGS="-c release -Xswiftc -static-stdlib -Xlinker -l_CFURLSessionInterface -Xlinker -l_CFXMLInterface -Xlinker -lcurl -Xlinker -lxml2 -Xswiftc -I. -Xlinker -fuse-ld=lld -Xlinker -L/usr/lib/swift/linux"
RUN swift build $SWIFT_FLAGS --product swiftlint
RUN mv `swift build $SWIFT_FLAGS --show-bin-path`/swiftlint /usr/bin
RUN strip /usr/bin/swiftlint
COPY tools/build-linux-release.sh tools/
ARG TARGETPLATFORM
RUN --mount=type=cache,target=/workspace/.build,id=build-$TARGETPLATFORM ./tools/build-linux-release.sh

# Runtime image
FROM ${RUNTIME_IMAGE}
FROM ubuntu:${UBUNTU_VERSION} AS runtime
LABEL org.opencontainers.image.source=https://github.com/realm/SwiftLint
RUN apt-get update && apt-get install -y \
libcurl4 \
libxml2 \
&& rm -r /var/lib/apt/lists/*
RUN apt-get update
RUN apt-get install -y libcurl4-openssl-dev libxml2-dev
RUN rm -r /var/lib/apt/lists/*

COPY --from=builder /usr/lib/libsourcekitdInProc.so /usr/lib
COPY --from=builder /usr/lib/swift/host/libSwiftBasicFormat.so /usr/lib
COPY --from=builder /usr/lib/swift/host/libSwiftCompilerPluginMessageHandling.so /usr/lib
Expand Down Expand Up @@ -56,9 +51,12 @@ COPY --from=builder /usr/lib/swift/linux/libswiftDispatch.so /usr/lib
COPY --from=builder /usr/lib/swift/linux/libswiftGlibc.so /usr/lib
COPY --from=builder /usr/lib/swift/linux/libswiftSynchronization.so /usr/lib
COPY --from=builder /usr/lib/swift/linux/libswiftSwiftOnoneSupport.so /usr/lib
Comment thread
SimplyDanny marked this conversation as resolved.
COPY --from=builder /usr/bin/swiftlint /usr/bin
COPY --from=builder /workspace/swiftlint_linux_* /usr/bin

RUN ln -s /usr/bin/swiftlint_linux_* /usr/bin/swiftlint

RUN swiftlint version
RUN echo "_ = 0" | swiftlint --use-stdin

CMD ["swiftlint"]
ENTRYPOINT [ "/usr/bin/swiftlint" ]
CMD ["."]
27 changes: 15 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ SWIFTLINT_EXECUTABLE_PARENT=.build/universal
SWIFTLINT_EXECUTABLE=$(SWIFTLINT_EXECUTABLE_PARENT)/swiftlint
SWIFTLINT_EXECUTABLE_LINUX_PARENT=.build/linux
SWIFTLINT_EXECUTABLE_LINUX_AMD64=$(SWIFTLINT_EXECUTABLE_LINUX_PARENT)/swiftlint_linux_amd64
SWIFTLINT_EXECUTABLE_LINUX_ARM64=$(SWIFTLINT_EXECUTABLE_LINUX_PARENT)/swiftlint_linux_arm64

ARTIFACT_BUNDLE_PATH=$(TEMPORARY_FOLDER)/SwiftLintBinary.artifactbundle

Expand Down Expand Up @@ -87,6 +88,11 @@ $(SWIFTLINT_EXECUTABLE_LINUX_AMD64):
docker run --platform linux/amd64 "ghcr.io/realm/swiftlint:$(VERSION_STRING)" cat /usr/bin/swiftlint > "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)"
chmod +x "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)"

$(SWIFTLINT_EXECUTABLE_LINUX_ARM64):
mkdir -p "$(SWIFTLINT_EXECUTABLE_LINUX_PARENT)"
docker run --platform linux/arm64 "ghcr.io/realm/swiftlint:$(VERSION_STRING)" cat /usr/bin/swiftlint > "$(SWIFTLINT_EXECUTABLE_LINUX_ARM64)"
chmod +x "$(SWIFTLINT_EXECUTABLE_LINUX_ARM64)"

build_with_disable_sandbox:
swift build --disable-sandbox $(SWIFT_BUILD_FLAGS)

Expand All @@ -102,9 +108,10 @@ installables: $(SWIFTLINT_EXECUTABLE)
install -d "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)"
install "$(SWIFTLINT_EXECUTABLE)" "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)"

installables_linux: $(SWIFTLINT_EXECUTABLE_LINUX_AMD64)
installables_linux: $(SWIFTLINT_EXECUTABLE_LINUX_AMD64) $(SWIFTLINT_EXECUTABLE_LINUX_ARM64)
install -d "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)"
install "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)" "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)"
install "$(SWIFTLINT_EXECUTABLE_LINUX_ARM64)" "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)"

prefix_install: build_with_disable_sandbox
install -d "$(PREFIX)/bin/"
Expand All @@ -115,26 +122,22 @@ portable_zip: installables
cp -f "$(LICENSE_PATH)" "$(TEMPORARY_FOLDER)"
(cd "$(TEMPORARY_FOLDER)"; zip -yr - "swiftlint" "LICENSE") > "./portable_swiftlint.zip"

spm_artifactbundle: $(SWIFTLINT_EXECUTABLE) $(SWIFTLINT_EXECUTABLE_LINUX_AMD64)
spm_artifactbundle: $(SWIFTLINT_EXECUTABLE) $(SWIFTLINT_EXECUTABLE_LINUX_AMD64) $(SWIFTLINT_EXECUTABLE_LINUX_ARM64)
mkdir -p "$(ARTIFACT_BUNDLE_PATH)/swiftlint-$(VERSION_STRING)-macos/bin"
mkdir -p "$(ARTIFACT_BUNDLE_PATH)/swiftlint-$(VERSION_STRING)-linux-gnu/bin"
sed 's/__VERSION__/$(VERSION_STRING)/g' tools/info.json.template > "$(ARTIFACT_BUNDLE_PATH)/info.json"
cp -f "$(SWIFTLINT_EXECUTABLE)" "$(ARTIFACT_BUNDLE_PATH)/swiftlint-$(VERSION_STRING)-macos/bin/swiftlint"
cp -f "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)" "$(ARTIFACT_BUNDLE_PATH)/swiftlint-$(VERSION_STRING)-linux-gnu/bin/swiftlint"
cp -f "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)" "$(ARTIFACT_BUNDLE_PATH)/swiftlint-$(VERSION_STRING)-linux-gnu/bin/swiftlint_amd64"
cp -f "$(SWIFTLINT_EXECUTABLE_LINUX_ARM64)" "$(ARTIFACT_BUNDLE_PATH)/swiftlint-$(VERSION_STRING)-linux-gnu/bin/swiftlint_arm64"
cp -f "$(LICENSE_PATH)" "$(ARTIFACT_BUNDLE_PATH)"
(cd "$(TEMPORARY_FOLDER)"; zip -yr - "SwiftLintBinary.artifactbundle") > "./SwiftLintBinary.artifactbundle.zip"

zip_linux: docker_image $(SWIFTLINT_EXECUTABLE_LINUX_AMD64)
$(eval TMP_FOLDER := $(shell mktemp -d))
cp -f $(SWIFTLINT_EXECUTABLE_LINUX_AMD64) "$(TMP_FOLDER)/swiftlint"
cp -f "$(LICENSE_PATH)" "$(TMP_FOLDER)"
(cd "$(TMP_FOLDER)"; zip -yr - "swiftlint" "LICENSE") > "./swiftlint_linux.zip"

zip_linux_release: $(SWIFTLINT_EXECUTABLE_LINUX_AMD64)
zip_linux_release: $(SWIFTLINT_EXECUTABLE_LINUX_AMD64) $(SWIFTLINT_EXECUTABLE_LINUX_ARM64)
$(eval TMP_FOLDER := $(shell mktemp -d))
cp -f "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)" "$(TMP_FOLDER)/swiftlint"
cp -f "$(SWIFTLINT_EXECUTABLE_LINUX_AMD64)" "$(TMP_FOLDER)/swiftlint_amd64"
cp -f "$(SWIFTLINT_EXECUTABLE_LINUX_ARM64)" "$(TMP_FOLDER)/swiftlint_arm64"
cp -f "$(LICENSE_PATH)" "$(TMP_FOLDER)"
(cd "$(TMP_FOLDER)"; zip -yr - "swiftlint" "LICENSE") > "./swiftlint_linux.zip"
(cd "$(TMP_FOLDER)"; zip -yr - "swiftlint_amd64" "swiftlint_arm64" "LICENSE") > "./swiftlint_linux.zip"

package: $(SWIFTLINT_EXECUTABLE)
$(eval PACKAGE_ROOT := $(shell mktemp -d))
Expand Down
33 changes: 33 additions & 0 deletions tools/build-linux-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

set -eo pipefail

pushd "$(dirname "${BASH_SOURCE[0]}")/.." > /dev/null

if [[ "$TARGETPLATFORM" = "linux/amd64" ]]; then
ARCH="x86_64"
STRIP_CMD="strip"
elif [[ "$TARGETPLATFORM" = "linux/arm64" ]]; then
ARCH="aarch64"
STRIP_CMD="strip"
else
echo "Unsupported target platform: $TARGETPLATFORM"
exit 1
fi

BUILD_ARGS=(
--product swiftlint
--configuration release
-Xswiftc -I.
-Xswiftc -static-stdlib
-Xlinker -l_CFURLSessionInterface
-Xlinker -l_CFXMLInterface
-Xlinker -lcurl
-Xlinker -lxml2
-Xlinker -fuse-ld=lld
-Xlinker -L/usr/lib/swift/linux
)
Comment thread
SimplyDanny marked this conversation as resolved.

swift build "${BUILD_ARGS[@]}"
mv ".build/release/swiftlint" "swiftlint_linux_${ARCH}"
${STRIP_CMD} "swiftlint_linux_${ARCH}"
6 changes: 5 additions & 1 deletion tools/info.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
"supportedTriples": ["x86_64-apple-macosx", "arm64-apple-macosx"]
},
{
"path": "swiftlint-__VERSION__-linux-gnu/bin/swiftlint",
"path": "swiftlint-__VERSION__-linux-gnu/bin/swiftlint_amd64",
"supportedTriples": ["x86_64-unknown-linux-gnu"]
},
{
"path": "swiftlint-__VERSION__-linux-gnu/bin/swiftlint_arm64",
"supportedTriples": ["aarch64-unknown-linux-gnu", "arm64-unknown-linux-gnu"]
}
]
}
Expand Down