diff --git a/.changes/1033.json b/.changes/1033.json new file mode 100644 index 000000000..435d43df6 --- /dev/null +++ b/.changes/1033.json @@ -0,0 +1,5 @@ +{ + "description": "fix --cache-from using podman.", + "type": "fixed", + "issues": [1031] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e88e30a0..792e11923 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -319,6 +319,45 @@ jobs: run: ./ci/test-docker-in-docker.sh shell: bash + podman: + name: podman + runs-on: ubuntu-latest + needs: [shellcheck, test, check] + if: github.event_name == 'push' + strategy: + fail-fast: false + 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 + + - uses: ./.github/actions/setup-rust + + - name: Install Podman + env: + DEBIAN_FRONTEND: noninteractive + run: | + sudo apt-get update + sudo apt-get install podman --no-install-recommends --assume-yes + + - name: LLVM instrument coverage + id: cov + uses: ./.github/actions/cargo-llvm-cov + with: + name: cross-podman-aarch64-unknown-linux-gnu + + - name: Install cross + run: cargo install --path . --force --debug + + - name: Run Podman Test + run: ./ci/test-podman.sh + env: + CROSS_CONTAINER_ENGINE: podman + TARGET: aarch64-unknown-linux-gnu + shell: bash + publish: needs: [build, check, fmt, clippy, cargo-deny] runs-on: ubuntu-latest @@ -331,7 +370,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} conclusion: - needs: [shellcheck, fmt, clippy, test, generate-matrix, build, publish, check, remote, bisect, docker-in-docker, foreign] + needs: [shellcheck, fmt, clippy, test, generate-matrix, build, publish, check, remote, bisect, docker-in-docker, foreign, podman] if: always() runs-on: ubuntu-latest steps: diff --git a/ci/test-podman.sh b/ci/test-podman.sh new file mode 100755 index 000000000..774977c79 --- /dev/null +++ b/ci/test-podman.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# shellcheck disable=SC1091,SC1090 + +# test to see that running and building images with podman works. + +set -x +set -eo pipefail + +export CROSS_CONTAINER_ENGINE=podman +if [[ -z "${TARGET}" ]]; then + export TARGET="aarch64-unknown-linux-gnu" +fi + +ci_dir=$(dirname "${BASH_SOURCE[0]}") +ci_dir=$(realpath "${ci_dir}") +. "${ci_dir}"/shared.sh + +main() { + local td= + local parent= + local target="${TARGET}" + + retry cargo fetch + cargo build + export CROSS="${PROJECT_HOME}/target/debug/cross" + + td="$(mkcargotemp -d)" + parent=$(dirname "${td}") + pushd "${td}" + cargo init --bin --name "hello" . + + echo '[build] +pre-build = ["apt-get update"]' > "${parent}/Cross.toml" + + CROSS_CONTAINER_ENGINE="${CROSS_ENGINE}" "${CROSS}" build --target "${target}" --verbose + + popd + rm -rf "${td}" +} + +main diff --git a/src/docker/engine.rs b/src/docker/engine.rs index f36b91ddd..f0aa5367f 100644 --- a/src/docker/engine.rs +++ b/src/docker/engine.rs @@ -17,21 +17,45 @@ pub enum EngineType { Docker, Podman, PodmanRemote, + Nerdctl, Other, } impl EngineType { /// Returns `true` if the engine type is [`Podman`](Self::Podman) or [`PodmanRemote`](Self::PodmanRemote). #[must_use] - pub fn is_podman(&self) -> bool { + pub const fn is_podman(&self) -> bool { matches!(self, Self::Podman | Self::PodmanRemote) } /// Returns `true` if the engine type is [`Docker`](EngineType::Docker). #[must_use] - pub fn is_docker(&self) -> bool { + pub const fn is_docker(&self) -> bool { matches!(self, Self::Docker) } + + /// Returns `true` if the build command supports the `--output` flag. + #[must_use] + pub const fn supports_output_flag(&self) -> bool { + !matches!(self, Self::Other) + } + + /// Returns `true` if the build command supports the `--pull` flag. + #[must_use] + pub const fn supports_pull_flag(&self) -> bool { + !matches!(self, Self::Nerdctl | Self::Other) + } + + /// Returns `true` if the build command supports the `--cache-from type=` key. + /// + /// Some container engines, especially podman, do not support the `type` + /// key of `--cache-from` during the image build steps. They also do + /// not support any tags for the `--cache-from` steps either. See: + /// https://docs.podman.io/en/latest/markdown/podman-build.1.html#cache-from + #[must_use] + pub const fn supports_cache_from_type(&self) -> bool { + matches!(self, Self::Docker | Self::Nerdctl) + } } #[derive(Clone, Debug, PartialEq, Eq)] @@ -132,6 +156,8 @@ fn get_engine_info( EngineType::PodmanRemote } else if stdout_help.contains("podman") { EngineType::Podman + } else if stdout_help.contains("nerdctl") { + EngineType::Nerdctl } else if stdout_help.contains("docker") && !stdout_help.contains("emulate") { EngineType::Docker } else { diff --git a/xtask/src/build_docker_image.rs b/xtask/src/build_docker_image.rs index 07df5bf95..2d7e90e43 100644 --- a/xtask/src/build_docker_image.rs +++ b/xtask/src/build_docker_image.rs @@ -187,8 +187,10 @@ pub fn build_docker_image( if push { docker_build.arg("--push"); - } else if engine.kind.is_docker() && no_output { + } else if engine.kind.supports_output_flag() && no_output { docker_build.args(["--output", "type=tar,dest=/dev/null"]); + } 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 { docker_build.arg("--load"); } @@ -216,10 +218,12 @@ pub fn build_docker_image( tags = vec![target.image_name(&repository, tag)]; } - docker_build.arg("--pull"); + if engine.kind.supports_pull_flag() { + docker_build.arg("--pull"); + } if no_cache { docker_build.arg("--no-cache"); - } else { + } else if engine.kind.supports_cache_from_type() { docker_build.args([ "--cache-from", &format!( @@ -227,6 +231,8 @@ pub fn build_docker_image( target.image_name(&repository, "main") ), ]); + } else { + docker_build.args(["--cache-from", &format!("{repository}/{}", target.name)]); } if push {