Skip to content
36 changes: 36 additions & 0 deletions .github/actions/configure-docker-containerd-image-store/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: 'configure docker containerd image store'
description: 'configure docker containerd image store'
inputs:
USE_CONTAINERD:
description: use containerd as docker image store
required: false
default: 'false'
runs:
using: "composite"
steps:
- run: |
# enable containerd image store
ENABLE_CONTAINERD_IMAGE_STORE=${{ inputs.USE_CONTAINERD }}
[ "$ENABLE_CONTAINERD_IMAGE_STORE" != 'false' ] \
&& ENABLE_CONTAINERD_IMAGE_STORE=true \
|| ENABLE_CONTAINERD_IMAGE_STORE=false

# detect current configuration
config=/etc/docker/daemon.json
current=$((sudo cat "$config" 2>/dev/null || echo "{}")|jq '.features."containerd-snapshotter" // false')

# update configuration if necessary
[ "$current" = "$ENABLE_CONTAINERD_IMAGE_STORE" ] && exit 0
jq_expression='.features."containerd-snapshotter" = '$ENABLE_CONTAINERD_IMAGE_STORE
tmpfile=$(mktemp) && (sudo cat "$config" 2>/dev/null || echo "{}") | jq "$jq_expression" > "$tmpfile"
mkdir -p $(dirname "$config") && (cat "$tmpfile" | sudo tee "$config") && rm "$tmpfile"

# restart docker
sudo systemctl restart docker || sudo journalctl -xeu docker.service
echo ---
docker info
echo ---
docker image ls
echo ---
sudo systemctl status docker
shell: bash
44 changes: 44 additions & 0 deletions .github/actions/install_qemu_user_static_from_debian/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: 'install qemu-user-static from debian'
description: 'install qemu-user-static from debian'
inputs:
VERSION:
description: version of qemu-user-static
required: false
TARGET_RELEASE:
default: bookworm
description: target release specifying to apt-get install
required: false
runs:
using: "composite"
steps:
- id: process
run: |
TARGET_RELEASE=${{ inputs.TARGET_RELEASE }}
VERSION=${{ inputs.VERSION }}

# install debian-archive-keyring
keyring=/etc/apt/keyrings/debian-archive-keyring.gpg
[ -f $keyring ] || curl https://ftp-master.debian.org/keys/archive-key-11.asc -o - | sudo gpg --dearmor -o $keyring

# add debian sources
debian_sources=/etc/apt/sources.list.d/debian-$TARGET_RELEASE.sources
[ -f "$debian_sources" ] || sudo tee $debian_sources <<EOF
Types: deb
URIs: http://deb.debian.org/debian
Suites: $TARGET_RELEASE
Components: main
Signed-By: $keyring
EOF

# pin debian sources
debian_pin=/etc/apt/preferences.d/debian-$TARGET_RELEASE-pin
[ -f "$debian_pin" ] || sudo tee $debian_pin <<EOF
Package: *
Pin: release n=$TARGET_RELEASE
Pin-Priority: 100
EOF

TARGET_FLAG=${TARGET_RELEASE:+-t $TARGET_RELEASE}
VERSION_REQUIREMENT=${VERSION:+=$VERSION}
sudo apt-get update && sudo apt-get $TARGET_FLAG install -y qemu-user-static$VERSION_REQUIREMENT
shell: bash
121 changes: 98 additions & 23 deletions .github/workflows/docker-image-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
create:
push:
branches: [master]
paths:
paths:
- '.github/actions/*/action.yml'
- '.github/workflows/docker-image-ci.yml'
- '*/Dockerfile'
Expand All @@ -24,10 +24,9 @@ jobs:
strategy:
matrix:
include:
- swift_version: 5.10.0
- swift_version: 5.10.1
swift_version_aliases: ["5", "5.10"]
env:
LOAD: true
PUSH: false
SWIFTLINT_REVISION: 0.55.0

Expand All @@ -36,7 +35,6 @@ jobs:

- if: github.event_name == 'create' && github.event.ref_type == 'tag'
run: |
echo "LOAD=false" >> $GITHUB_ENV
echo "PUSH=true" >> $GITHUB_ENV
echo "SWIFTLINT_REVISION=${{ github.event.ref }}" >> $GITHUB_ENV

Expand All @@ -50,9 +48,11 @@ jobs:

- run: echo "${{ steps.tags_for_latest.outputs.tags }}"

