|
| 1 | +# Fix GitHub Release Asset Conflict |
| 2 | + |
| 3 | +## Problem |
| 4 | +The semantic-release CI/CD pipeline was failing with the error: |
| 5 | +``` |
| 6 | +{"resource":"ReleaseAsset","code":"already_exists","field":"name"} |
| 7 | +``` |
| 8 | + |
| 9 | +This occurred when trying to upload documentation files as GitHub release assets. The issue was that multiple `index.html` files existed in different subdirectories of the `docs/` folder (e.g., `docs/index.html`, `docs/coverage/index.html`, `docs/coverage/lcov-report/index.html`, etc.), and GitHub treats all files with the same basename as duplicate assets. |
| 10 | + |
| 11 | +## Root Cause |
| 12 | +The original semantic-release configuration attempted to upload all files in `docs/**/*` as individual assets: |
| 13 | + |
| 14 | +```json |
| 15 | +{ |
| 16 | + "path": "docs/**/*", |
| 17 | + "label": "Documentation" |
| 18 | +} |
| 19 | +``` |
| 20 | + |
| 21 | +When semantic-release processes this glob pattern, it uploads each file individually to GitHub Releases. Since GitHub uses only the basename for asset names (not the full path), multiple files named `index.html` caused conflicts. |
| 22 | + |
| 23 | +## Solution |
| 24 | +Changed the asset strategy from uploading individual files to creating a single compressed archive: |
| 25 | + |
| 26 | +### 1. Updated semantic-release configuration (`.releaserc.json`) |
| 27 | +```json |
| 28 | +{ |
| 29 | + "path": "docs-archive.tar.gz", |
| 30 | + "label": "Documentation Archive" |
| 31 | +} |
| 32 | +``` |
| 33 | + |
| 34 | +### 2. Modified CI/CD workflow (`.github/workflows/ci-cd.yml`) |
| 35 | +Added a step to create the documentation archive before semantic-release: |
| 36 | + |
| 37 | +```yaml |
| 38 | +- name: 📦 Create documentation archive |
| 39 | + run: | |
| 40 | + cd docs |
| 41 | + tar -czf ../docs-archive.tar.gz . |
| 42 | + cd .. |
| 43 | + echo "📦 Documentation archive created: $(du -h docs-archive.tar.gz)" |
| 44 | +``` |
| 45 | +
|
| 46 | +### 3. Created packaging script (`scripts/package-docs.sh`) |
| 47 | +Added a reusable script for local documentation packaging with: |
| 48 | +- Automated documentation generation if needed |
| 49 | +- Archive creation with compression |
| 50 | +- Size and content reporting |
| 51 | +- Error handling and validation |
| 52 | + |
| 53 | +### 4. Added npm script |
| 54 | +```json |
| 55 | +"docs:package": "./scripts/package-docs.sh" |
| 56 | +``` |
| 57 | + |
| 58 | +### 5. Updated .gitignore |
| 59 | +Added patterns to exclude documentation archives from git: |
| 60 | +``` |
| 61 | +# Documentation archives |
| 62 | +docs-archive.tar.gz |
| 63 | +*.docs.tar.gz |
| 64 | +``` |
| 65 | + |
| 66 | +## Benefits |
| 67 | +1. **Eliminates asset conflicts**: Single archive file prevents naming conflicts |
| 68 | +2. **Smaller release assets**: Compressed archive is more efficient than multiple files |
| 69 | +3. **Better download experience**: Users get complete documentation in one download |
| 70 | +4. **Consistent naming**: Archive name is predictable and unique |
| 71 | +5. **Local tooling**: Developers can package documentation locally for testing |
| 72 | + |
| 73 | +## Usage |
| 74 | +- **Local packaging**: `pnpm run docs:package` |
| 75 | +- **CI/CD**: Automatic during release process |
| 76 | +- **Download**: Single `.tar.gz` file in GitHub releases |
| 77 | + |
| 78 | +## File Structure |
| 79 | +``` |
| 80 | +docs-archive.tar.gz |
| 81 | +├── index.html # Main documentation |
| 82 | +├── api/ # API documentation |
| 83 | +├── coverage/ # Test coverage reports |
| 84 | +└── html/ # Generated HTML docs |
| 85 | +``` |
| 86 | +
|
| 87 | +This solution maintains all documentation functionality while eliminating the GitHub asset conflict error. |
0 commit comments