|
1 | | -name: Continuous Integration |
| 1 | +name: CI and Release |
2 | 2 |
|
3 | 3 | on: |
4 | 4 | push: |
|
7 | 7 | branches: [ "master" ] |
8 | 8 |
|
9 | 9 | permissions: |
10 | | - contents: read |
| 10 | + contents: write |
11 | 11 |
|
12 | 12 | env: |
13 | 13 | CARGO_TERM_COLOR: always |
|
17 | 17 | test: |
18 | 18 | name: Test Suite |
19 | 19 | runs-on: ubuntu-latest |
| 20 | + if: "!contains(github.event.head_commit.message, '[skip ci]')" |
20 | 21 |
|
21 | 22 | steps: |
22 | 23 | - name: Checkout repository |
@@ -69,3 +70,187 @@ jobs: |
69 | 70 |
|
70 | 71 | - name: Check formatting |
71 | 72 | run: cargo fmt --all -- --check |
| 73 | + |
| 74 | + release: |
| 75 | + name: Bump Version and Tag |
| 76 | + runs-on: ubuntu-latest |
| 77 | + needs: test |
| 78 | + if: github.event_name == 'push' && github.ref == 'refs/heads/master' |
| 79 | + outputs: |
| 80 | + new_version: ${{ steps.bump.outputs.new_version }} |
| 81 | + |
| 82 | + steps: |
| 83 | + - name: Checkout repository |
| 84 | + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 |
| 85 | + with: |
| 86 | + fetch-depth: 0 |
| 87 | + |
| 88 | + - name: Configure git |
| 89 | + run: | |
| 90 | + git config user.name "github-actions[bot]" |
| 91 | + git config user.email "github-actions[bot]@users.noreply.github.com" |
| 92 | +
|
| 93 | + - name: Setup Rust toolchain |
| 94 | + uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable |
| 95 | + with: |
| 96 | + toolchain: stable |
| 97 | + |
| 98 | + - name: Bump patch version |
| 99 | + id: bump |
| 100 | + run: | |
| 101 | + CURRENT=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') |
| 102 | + NEW=$(echo $CURRENT | awk -F. '{print $1"."$2"."$3+1}') |
| 103 | + echo "Current version: $CURRENT" |
| 104 | + echo "New version: $NEW" |
| 105 | + sed -i "s/^version = \"$CURRENT\"/version = \"$NEW\"/" Cargo.toml |
| 106 | + echo "new_version=$NEW" >> $GITHUB_OUTPUT |
| 107 | +
|
| 108 | + - name: Update Cargo.lock |
| 109 | + run: cargo check --locked || cargo update |
| 110 | + |
| 111 | + - name: Commit version bump |
| 112 | + run: | |
| 113 | + git add Cargo.toml Cargo.lock |
| 114 | + git commit -m "chore: bump version to v${{ steps.bump.outputs.new_version }} [skip ci]" |
| 115 | +
|
| 116 | + - name: Create and push tag |
| 117 | + run: | |
| 118 | + git tag "v${{ steps.bump.outputs.new_version }}" |
| 119 | + git push origin master --follow-tags |
| 120 | +
|
| 121 | + build: |
| 122 | + name: Build Release Binaries |
| 123 | + runs-on: ${{ matrix.os }} |
| 124 | + needs: release |
| 125 | + |
| 126 | + strategy: |
| 127 | + matrix: |
| 128 | + include: |
| 129 | + - os: ubuntu-latest |
| 130 | + target: x86_64-unknown-linux-gnu |
| 131 | + - os: macos-latest |
| 132 | + target: x86_64-apple-darwin |
| 133 | + - os: macos-latest |
| 134 | + target: aarch64-apple-darwin |
| 135 | + |
| 136 | + steps: |
| 137 | + - name: Checkout repository |
| 138 | + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 |
| 139 | + with: |
| 140 | + ref: v${{ needs.release.outputs.new_version }} |
| 141 | + |
| 142 | + - name: Setup Rust toolchain |
| 143 | + uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable |
| 144 | + with: |
| 145 | + toolchain: stable |
| 146 | + targets: ${{ matrix.target }} |
| 147 | + |
| 148 | + - name: Verify Cargo.lock is up to date |
| 149 | + run: cargo check --locked --target ${{ matrix.target }} |
| 150 | + |
| 151 | + - name: Cache cargo registry |
| 152 | + uses: actions/cache@v4 |
| 153 | + with: |
| 154 | + path: | |
| 155 | + ~/.cargo/registry/index/ |
| 156 | + ~/.cargo/registry/cache/ |
| 157 | + ~/.cargo/git/db/ |
| 158 | + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} |
| 159 | + restore-keys: | |
| 160 | + ${{ runner.os }}-cargo-registry- |
| 161 | +
|
| 162 | + - name: Build release binary |
| 163 | + run: | |
| 164 | + cargo build --release --target ${{ matrix.target }} |
| 165 | +
|
| 166 | + - name: Prepare binary artifact |
| 167 | + run: | |
| 168 | + mkdir -p artifacts |
| 169 | + if [[ "${{ matrix.os }}" == "windows-latest" ]]; then |
| 170 | + cp target/${{ matrix.target }}/release/devcontainer-sync.exe artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }}.exe |
| 171 | + ls -la artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }}.exe |
| 172 | + else |
| 173 | + cp target/${{ matrix.target }}/release/devcontainer-sync artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }} |
| 174 | + ls -la artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }} |
| 175 | + chmod +x artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }} |
| 176 | + fi |
| 177 | +
|
| 178 | + - name: Run smoke tests |
| 179 | + run: | |
| 180 | + if [[ "${{ matrix.os }}" == "windows-latest" ]]; then |
| 181 | + BINARY="artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }}.exe" |
| 182 | + else |
| 183 | + BINARY="artifacts/devcontainer-sync-v${{ needs.release.outputs.new_version }}-${{ matrix.target }}" |
| 184 | + fi |
| 185 | +
|
| 186 | + echo "Testing binary execution..." |
| 187 | + $BINARY --help |
| 188 | +
|
| 189 | + echo "Testing version output..." |
| 190 | + $BINARY --version |
| 191 | +
|
| 192 | + echo "Testing invalid command handling..." |
| 193 | + if $BINARY invalid-command 2>/dev/null; then |
| 194 | + echo "ERROR: Binary should fail on invalid command" |
| 195 | + exit 1 |
| 196 | + else |
| 197 | + echo "SUCCESS: Binary correctly handles invalid commands" |
| 198 | + fi |
| 199 | +
|
| 200 | + echo "Smoke tests passed for ${{ matrix.target }}" |
| 201 | +
|
| 202 | + - name: Upload build artifacts |
| 203 | + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 |
| 204 | + with: |
| 205 | + name: devcontainer-sync-${{ matrix.target }} |
| 206 | + path: artifacts/* |
| 207 | + retention-days: 1 |
| 208 | + |
| 209 | + create-release: |
| 210 | + name: Create GitHub Release |
| 211 | + runs-on: ubuntu-latest |
| 212 | + needs: [release, build] |
| 213 | + |
| 214 | + steps: |
| 215 | + - name: Checkout repository |
| 216 | + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 |
| 217 | + with: |
| 218 | + ref: v${{ needs.release.outputs.new_version }} |
| 219 | + fetch-depth: 0 |
| 220 | + |
| 221 | + - name: Download all artifacts |
| 222 | + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 |
| 223 | + with: |
| 224 | + path: artifacts |
| 225 | + |
| 226 | + - name: Prepare release assets |
| 227 | + run: | |
| 228 | + mkdir -p release-assets |
| 229 | + find artifacts -name "devcontainer-sync-*" -type f -exec cp {} release-assets/ \; |
| 230 | + ls -la release-assets/ |
| 231 | +
|
| 232 | + - name: Generate release notes |
| 233 | + run: | |
| 234 | + VERSION="v${{ needs.release.outputs.new_version }}" |
| 235 | + echo "## Release $VERSION" > release_notes.md |
| 236 | + echo "" >> release_notes.md |
| 237 | + echo "### Changes" >> release_notes.md |
| 238 | + git log --pretty=format:"- %s" $(git describe --tags --abbrev=0 HEAD^)..HEAD^ >> release_notes.md || echo "- Initial release" >> release_notes.md |
| 239 | + echo "" >> release_notes.md |
| 240 | + echo "### Downloads" >> release_notes.md |
| 241 | + echo "Choose the appropriate binary for your platform:" >> release_notes.md |
| 242 | + echo "- **Linux x86_64**: \`devcontainer-sync-$VERSION-x86_64-unknown-linux-gnu\`" >> release_notes.md |
| 243 | + echo "- **macOS x86_64**: \`devcontainer-sync-$VERSION-x86_64-apple-darwin\`" >> release_notes.md |
| 244 | + echo "- **macOS ARM64**: \`devcontainer-sync-$VERSION-aarch64-apple-darwin\`" >> release_notes.md |
| 245 | +
|
| 246 | + - name: Create GitHub Release |
| 247 | + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2.0.4 |
| 248 | + with: |
| 249 | + tag_name: v${{ needs.release.outputs.new_version }} |
| 250 | + name: Release v${{ needs.release.outputs.new_version }} |
| 251 | + body_path: release_notes.md |
| 252 | + files: release-assets/* |
| 253 | + draft: false |
| 254 | + prerelease: false |
| 255 | + env: |
| 256 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
0 commit comments