- uses: docker/setup-qemu-action@v3
- uses: ./.github/actions/install_qemu_user_static_from_debian

- uses: docker/setup-buildx-action@v3
- uses: ./.github/actions/configure-docker-containerd-image-store
with:
USE_CONTAINERD: true

- name: Login to Docker Hub
uses: docker/login-action@v3
Expand All @@ -67,36 +67,104 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/build-push-action@v5
- name: build amd64 architecture
uses: docker/build-push-action@v5
with:
build-args: |
BUILDER_IMAGE=swift:5.10.0-jammy
RUNTIME_IMAGE=swift:${{ matrix.swift_version }}-jammy
BUILDER_IMAGE=swiftlang/swift:nightly-jammy
FIX_SWIFTPM_7695=1
SWIFTLINT_REVISION=${{ env.SWIFTLINT_REVISION }}
TARGET_IMAGE=swift:${{ matrix.swift_version }}-jammy
context: builder
load: true
platforms: linux/amd64
push: false
tags: swiftlint:amd64
cache-from: type=gha
cache-to: type=gha,mode=max

- name: build arm64 architecture
uses: docker/build-push-action@v5
with:
build-args: |
BUILDER_IMAGE=swiftlang/swift:nightly-jammy
CROSS_TARGETARCHS=arm64
FIX_SWIFTPM_7695=1
SWIFTLINT_REVISION=${{ env.SWIFTLINT_REVISION }}
TARGET_IMAGE=swift:${{ matrix.swift_version }}-jammy
context: builder
load: ${{ env.LOAD }}
# platforms: linux/amd64,linux/arm64
load: true
platforms: linux/arm64
push: false
tags: swiftlint:arm64
cache-from: type=gha
cache-to: type=gha,mode=max

- name: archive
run: |
docker run swiftlint:amd64 archive-swiftlint-runtime > copier/swiftlint_linux_amd64.tar.gz
docker run swiftlint:arm64 archive-swiftlint-runtime > copier/swiftlint_linux_arm64.tar.gz

- name: upload amd64 artifact
uses: actions/upload-artifact@v4
with:
name: swiftlint_amd64
path: copier/swiftlint_linux_amd64.tar.gz

- name: upload arm64 artifact
uses: actions/upload-artifact@v4
with:
name: swiftlint_arm64
path: copier/swiftlint_linux_arm64.tar.gz

