Skip to content

update ci tools to publish arm64 docker images #1636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .changes/1636.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "added",
"description": "Add provided docker images for `linux/arm64/v8` target for many Ubuntu-based targets"
}
83 changes: 80 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,27 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

generate-matrix-for-build:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In build job, we need to run docker build and test for each (target, platform) pair. In push job, we need to run build for each target with multiple targets.

runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.generate-matrix.outputs.matrix }}
tests: ${{ steps.generate-matrix.outputs.tests }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.checkout-ref }}
- uses: ./.github/actions/setup-rust

- name: Generate matrix
id: generate-matrix
run: cargo xtask ci-job target-matrix ${{ github.event_name == 'merge_group' && format('--merge-group {0}', github.ref) || '' }} ${{ inputs.matrix-args || '' }} --for-build
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build:
name: target (${{ matrix.pretty }},${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: [shellcheck, test, generate-matrix, check]
needs: [shellcheck, test, generate-matrix-for-build, check]
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group' || github.event_name == 'issue_comment' || github.event_name == 'schedule') && needs.generate-matrix.outputs.matrix != '{}' && needs.generate-matrix.outputs.matrix != '[]' && needs.generate-matrix.outputs.matrix != ''
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.pretty }}
Expand Down Expand Up @@ -186,7 +203,7 @@ jobs:
id: build-docker-image
if: steps.prepare-meta.outputs.has-image
timeout-minutes: 120
run: cargo xtask build-docker-image -v "${TARGET}${SUB:+.$SUB}" ${{ matrix.verbose && '-v' || '' }}
run: cargo xtask build-docker-image -v "${TARGET}${SUB:+.$SUB}" ${{ matrix.verbose && '-v' || '' }} --platform ${{ matrix.platform }}
env:
TARGET: ${{ matrix.target }}
SUB: ${{ matrix.sub }}
Expand Down Expand Up @@ -232,6 +249,66 @@ jobs:
IMAGE: 'ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main'
shell: bash

push_image:
name: target (${{ matrix.pretty }},${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: [shellcheck, test, generate-matrix, check, build]
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'merge_group' || github.event_name == 'issue_comment' || github.event_name == 'schedule') && needs.generate-matrix.outputs.matrix != '{}' && needs.generate-matrix.outputs.matrix != '[]' && needs.generate-matrix.outputs.matrix != ''
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.pretty }}
cancel-in-progress: false
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
outputs:
has-image: ${{ steps.prepare-meta.outputs.has-image }}
images: ${{ steps.build-docker-image.outputs.images && fromJSON(steps.build-docker-image.outputs.images) }}
coverage-artifact: ${{ steps.cov.outputs.artifact-name }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.checkout-ref }}

- uses: ./.github/actions/setup-rust

- name: Set up Docker Buildx
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v2

- name: Build xtask
run: cargo build -p xtask

- name: Prepare Meta
id: prepare-meta
timeout-minutes: 60
run: cargo xtask ci-job prepare-meta "${TARGET}${SUB:+.$SUB}"
env:
TARGET: ${{ matrix.target }}
SUB: ${{ matrix.sub }}
PLATFORMS: ${{ join(matrix.platforms, ',') }}
shell: bash

- name: LLVM instrument coverage
id: cov
uses: ./.github/actions/cargo-llvm-cov
if: steps.prepare-meta.outputs.has-image && steps.prepare-meta.outputs.test-variant != 'zig'
with:
name: cross-${{matrix.pretty}}

- name: Install cross
if: matrix.deploy
run: cargo install --path . --force --debug

- name: Docker Meta
if: steps.prepare-meta.outputs.has-image
id: docker-meta
uses: docker/metadata-action@v4
with:
images: |
name=${{ steps.prepare-meta.outputs.image }}
labels: |
${{ fromJSON(steps.prepare-meta.outputs.labels) }}
- name: Login to GitHub Container Registry
if: steps.prepare-meta.outputs.has-image
uses: docker/login-action@v2
Expand All @@ -246,7 +323,7 @@ jobs:
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) ||
startsWith(github.ref, 'refs/tags/v')
)
run: cargo xtask build-docker-image -v --push "${TARGET}${SUB:+.$SUB}"
run: cargo xtask build-docker-image -v --push "${TARGET}${SUB:+.$SUB}" --platform ${{ join(matrix.platforms, ',') }}
env:
TARGET: ${{ matrix.target }}
SUB: ${{ matrix.sub }}
Expand Down
15 changes: 9 additions & 6 deletions src/docker/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub trait BuildCommandExt {
fn progress(&mut self, progress: Option<Progress>) -> Result<&mut Self>;
fn verbose(&mut self, verbosity: Verbosity) -> &mut Self;
fn disable_scan_suggest(&mut self) -> &mut Self;
fn cross_labels(&mut self, target: &str, platform: &str) -> &mut Self;
fn cross_labels(&mut self, target: &str, platform: &[&str]) -> &mut Self;
}

