`Unused dependencies in mix.lock file` after upload, then download `deps` directory

Hello :wave:

I’ve been struggling with GitHub Actions lately. I’m trying to parallelize my tests, and this includes building the project once, and then starting more tests. To achieve that, I tried to use GHA artifacts to move the built project from one job to another, but I’m having trouble with that.

Basically, in the first job I download the dependencies, build the project, upload deps directory to GitHub as an artifact. All good up to this point :ok_hand:
However, when I download the artifact and try to run my first test mix deps.unlock --check-unused, I get an Unused dependencies in mix.lock file .

Things I tried

  • At first, I uploaded the _build directory too, but when removing it the issue still appears,
  • If I run mix deps.get right after downloading, some dependencies are updated - and then the job goes on without issue,
  • use a different command after downloading, but they always end up in errors, for apparently the same reason (some deps are outdated),
  • after cleaning up the project, I tried to run mix deps.get; zip -r archive.zip deps; rm -rf deps; unzip archive.zip; mix deps.unlock --check-unused and it worked well

It may be important to note that the artifact upload/download archives and unarchives the files. Sooo, I’m wondering if mix uses some information about these files that are lost in the archiving process, like the time of creation or update or something, and if there’s a workaround to fix this - or maybe I’m just doing something wrong, but I have no idea what :smile:

Workflow file excerpt

This is the simplest workflow file I could come up with to reproduce the problem.

[...]

env:
  # Ensure everything is run in the test environment,
  # avoiding multiple compilations of the same code.
  MIX_ENV: test

jobs:
  build:
    name: Build project
    runs-on: ubuntu-22.04

    steps:
      - uses: actions/checkout@v3
      - name: Setup up Elixir
        uses: ./.github/workflows/composite/setup-elixir
      - run: mix deps.get --check-locked
      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: build
          path: |
            deps
          if-no-files-found: error

  validate:
    name: Validate code
    runs-on: ubuntu-22.04
    needs: build

    steps:
      - uses: actions/checkout@v3
      - name: Setup up Elixir
        uses: ./.github/workflows/composite/setup-elixir
      - uses: actions/download-artifact@v4
        with:
          name: build
      - name: Run code validation
        run: mix deps.unlock --check-unused

Thanks in advance for you input!

Your mix.lock file contains a (sub)dependency that isn’t used (not defined in mix.exs or defined by another dependency in mix.exs). You can remove those entries from the lock file using

mix deps.clean --unlock --unused.

Sorry, I’m not following. Where should I run this command? I tried locally, and that did not change the mix.lock. I tried to run mix deps.unlock --unused too, same thing, the dependencies in mix.lock seem correct. mix deps.get --check-locked would probably have caught such problem, wouldn’t it?

You are right, I missed that part.

I think you need to set the path option for actions/download-artifact@v4, otherwise the content of deps is placed in the root directory instead of under deps/.

- uses: actions/download-artifact@v4
        with:
          name: build
          path: deps

Well spotted, but I do have another error now, which was actually the first error I got, I tried to make the yaml too minimal and got a different error, I just didn’t realize it, sorry for that :sweat_smile:

So, unfun fact, mix deps.unlock --check-unused now works correctly. But mix compile still doesn’t work. I get an error Unchecked dependencies for environment test:, then some dependencies are listed (not all!) with a warning lock mismatch: the dependency is out of date. To fetch locked version run "mix deps.get"

Here’s the updated YAML:

env:
  # Ensure everything is run in the test environment,
  # avoiding multiple compilations of the same code.
  MIX_ENV: test

jobs:
  build:
    name: Build project
    runs-on: ubuntu-22.04

    steps:
      - uses: actions/checkout@v3
      - name: Setup up Elixir
        uses: ./.github/workflows/composite/setup-elixir
      - run: mix deps.get --check-locked
      - run: mkdir -p _build/test
      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: build
          path: |
            _build
            deps
          if-no-files-found: error

  validate:
    name: Validate code
    runs-on: ubuntu-22.04
    needs: build

    steps:
      - uses: actions/checkout@v3
      - name: Setup up Elixir
        uses: ./.github/workflows/composite/setup-elixir
      - uses: actions/download-artifact@v4
        with:
          name: build
      - run: ls -l # just to verify `deps` is correctly placed
      - name: Run code validation
        run: mix compile --warnings-as-errors

I found the origin of my problem! It was indeed actions/upload-workflow, which does not include hidden files by default :sweat_smile: I had to add the parameter include-hidden-files: true, and deps are now copied correctly.

2 Likes