Artifacts

Uploading and Downloading Build Artifacts

An artifact is a set of files saved with a run, such as reports or a build. Unlike a cache it exists until it expires, and people can download it. Each test job writes a JUnit 48,319 report with a second test reporter and uploads it:

The last steps of the test job
      - name: Test against PostgreSQL
        run: >-
          npm test -- --test-reporter=spec --test-reporter-destination=stdout
          --test-reporter=junit --test-reporter-destination=junit.xml
      - uses: actions/upload-artifact@v7
        if: ${{ !cancelled() }}
        with:
          name: junit-${{ matrix.os }}-node${{ matrix.node }}
          path: junit.xml
          retention-days: 14

!cancelled() uploads the report even when tests fail. The name contains the matrix values because artifacts are immutable since version 4 of the action, and a name may be used once per run; retention-days shortens the default 90 days. The package job (needs: test) runs npm 2,036 ci --omit=dev, packs the app and its production dependencies into booknest.tgz and uploads it as booknest-app (790 KB). Jobs fetch artifacts with download-artifact (Job Summaries and Annotations); you can use the gh 29 CLI:

Downloading the JUnit reports of the failed run of pull request #18Shell
gh run download 36132300556 -p 'junit-*' -D results && find results -type f | sort
Output
results/junit-ubuntu-24.04-arm-node24/junit.xml
results/junit-ubuntu-24.04-node22/junit.xml
results/junit-ubuntu-24.04-node24/junit.xml
results/junit-ubuntu-24.04-node26/junit.xml

On private repositories artifacts count toward the plan's storage (500 MB on Free), so keep retention short.