Artifacts

RWX can extract artifacts from your task once it has finished running. These artifacts can be downloaded in the RWX UI and used in subsequent tasks.

Example

Consider a task which runs your test suite and tracks code coverage statistics. Without artifacts, you might upload those coverage results within the same task. However, with artifacts, you can extract the coverage results and use them in another task.

tasks:
  - key: run-tests
    run: ./run-my-tests.sh
    outputs:
      artifacts:
        - key: coverage
          path: tmp/coverage

  - key: upload-coverage
    after: ${{ run-tests.succeeded || run-tests.failed }}
    run: ./upload-coverage.sh $COVERAGE_DIR
    env:
      COVERAGE_DIR: ${{ tasks.run-tests.artifacts.coverage }}

$RWX_ARTIFACTS

As an alternative to declaring outputs.artifacts, your task can write files directly to the $RWX_ARTIFACTS directory. RWX uploads every top-level entry under $RWX_ARTIFACTS as an artifact, using the entry's name as the artifact key.

tasks:
  - key: generate-report
    run: |
      ./gather-metrics.sh > $RWX_ARTIFACTS/metrics.json
      ./build-report.sh --output $RWX_ARTIFACTS/report

The generate-report task above produces two artifacts without any outputs.artifacts declaration: a metrics.json file and a report directory. The same file and directory packaging rules apply, and downstream tasks reference them the same way.

Use outputs.artifacts when the file you want to upload is already on your task's filesystem — for instance, build output or coverage results. Use $RWX_ARTIFACTS when you're producing a file solely so RWX can upload it, or when a tool needs to write artifacts dynamically without the task definition listing them up front.

You can use both in the same task. If a top-level entry under $RWX_ARTIFACTS has the same name as a key declared in outputs.artifacts, the task will fail. Rename the file or change the key to resolve the conflict.

Parallel Tasks

When a parallel task group produces artifacts, each parallel task's artifacts are mounted in a subdirectory named after the task key.

tasks:
  - key: parallel-group
    parallel: 2
    run: touch a.txt
    outputs:
      artifacts:
        - key: a
          path: a.txt

  - key: list-artifacts
    run: find ${{ tasks.parallel-group.artifacts.a }}

The artifact expression resolves to a directory containing a subdirectory for each parallel task:

parallel-group-0/a.txt
parallel-group-1/a.txt

Files

When path points to a file in your task's filesystem, RWX will produce a .tar.gz archive which contains your file at the root. For example, if path were some/path/to/file.txt, the artifact would contain file.txt at the root.

When you reference the artifact with a RWX expression to use in a subsequent task, it'll point to file.txt directly. This lets you use the artifact path as if it were a bash variable.

Directories

When path points to a directory in your task's filesystem, RWX will produce a .tar.gz archive which contains the contents of that directory at the root of the archive. For example, if path were some/path and some/path contains both hello.txt and world.txt, the artifact would contain those two files at the root.

When you reference the artifact with an RWX expression to use in a subsequent task, it'll point to directory containing those files directly. Like files, this lets you use the artifact path as if it were a bash variable.

Filtering

Directory artifacts (including the .rwx directory via ${{ run.dir }}) can be filtered just like the filesystem of a task to improve cache hits when using artifact contents. You can filter artifacts with the following syntax:

tasks:
  - key: upload-artifact
    run: |
      mkdir -p path/to/my-artifact
      echo one | tee path/to/my-artifact/one.txt
      echo two | tee path/to/my-artifact/two.txt
    outputs:
      artifacts:
        - key: my-artifact
          path: path/to/my-artifact

  - key: use-only-one-txt
    run: |
      ls ${{ tasks.upload-artifact.artifacts.my-artifact }}
      cat ${{ tasks.upload-artifact.artifacts.my-artifact }}/one.txt
    filter:
      ${{ tasks.upload-artifact.artifacts.my-artifact }}:
        - one.txt

If you also need to filter the workspace, you can specify the workspace key within filter:

tasks:
  - key: files
    run: |
      echo a | tee a.txt
      echo b | tee b.txt

  - key: upload-artifact
    run: |
      mkdir -p path/to/my-artifact
      echo one | tee path/to/my-artifact/one.txt
      echo two | tee path/to/my-artifact/two.txt
    outputs:
      artifacts:
        - key: my-artifact
          path: path/to/my-artifact

  - key: use-only-one-txt-and-a-txt
    use: files
    run: |
      ls ./
      cat a.txt

      ls ${{ tasks.upload-artifact.artifacts.my-artifact }}
      cat ${{ tasks.upload-artifact.artifacts.my-artifact }}/one.txt
    filter:
      workspace:
        - a.txt
      ${{ tasks.upload-artifact.artifacts.my-artifact }}:
        - one.txt