Ellie Fairholm @elliefairholm and Josep Giralt D’Lacoste @Gilacost,
After pushing the new branch in order to create the PR at the end of the “Updating Your CI/CD Workflow to Include a PostgreSQL Database” section, I’m getting the following error in Github during the build:
In the “Run docker/build-push-action@v5” step, the following error occurs: “Error: buildx failed with: ERROR: failed to solve: hexpm/elixir:1.16.0-erlang–debian-bullseye-20231009-slim: failed to resolve source metadata for docker.io/hexpm/elixir:1.16.0-erlang--debian-bullseye-20231009-slim: docker.io/hexpm/elixir:1.16.0-erlang--debian-bullseye-20231009-slim: not found”
Anyone else have any tips on how to get around this?
HI @SlowburnAZ. I think you might have an issue that is not related to the update in the CI workflow. It looks like you are trying to build an image that does not exist: docker.io/hexpm/elixir:1.16.0-erlang--debian-bullseye-20231009-slim
. If you look at the registry URL you will see that the Erlang version is not included. Could you please share your .tool-versions
, .githubt/workflows/ci_cd.yaml
and scripts/versions.sh
files?
Thanks, @Gilacost
Yeah, it seems I’m missing something somewhere, or there’s a typo I’m not catching.
Here’s my .tool-versions file:
github-cli 2.42.1
terraform 1.7.1
awscli 2.15.15
elixir 1.16.0-otp-26
erlang 26.2.1
postgres 15.2
packer 1.9.0
age 1.1.1
jq 1.7
sops 3.8.1
Here’s the .github/workflows/ci_cd.yaml file:
name: CI/CD Elixir
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
ci:
runs-on: ubuntu-latest
name: Compile with mix test, format, dialyzer & unused deps check
env:
MIX_ENV: test
services:
postgres:
image: postgres:15.2
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Setup Elixir
uses: erlef/setup-beam@v1.17.3
with:
version-file: .tool-versions
version-type: strict
- name: Cache deps directory
uses: actions/cache@v4
id: cache-deps
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-
- name: Get dependencies
if: steps.cache-deps.outputs.cache-hit != 'true'
run: mix deps.get
- name: Check unused dependencies
run: mix deps.unlock --check-unused
- run: mix compile --warnings-as-errors
- name: Check code is formatted
run: mix format --check-formatted
- name: Run tests
run: mix test --max-failures 1 --trace --warnings-as-errors
- name: Cache plt files
uses: actions/cache@v4
env:
EX_OTP_VERSIONS: ${{ steps.setup-beam.outputs.elixir-version }}
KEY_BASE: plt-${{ runner.os }}-${{ env.EX_OTP_VERSIONS }}
with:
path: |
priv/plts
key: |
${{ env.KEY_BASE }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ env.KEY_BASE }}-
- name: Dialyzer static analysis
run: mix dialyzer --format github
build-push:
runs-on: ubuntu-latest
needs: ci
name: Build Docker image & push to ghcr.io
steps:
- uses: actions/checkout@v4
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_PAT }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/{myusername}/kanban
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=pr
type=sha,format=short
- name: Parse versions from .tool-versions
id: parse-asdf
run: ./scripts/versions.sh
- uses: docker/setup-buildx-action@v3
- name: Setup QEMU
uses: docker/setup-qemu-action@v3
- uses: docker/build-push-action@v5
with:
context: .
cache-from: type=registry,ref=ghcr.io/{myusername}/kanban:cache
cache-to: type=registry,ref=ghcr.io/{myusername}/kanban:cache,mode=max
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64, linux/arm64
labels: ${{ steps.meta.outputs.labels }}
push: true
build-args: |
ELIXIR_VERSION=${{ env.ELIXIR_VERSION }}
OTP_VERSION=${{ env.ERLANG_VERSION }}
and finally, the scripts/versions.sh file:
#!/bin/bash
set -x
# read the version information from the ./tool-versions file
version_output=$(cat ./.tool-versions)
# extract the Elixir version
ELIXIR_VERSION=$(echo "$version_output" | grep 'elixir' | cut -d' ' -f2 | cut -d'-' -f1)
# extract Erlang version
ERLANG_VERSION=$(echo "$version_output" | grep 'erlang' | cur -d' ' -f2)
# add the variables to the `GITHUB_ENV` (env used by the action's runner)
{
echo "ELIXIR_VERSION=${ELIXIR_VERSION}";
echo "ERLANG_VERSION=${ERLANG_VERSION}";
} >> "$GITHUB_ENV"
Also, here’s the Dockerfile that the mix phx.gen.release --docker
command produced:
# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
# instead of Alpine to avoid DNS resolution issues in production.
#
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
# https://hub.docker.com/_/ubuntu?tab=tags
#
# This file is based on these images:
#
# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20231009-slim - for the release image
# - https://pkgs.org/ - resource for finding needed packages
# - Ex: hexpm/elixir:1.16.0-erlang-26.2.1-debian-bullseye-20231009-slim
#
ARG ELIXIR_VERSION=1.16.0
ARG OTP_VERSION=26.2.1
ARG DEBIAN_VERSION=bullseye-20231009-slim
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
FROM ${BUILDER_IMAGE} as builder
ENV ERL_FLAGS="+JPperf true"
# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
# prepare build dir
WORKDIR /app
# install hex + rebar
RUN mix local.hex --force && \
mix local.rebar --force
# set build ENV
ENV MIX_ENV="prod"
# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config
# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile
COPY priv priv
COPY lib lib
COPY assets assets
# compile assets
RUN mix assets.deploy
# Compile the release
RUN mix compile
# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/
COPY rel rel
RUN mix release
# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}
RUN apt-get update -y && \
apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
WORKDIR "/app"
RUN chown nobody /app
# set runner ENV
ENV MIX_ENV="prod"
# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/kanban ./
USER nobody
# If using an environment that doesn't automatically reap zombie processes, it is
# advised to add an init process such as tini via `apt-get install`
# above and adding an entrypoint. See https://github.com/krallin/tini for details
# ENTRYPOINT ["/tini", "--"]
CMD ["/app/bin/server"]
It seems the “OTP_VERSION” argument is defined and correct. Not sure why it’s not being included in the registry URL… ??
Thank you for sharing the files! You have a typo in your versions.sh
script in the bit that is trying to extract the Erlang version: it says “cur” rather than “cut”. Your versions.sh
should look like this:
#!/bin/bash
set -x
# read the version information from the ./tool-versions file
version_output=$(cat ./.tool-versions)
# extract the Elixir version
ELIXIR_VERSION=$(echo "$version_output" | grep 'elixir' | cut -d' ' -f2 | cut -d'-' -f1)
# extract Erlang version
ERLANG_VERSION=$(echo "$version_output" | grep 'erlang' | cut -d' ' -f2)
# add the variables to the `GITHUB_ENV` (env used by the action's runner)
{
echo "ELIXIR_VERSION=${ELIXIR_VERSION}";
echo "ERLANG_VERSION=${ERLANG_VERSION}";
} >> "$GITHUB_ENV"
To validate that this is working as expected, execute your ./scripts/versions.sh
script and check that it echoes the right ERLANG and ELIXIR versions.
Please let me know how it goes.
Oh geez, figures. Thank you! Yes, that shows the correct versions now.
1 Like