impl BuildCommandExt for Command {
Expand Down Expand Up @@ -74,15 +74,18 @@ impl BuildCommandExt for Command {
self.env("DOCKER_SCAN_SUGGEST", "false")
}

fn cross_labels(&mut self, target: &str, platform: &str) -> &mut Self {
fn cross_labels(&mut self, target: &str, platforms: &[&str]) -> &mut Self {
self.args([
"--label",
&format!("{}.for-cross-target={target}", crate::CROSS_LABEL_DOMAIN,),
]);
self.args([
"--label",
&format!("{}.runs-with={platform}", crate::CROSS_LABEL_DOMAIN,),
])
for platform in platforms {
self.args([
"--label",
&format!("{}.runs-with={platform}", crate::CROSS_LABEL_DOMAIN,),
]);
}
self
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/docker/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl<'a> Dockerfile<'a> {

docker_build.progress(None)?;
docker_build.verbose(msg_info.verbosity);
docker_build.cross_labels(options.target.triple(), self.runs_with().target.triple());
docker_build.cross_labels(options.target.triple(), &[self.runs_with().target.triple()]);

docker_build.args([
"--label",
Expand Down
16 changes: 8 additions & 8 deletions src/docker/provided_images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,42 @@ pub static PROVIDED_IMAGES: &[ProvidedImage] = &[
},
ProvidedImage {
name: "aarch64-unknown-linux-gnu",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "arm-unknown-linux-gnueabi",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "arm-unknown-linux-gnueabihf",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "armv7-unknown-linux-gnueabi",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "armv7-unknown-linux-gnueabihf",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "thumbv7neon-unknown-linux-gnueabihf",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "i586-unknown-linux-gnu",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
name: "i686-unknown-linux-gnu",
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU],
platforms: &[ImagePlatform::X86_64_UNKNOWN_LINUX_GNU, ImagePlatform::AARCH64_UNKNOWN_LINUX_GNU],
sub: None
},
ProvidedImage {
Expand Down
8 changes: 8 additions & 0 deletions targets.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dylib = true
std = true
run = true
runners = "qemu-user qemu-system"
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "arm-unknown-linux-gnueabi"
Expand All @@ -61,6 +62,7 @@ cpp = true
dylib = true
std = true
run = true
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "arm-unknown-linux-gnueabihf"
Expand All @@ -69,6 +71,7 @@ cpp = true
dylib = true
std = true
run = true
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "armv7-unknown-linux-gnueabi"
Expand All @@ -78,6 +81,7 @@ dylib = true
std = true
run = true
runners = "qemu-user"
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "armv7-unknown-linux-gnueabihf"
Expand All @@ -87,6 +91,7 @@ dylib = true
std = true
run = true
runners = "qemu-user qemu-system"
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "thumbv7neon-unknown-linux-gnueabihf"
Expand All @@ -96,6 +101,7 @@ dylib = true
std = true
run = true
runners = "qemu-user qemu-system"
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "i586-unknown-linux-gnu"
Expand All @@ -104,6 +110,7 @@ cpp = true
dylib = true
std = true
run = true
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "i686-unknown-linux-gnu"
Expand All @@ -113,6 +120,7 @@ dylib = true
std = true
run = true
runners = "native qemu-user qemu-system"
platforms = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

[[target]]
target = "loongarch64-unknown-linux-gnu"
Expand Down
33 changes: 23 additions & 10 deletions xtask/src/build_docker_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub struct BuildDockerImage {
#[clap(long)]
pub build_arg: Vec<String>,
// [os/arch[/variant]=]toolchain
#[clap(long, short = 'a', action = clap::builder::ArgAction::Append)]
#[clap(long, short = 'a', action = clap::builder::ArgAction::Append, value_delimiter = ',')]
pub platform: Vec<ImagePlatform>,
/// Targets to build for
#[clap()]
Expand Down Expand Up @@ -176,30 +176,35 @@ pub fn build_docker_image(
};

let mut results = vec![];
for (platform, (target, dockerfile)) in targets
.iter()
.flat_map(|t| platforms.iter().map(move |p| (p, t)))
{
for (target, dockerfile) in targets.iter() {
if gha && targets.len() > 1 {
gha_print("::group::Build {target}");
} else {
msg_info.note(format_args!("Build {target} for {}", platform.target))?;
msg_info.note(format_args!(
"Build {target} for {}",
platforms
.iter()
.map(|p| p.target.to_string())
.collect::<Vec<_>>()
.join(" and ")
))?;
}
let mut docker_build = engine.command();
docker_build.invoke_build_command();
let has_buildkit = docker::Engine::has_buildkit();
docker_build.current_dir(&docker_root);

let docker_platform = platform.docker_platform();
let docker_platforms: Vec<String> = platforms.iter().map(|p| p.docker_platform()).collect();
let mut dockerfile = dockerfile.clone();
docker_build.args(["--platform", &docker_platform]);
let uppercase_triple = target.name.to_ascii_uppercase().replace('-', "_");
docker_build.args([
"--build-arg",
&format!("CROSS_TARGET_TRIPLE={}", uppercase_triple),
]);
// add our platform, and determine if we need to use a native docker image
if has_native_image(docker_platform.as_str(), target, msg_info)? {
if docker_platforms.len() == 1
&& has_native_image(docker_platforms[0].as_str(), target, msg_info)?
{
let dockerfile_name = match target.sub.as_deref() {
Some(sub) => format!("Dockerfile.native.{sub}"),
None => "Dockerfile.native".to_owned(),
Expand All @@ -212,6 +217,7 @@ pub fn build_docker_image(
}
dockerfile = dockerfile_path.to_utf8()?.to_string();
}
docker_build.args(["--platform", &docker_platforms.join(",")]);

if push {
docker_build.arg("--push");
Expand All @@ -220,6 +226,7 @@ pub fn build_docker_image(
} else if no_output {
msg_info.fatal("cannot specify `--no-output` with engine that does not support the `--output` flag", 1);
} else if has_buildkit {
// TODO: docker daemon doesn't support loading multi-arch, so it will fail when platforms.len() > 1
docker_build.arg("--load");
}

Expand Down Expand Up @@ -287,7 +294,13 @@ pub fn build_docker_image(
docker_build.args(["--label", label]);
}

docker_build.cross_labels(&target.name, platform.target.triple());
docker_build.cross_labels(
&target.name,
&platforms
.iter()
.map(|p| p.target.triple())
.collect::<Vec<_>>(),
);
docker_build.args(["--file", &dockerfile]);

docker_build.progress(progress)?;
Expand Down
Loading
Loading