181

Trying to use Github's beta actions, I have two jobs, one that builds the code and then one that will deploy code. However, I can't seem to get the build artifact in deploy job.

My latest attempt is to manually set a container image with the same volumes for each job, according to docs this should be solution: https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idcontainervolumes

Sets an array of volumes for the container to use. You can use volumes to share data between services or other steps in a job. You can specify named Docker volumes, anonymous Docker volumes, or bind mounts on the host.

Workflow

name: CI
on:
  push:
    branches:
    - master
    paths:
    - .github/workflows/server.yml
    - server/*
jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: docker://node:10
      volumes:
      - /workspace:/github/workspace
    steps:
    - uses: actions/checkout@master
    - run: yarn install
      working-directory: server
    - run: yarn build
      working-directory: server
    - run: yarn test
      working-directory: server
    - run: ls
      working-directory: server
  deploy:
    needs: build
    runs-on: ubuntu-latest
    container:
      image: docker://google/cloud-sdk:latest
      volumes:
      - /workspace:/github/workspace
    steps:
      - uses: actions/checkout@master
      - run: ls
        working-directory: server
      - run: gcloud --version

The first job (build) has a build directory, but when the second job (deploy) runs it doesn't and only contains the source code.

This project is a mono repo with code I'm trying to deploy being under path server hence all the working-directory flags.

Labithiotis
  • 3,519
  • 7
  • 27
  • 47
  • 4
    See https://stackoverflow.com/questions/57509118/new-github-actions-run-in-empty-folders - the [Workflow syntax docs](https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobs) say "Each job runs in a fresh instance of the virtual environment specified by runs-on." My guess (I'm not in the beta so I'm just guessing) is that your deploy job would either need to become a step in the `build` job, or would need to reproduce the `build` steps again in the new container. (Minus, perhaps, the `yarn test` step since you already know that it succeeded). – rmunn Aug 19 '19 at 07:42
  • 2
    Did you ever find an answer for this? I'm trying to figure out how to do this as well.. From what i've read jobs are supposed to share the workspace filesystem, but it doesn't seem to be the case. – Joseph Aug 20 '19 at 17:56
  • 1
    @Joseph nope, I'm just running one job and using custom docker image. I believe issue sits with GitHub and is likely due to the transitioning from HCL to YML syntax. Odd that they plan to drop HCL at the end of September and the basic ability to share artefacts between jobs doesn't work yet. Hopefully, in a months time, it will be resolved. – Labithiotis Aug 21 '19 at 08:29
  • "You can use volumes to share data between services or other steps in a job." That means sharing data within a single job between steps. It's not for sharing data between steps or workflows. – thisismydesign Jan 31 '20 at 15:43
  • 3 years, 5 months later, and this is still not possible without using artifacts or cache. GitHub, if you will ever read this, a simple keyword `after: ` would be amazing. – Eduardo Pignatelli Jan 18 '23 at 23:39
  • Github Actions is my source of frustration this week I don't believe they had an intent to create it for humans. Funniest thing we can find lots of beautiful pictures of workflow graphs, but no real example of implementing such pipeline without ducktape. – ZuzEL May 20 '23 at 23:51

5 Answers5

152

You can use the Github Actions upload-artifact and download-artifact to share data between jobs.

In job1:

steps:
- uses: actions/checkout@v1

- run: mkdir -p path/to/artifact

- run: echo hello > path/to/artifact/world.txt

- uses: actions/upload-artifact@master
  with:
    name: my-artifact
    path: path/to/artifact

And job2:

steps:
- uses: actions/checkout@master

- uses: actions/download-artifact@master
  with:
    name: my-artifact
    path: path/to/artifact
    
- run: cat path/to/artifact/world.txt

https://github.com/actions/upload-artifact
https://github.com/actions/download-artifact

qmacro
  • 3,025
  • 23
  • 33
Tyler Carberry
  • 2,001
  • 1
  • 14
  • 10
  • 3
    you can now also delete artifacts: https://github.com/marketplace/actions/delete-run-artifacts https://github.com/marketplace/actions/purge-artifacts – Chris Mar 11 '20 at 18:54
  • @qmacro I'd like to do something like this, but I would like to build a Docker image that I would use in a following jobs' `services` rather than its `steps`. Don't see how that's possible, since the artifact downloading would be done only _after_ the `services` are started. Any suggestions? – Robert P. Goldman Sep 28 '21 at 20:02
  • 1
    while this is indeed an option, for anything serious (imagine 50 docker images shared), using this approach takes tens of minutes. Since github does not offer a proper solution, we switched to circleci, which cut the builds by at least 1 hour. its very, very weird not to have such an option – Eugene Jul 31 '22 at 06:44
  • The order of the steps in 2nd job is very important. `checkout` action deletes everything :) – Anton Krosnev May 17 '23 at 11:01
37

For those interested in sharing a Docker image between two jobs, here is how I did it:

jobs:
  docker-build:
    name: Docker build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Build Docker image
        run: |
          docker build -t foo/bar:$GITHUB_SHA
          mkdir -p path/to/artifacts
          docker save foo/bar:$GITHUB_SHA > path/to/artifacts/docker-image.tar
          
      - name: Temporarily save Docker image
        uses: actions/upload-artifact@v2
        with:
          name: docker-artifact
          path: path/to/artifacts
          retention-days: 1

  docker-deploy:
    name: Deploy to Docker Hub
    runs-on: ubuntu-latest
    needs: docker-build
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Retrieve saved Docker image
        uses: actions/download-artifact@v2
        with:
          name: docker-artifact
          path: path/to/artifacts

      - name: Docker load
        run: |
          cd path/to/artifacts
          docker load < docker-image.tar
          # docker_build_push.sh

Very inspired by https://github.com/unfor19/install-aws-cli-action/actions/runs/400601222/workflow

Merci @unfor19

Thomas
  • 1,491
  • 13
  • 23
  • 1
    For anyone coming across this and wondering how to avoid cluttering up your artifacts since github doesn't provide an action for that: there are several community actions, e.g. https://github.com/marketplace/actions/delete-artifact – Alan Plum Jan 25 '21 at 18:38
  • 4
    @AlanPlum Well said. We do clean up artifacts now with the parameter `retention-days`. I'll update my answer. Thanks. – Thomas Jan 26 '21 at 19:24
  • this is indeed an option, but if you have many images, this is a very painful and slow option. Other CI/CD frameworks have this by default, github does not. – Eugene Jul 31 '22 at 06:46
  • 1
    `retention-days` is the key! Otherwise Github gonna waste your money – orkenstein Aug 24 '22 at 20:27
24

Use Cache or Artifacts Upload/Download

Caching is used to re-use data/files between jobs or workflows while Artifacts are used to save files after workflow ended.

Psijic
  • 743
  • 7
  • 20
22

If you are using the upload/download GitHub Actions, beware of the structure of the artifact.

Starting January 2020, see "GitHub Actions: Changes to artifact download experience":

We have changed the artifact download experience in GitHub Actions so it no longer adds an extra root directory to the downloaded archive.

Previously, if you uploaded the following files and folders as an artifact named foo, the downloaded archive would contain the following structure:

foo/
 |-- file1.txt
 |-- dir1/
 |    |-- dir1-file1.txt

Now, you will get an archive that only contains the files and folders you uploaded:

file1.txt
dir1/
|-- dir1-file1.txt
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
1

Each job runs on the separate runner.

Upload artifact action implementation

Github Action "actions/upload-artifact@v3" uploads the files from provided path to storage container location.

In next job when you run action "actions/download-artifact@v3" , it downloads the artifact from 'storage container location' where previous job uploaded the artifacts to provided path.

Implementation for download artifact and displaying download path

For more information refer below links,

Github action for upload artifacts

Github action for download artifacts

chetan kadam
  • 15
  • 1
  • 6