- name: build multi-arch image
uses: docker/build-push-action@v5
with:
build-args: |
RUNTIME_IMAGE=swift:${{ matrix.swift_version }}-jammy
context: copier
load: false
platforms: linux/amd64,linux/arm64
push: ${{ env.PUSH }}
tags: ${{ steps.tags_for_latest.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max

- run: >
docker run norionomura/swiftlint:${{ env.SWIFTLINT_REVISION }}
archive-swiftlint-runtime > swiftlint_linux.tar.gz
- id: slim_tags
uses: ./.github/actions/product
with:
a: ${{ env.CONTAINER_REPOSITORIES }}
b: "[\"slim\", \"${{ env.SWIFTLINT_REVISION }}-slim\"]"
sep: '":"'

- uses: actions/upload-artifact@v4
- id: slim_tag_list
uses: ./.github/actions/list
with:
name: swiftlint
path: swiftlint_linux.tar.gz
array: ${{ steps.slim_tags.outputs.product }}

- run: echo "${{ steps.slim_tag_list.outputs.list }}"

- name: build slim image
uses: docker/build-push-action@v5
with:
build-args: |
RUNTIME_IMAGE=ubuntu:jammy
TARGET_IMAGE=swift:${{ matrix.swift_version }}-jammy
context: copier
load: false
platforms: linux/amd64,linux/arm64
push: ${{ env.PUSH }}
tags: ${{ steps.slim_tag_list.outputs.list }}
cache-from: type=gha
cache-to: type=gha,mode=max

push:
needs: build-latest
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
swift_version: ['5.7.0', '5.7.1', '5.7.2', '5.7.3', '5.8.0', '5.8.1', '5.9.0', '5.9.1', '5.9.2']
swift_version: ['5.7.0', '5.7.1', '5.7.2', '5.7.3', '5.8.0', '5.8.1', '5.9.0', '5.9.1', '5.9.2', '5.10.0']
include:
- swift_version: '5.7.3'
swift_version_aliases: ["5.7"]
Expand All @@ -107,13 +175,18 @@ jobs:
env:
PUSH: false
SWIFTLINT_REVISION: 0.55.0

steps:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: swiftlint
name: swiftlint_amd64
path: copier

- uses: actions/download-artifact@v4
with:
name: swiftlint_arm64
path: copier

- if: github.event_name == 'create' && github.event.ref_type == 'tag'
Expand All @@ -131,9 +204,11 @@ jobs:

- run: echo "${{ steps.tags_for_older.outputs.tags }}"

- uses: docker/setup-qemu-action@v3
- uses: ./.github/actions/install_qemu_user_static_from_debian

- uses: docker/setup-buildx-action@v3
- uses: ./.github/actions/configure-docker-containerd-image-store
with:
USE_CONTAINERD: true

- name: Login to Docker Hub
uses: docker/login-action@v3
Expand All @@ -153,7 +228,7 @@ jobs:
build-args: |
RUNTIME_IMAGE=swift:${{ matrix.swift_version }}-jammy
context: copier
# platforms: linux/amd64,linux/arm64
platforms: linux/amd64,linux/arm64
push: ${{ env.PUSH }}
tags: ${{ steps.tags_for_older.outputs.tags }}
cache-from: type=gha
Expand Down
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# docker-swiftlint

*In this document, using **amd64, arm64** for platform architecture for docker, and **x86_64, aarch64** for Swift architecture.*

## `builder` directory
### Build without Swift SDK (no-sdk)

#### Build image for docker host architecture
```bash
docker buildx build --load builder/ -t swiftlint
```

#### Build multi-architecture image (x86_64-no-sdk, aarch64-no-sdk)
```bash
docker buildx build --load builder/ -t swiftlint \
--platform linux/amd64,linux/arm64
```

### Cross compilation on `BUILDER_IAMGE` using `TARGET_IMAGE` as Swift SDK
Setup `TARGET_IMAGE` as the Swift SDK for the target architecture, and use them from Swift Toolchain in `BUILDER_IMAGE`.

Supported combinations of `TARGET_IMAGE` and `BUILDER_IMAGE` are as follows:
| | aarch64 builder | x86_64 builder |
|----------------|--------------------|-------------------|
| aarch64 target | aarch64-on-aarch64 | aarch64-on-x86_64 |
| x86_64 target | x86_64-on-aarch64 | x86_64-on-x86_64 |


#### Using `--build-arg USE_SDK=1` for building with Swift SDK
Build arm64 architecture image using Swift SDK (aarch64-on-aarch64)
```bash
docker buildx build --load builder/ -t swiftlint \
--platform linux/arm64 --build-arg USE_SDK=1
```

#### Using `--build-arg CROSS=1` for cross compilation with Swift SDK
Build arm64 architecture image on amd64 architecture using Swift SDK (aarch64-on-x86_64)
```bash
docker buildx build --load builder/ -t swiftlint \
--platform linux/arm64 --build-arg CROSS=1
```

#### Using `--build-arg CROSS_TARGETARCHS=...` for cross compiling target architectures with Swift SDK
Build multi-architecture image, native compileed arm64 (aarch64-no-sdk), cross compiled amd64 (x86_64-on-aarch64).
```bash
docker buildx build --load builder/ -t swiftlint \
--platform linux/amd64,linux/arm64 --build-arg CROSS_TARGETARCHS=amd64
```
This command minimizes the use of emulation on arm64 host.


## `copier` directory
Expected to use `swiftlint` binary built in `builder` directory.

## Running aarch64 executable generated with Swift on x86_64 Ubuntu (GitHub Hosted Actions Runner) using `qemu-user-static`
There is a known issue where running an aarch64 executable generated with Swift on x86_64 Ubuntu using the default `qemu-user-static` results in a crash.
https://forums.swift.org/t/swift-runtime-unable-to-suspend-thread-when-compiling-in-qemu/67676

This issue can be avoided by using qemu-user-static-7.2 distributed by Debian.
There are two methods to install it:
- For rootful docker, run `docker run --rm --privileged multiarch/qemu-user-static:7.2.0-1 --reset -p yes`.
This method can be used as long as the docker installed on the GitHub Actions Runner is rootful.
- Setup debian sources to apt on host and install it. See [install_qemu_user_static_from_debian](.github/actions/install_qemu_user_static_from_debian/action.yml) as an example.

## Author

Norio Nomura

## License

available under the MIT license. See the LICENSE file for more info.
Loading