|
| 1 | +# Upload Modified Files Action |
| 2 | + |
| 3 | +## Description |
| 4 | + |
| 5 | +The `upload-modified-files` action detects files that have been modified in the working tree of a checked-out repository and uploads them to the current workflow run as an artifact. It is designed for the pattern where one repository (for example, a build repo) produces changes to tracked files — such as version bumps — and a downstream repository (for example, a deploy repo) downloads those changes and commits them back using a bot with direct push access. |
| 6 | + |
| 7 | +The action runs in two steps: |
| 8 | + |
| 9 | +1. **Detect modified files.** Inspects `git status` and collects modifications to existing tracked files. It **fails if any files are added (new/untracked) or deleted**, because the downstream consumer commits the files over an existing checkout and cannot safely reconcile additions or removals. |
| 10 | +2. **Upload to the workflow run.** Archives the modified files into a `tar.gz` that preserves their exact repo-relative paths, then uploads it as an artifact. |
| 11 | + |
| 12 | +## Key Features |
| 13 | + |
| 14 | +- **Modification-only safety check**: Fails fast on added or deleted files so only in-place edits are propagated. |
| 15 | +- **Exact path preservation**: Files are archived with their full repo-relative paths, so they restore to the same structure when extracted in another repo — even when the changes span subdirectories. |
| 16 | +- **Simple, self-contained**: Pure `git` and `tar`, no external dependencies beyond what GitHub-hosted runners provide. |
| 17 | + |
| 18 | +## How to Use It |
| 19 | + |
| 20 | +Add this step after a step that modifies tracked files (e.g. a version bump). The repository must already be checked out. |
| 21 | + |
| 22 | +```yaml |
| 23 | +- name: Checkout |
| 24 | + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| 25 | + with: |
| 26 | + persist-credentials: false |
| 27 | + |
| 28 | +# ... step(s) that modify tracked files, e.g. a version bump ... |
| 29 | + |
| 30 | +- name: Upload modified files |
| 31 | + id: upload |
| 32 | + uses: bitwarden/gh-actions/upload-modified-files@main |
| 33 | + with: |
| 34 | + artifact_name: modified-files |
| 35 | + retention_days: '7' |
| 36 | +``` |
| 37 | +
|
| 38 | +### Inputs |
| 39 | +
|
| 40 | +| Input | Required | Default | Description | |
| 41 | +| ---------------- | -------- | ---------------- | -------------------------------------------------------- | |
| 42 | +| `artifact_name` | No | `modified-files` | Name of the artifact to upload the modified files under. | |
| 43 | +| `retention_days` | No | `7` | Number of days to retain the uploaded artifact. | |
| 44 | + |
| 45 | +### Outputs |
| 46 | + |
| 47 | +| Output | Description | |
| 48 | +| ---------------- | ------------------------------------------------------------ | |
| 49 | +| `artifact_name` | Name of the artifact the modified files were uploaded under. | |
| 50 | +| `count` | Number of modified files detected and uploaded. | |
| 51 | +| `modified_files` | Newline-separated list of modified file paths. | |
| 52 | + |
| 53 | +## Consuming the Artifact |
| 54 | + |
| 55 | +The artifact contains a single file, `modified-files.tar.gz`, holding the modified files at their original repo-relative paths. In a downstream repository, download it, extract it over the checkout, and commit: |
| 56 | + |
| 57 | +```yaml |
| 58 | +- name: Checkout target repo |
| 59 | + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| 60 | +
|
| 61 | +- name: Download modified files |
| 62 | + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 |
| 63 | + with: |
| 64 | + name: modified-files |
| 65 | + path: modified-files-tmp |
| 66 | + github-token: ${{ steps.app-token.outputs.token }} |
| 67 | + run-id: ${{ github.event.workflow_run.id }} |
| 68 | + repository: bitwarden/source-repo |
| 69 | +
|
| 70 | +- name: Apply and commit |
| 71 | + run: | |
| 72 | + tar -xzf modified-files-tmp/modified-files.tar.gz |
| 73 | + git add --update |
| 74 | + git commit -m "Apply modified files from upstream run" |
| 75 | + git push |
| 76 | +``` |
| 77 | + |
| 78 | +> For cross-repo downloads, generate a GitHub App token scoped to the source repository and pass it to `actions/download-artifact` via `github-token`, along with the upstream `run-id` and `repository`. |
| 79 | + |
| 80 | +## Requirements |
| 81 | + |
| 82 | +- The repository must be checked out before this action runs (`actions/checkout`), with the modifications present in the working tree. |
| 83 | +- `git` and `tar` must be available on the runner (present by default on GitHub-hosted runners). |
| 84 | + |
| 85 | +## Troubleshooting |
| 86 | + |
| 87 | +### "Detected added/untracked files, which are not supported" |
| 88 | + |
| 89 | +- The working tree contains new files that are not tracked by git. This action only uploads modifications to existing tracked files. Remove the new files or handle them separately. |
| 90 | + |
| 91 | +### "Detected deleted files, which are not supported" |
| 92 | + |
| 93 | +- A tracked file was removed from the working tree. The downstream consumer cannot safely apply deletions; revert the deletion or handle it separately. |
| 94 | + |
| 95 | +### "No modified files detected. Nothing to upload." |
| 96 | + |
| 97 | +- The working tree is clean. Confirm the step that is supposed to modify files ran before this action and actually changed something. |
| 98 | + |
| 99 | +### Nested paths are missing after download |
| 100 | + |
| 101 | +- Ensure you extract `modified-files.tar.gz` from the repository root in the downstream job so the preserved repo-relative paths land in the right place. |
0 commit comments