Revert to alien for RPM packaging - rpmdevtools not available on Ubuntu #17
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| branches: | |
| - 'release/*' # Only trigger on release branches | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Tag to release' | |
| required: true | |
| default: 'v0.1.0' | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| permissions: | |
| contents: write | |
| packages: write | |
| jobs: | |
| build: | |
| strategy: | |
| matrix: | |
| include: | |
| # Windows | |
| - target: x86_64-pc-windows-msvc | |
| os: windows-latest | |
| name: httpc-windows-x64 | |
| # macOS | |
| - target: x86_64-apple-darwin | |
| os: macos-latest | |
| name: httpc-macos-x64 | |
| - target: aarch64-apple-darwin | |
| os: macos-latest | |
| name: httpc-macos-arm64 | |
| # Linux | |
| - target: x86_64-unknown-linux-gnu | |
| os: ubuntu-latest | |
| name: httpc-linux-x64 | |
| - target: aarch64-unknown-linux-gnu | |
| os: ubuntu-latest | |
| name: httpc-linux-arm64 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/registry | |
| key: ${{ runner.os }}-${{ matrix.target }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Cache cargo index | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/git | |
| key: ${{ runner.os }}-${{ matrix.target }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Cache cargo build | |
| uses: actions/cache@v4 | |
| with: | |
| path: target | |
| key: ${{ runner.os }}-${{ matrix.target }}-cargo-build-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Install cross-compilation tools (Linux ARM64) | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-aarch64-linux-gnu | |
| - name: Configure cross-compilation (Linux ARM64) | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| run: | | |
| mkdir -p ~/.cargo | |
| echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml | |
| echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml | |
| - name: Build release binary | |
| run: cargo build --release --target ${{ matrix.target }} | |
| - name: Prepare binary (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| cp target/${{ matrix.target }}/release/httpc.exe ${{ matrix.name }}.exe | |
| - name: Prepare binary (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| cp target/${{ matrix.target }}/release/httpc ${{ matrix.name }} | |
| chmod +x ${{ matrix.name }} | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.name }} | |
| path: ${{ matrix.name }}${{ runner.os == 'Windows' && '.exe' || '' }} | |
| if-no-files-found: error | |
| build-packages: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download Linux binary | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: httpc-linux-x64 | |
| path: binaries/ | |
| - name: Install packaging tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y alien fakeroot gzip | |
| # Verify tools are available | |
| which alien || echo "alien not found" | |
| which fakeroot || echo "fakeroot not found" | |
| which gzip || echo "gzip not found" | |
| # Show versions | |
| alien --version | |
| gzip --version | |
| - name: Setup package structure | |
| run: | | |
| chmod +x binaries/httpc-linux-x64 | |
| # Create directory structure for packaging | |
| mkdir -p packaging/usr/bin | |
| mkdir -p packaging/usr/share/man/man1 | |
| mkdir -p packaging/DEBIAN | |
| mkdir -p packaging/usr/share/doc/httpc | |
| mkdir -p packaging/etc/httpc | |
| # Copy binary | |
| cp binaries/httpc-linux-x64 packaging/usr/bin/httpc | |
| # Create profiles template | |
| cat > packaging/etc/httpc/profiles.example << 'EOF' | |
| # httpc Configuration Profiles | |
| # Copy this file to ~/.httpc/profile and customize as needed | |
| [default] | |
| host = https://api.example.com | |
| @content-type = application/json | |
| @accept = application/json | |
| # user = username | |
| # password = password | |
| # insecure = false | |
| # ca_cert = /path/to/cert.pem | |
| [local] | |
| host = http://localhost:8080 | |
| @content-type = application/json | |
| [staging] | |
| host = https://staging-api.example.com | |
| @content-type = application/json | |
| @authorization = Bearer your-token-here | |
| EOF | |
| # Create basic man page | |
| cat > packaging/usr/share/man/man1/httpc.1 << 'EOF' | |
| .TH HTTPC 1 "$(date +'%B %Y')" "httpc $(grep '^version' Cargo.toml | cut -d'"' -f2)" "User Commands" | |
| .SH NAME | |
| httpc \- A flexible HTTP client with profile support | |
| .SH SYNOPSIS | |
| .B httpc | |
| [\fIOPTIONS\fR] \fIMETHOD\fR \fIURL\fR | |
| .SH DESCRIPTION | |
| \fBhttpc\fP is a flexible HTTP client that supports configuration profiles and various authentication methods. | |
| .SH OPTIONS | |
| .TP | |
| \fB\-p, \-\-profile\fR \fIPROFILE\fR | |
| Use the specified profile from ~/.httpc/profile | |
| .TP | |
| \fB\-H, \-\-header\fR \fIHEADER\fR | |
| Add custom HTTP header | |
| .TP | |
| \fB\-d, \-\-data\fR \fIDATA\fR | |
| Send data in request body | |
| .TP | |
| \fB\-v, \-\-verbose\fR | |
| Enable verbose output | |
| .TP | |
| \fB\-h, \-\-help\fR | |
| Show help message | |
| .TP | |
| \fB\-V, \-\-version\fR | |
| Show version information | |
| .SH CONFIGURATION | |
| Configuration profiles are stored in ~/.httpc/profile in INI format. | |
| See /etc/httpc/profiles.example for configuration examples. | |
| .SH EXAMPLES | |
| .TP | |
| httpc GET https://api.example.com/users | |
| .TP | |
| httpc -p staging POST /api/data -d '{"key": "value"}' | |
| .TP | |
| httpc -H "Authorization: Bearer token" GET /protected | |
| .SH AUTHOR | |
| Written by Satoshi Iizuka. | |
| .SH REPORTING BUGS | |
| Report bugs to: https://github.com/samwisely75/httpc/issues | |
| EOF | |
| # Compress man page | |
| gzip packaging/usr/share/man/man1/httpc.1 | |
| # Create copyright file | |
| cp LICENSE packaging/usr/share/doc/httpc/copyright | |
| # Create changelog | |
| echo "httpc ($(grep '^version' Cargo.toml | cut -d'"' -f2)) stable; urgency=medium" > packaging/usr/share/doc/httpc/changelog.Debian | |
| echo "" >> packaging/usr/share/doc/httpc/changelog.Debian | |
| echo " * Release version $(grep '^version' Cargo.toml | cut -d'"' -f2)" >> packaging/usr/share/doc/httpc/changelog.Debian | |
| echo "" >> packaging/usr/share/doc/httpc/changelog.Debian | |
| echo " -- Satoshi Iizuka <[email protected]> $(date -R)" >> packaging/usr/share/doc/httpc/changelog.Debian | |
| # Compress changelog | |
| gzip packaging/usr/share/doc/httpc/changelog.Debian | |
| - name: Create DEB package | |
| run: | | |
| VERSION=$(grep '^version' Cargo.toml | cut -d'"' -f2) | |
| # Create DEBIAN control file | |
| cat > packaging/DEBIAN/control << EOF | |
| Package: httpc | |
| Version: ${VERSION} | |
| Section: utils | |
| Priority: optional | |
| Architecture: amd64 | |
| Depends: libc6 (>= 2.17) | |
| Maintainer: Satoshi Iizuka <[email protected]> | |
| Description: A flexible HTTP client with profile support | |
| httpc is a flexible HTTP client that supports configuration profiles, | |
| various authentication methods, and custom headers. It's designed for | |
| developers who need a powerful command-line HTTP client for testing | |
| APIs and web services. | |
| Homepage: https://github.com/samwisely75/httpc | |
| EOF | |
| # Create postinst script | |
| cat > packaging/DEBIAN/postinst << 'EOF' | |
| #!/bin/bash | |
| set -e | |
| # Create httpc config directory if it doesn't exist | |
| if [ ! -d "/etc/httpc" ]; then | |
| mkdir -p /etc/httpc | |
| fi | |
| # Check if user has a profile configuration | |
| if [ ! -f "$HOME/.httpc/profile" ]; then | |
| echo "================================================================" | |
| echo "httpc has been installed successfully!" | |
| echo "" | |
| echo "To get started, you need to create a profile configuration:" | |
| echo "1. Create the config directory: mkdir -p $HOME/.httpc" | |
| echo "2. Copy the example: cp /etc/httpc/profiles.example $HOME/.httpc/profile" | |
| echo "3. Edit the profile to configure your API endpoints" | |
| echo "" | |
| echo "For more information, see the README.md at:" | |
| echo "https://github.com/samwisely75/httpc" | |
| echo "================================================================" | |
| fi | |
| exit 0 | |
| EOF | |
| chmod +x packaging/DEBIAN/postinst | |
| # Build DEB package | |
| fakeroot dpkg-deb --build packaging httpc_${VERSION}_amd64.deb | |
| # Verify package | |
| dpkg-deb --info httpc_${VERSION}_amd64.deb | |
| dpkg-deb --contents httpc_${VERSION}_amd64.deb | |
| - name: Create RPM package | |
| run: | | |
| VERSION=$(grep '^version' Cargo.toml | cut -d'"' -f2) | |
| # Convert DEB to RPM using alien (more reliable on Ubuntu than rpm-build) | |
| echo "Converting DEB package to RPM using alien..." | |
| # alien requires the DEB file to exist | |
| if [ ! -f "httpc_${VERSION}_amd64.deb" ]; then | |
| echo "Error: DEB package not found" | |
| exit 1 | |
| fi | |
| # Convert DEB to RPM | |
| sudo alien --to-rpm --scripts httpc_${VERSION}_amd64.deb | |
| # Verify package was created | |
| ls -la *.rpm | |
| # Verify package (these may fail but that's ok) | |
| rpm -qip httpc-${VERSION}-*.rpm || echo "RPM info check failed, but package might still work" | |
| rpm -qlp httpc-${VERSION}-*.rpm || echo "RPM contents check failed, but package might still work" | |
| - name: Upload RPM package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: httpc-rpm-package | |
| path: "*.rpm" | |
| if-no-files-found: error | |
| - name: Upload DEB package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: httpc-deb-package | |
| path: "*.deb" | |
| if-no-files-found: error | |
| test-binaries: | |
| needs: build | |
| strategy: | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| binary: httpc-linux-x64 | |
| - os: macos-latest | |
| binary: httpc-macos-x64 | |
| - os: windows-latest | |
| binary: httpc-windows-x64 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Download binary | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ matrix.binary }} | |
| - name: Test binary (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| chmod +x ${{ matrix.binary }} | |
| ./${{ matrix.binary }} --version | |
| ./${{ matrix.binary }} --help | |
| - name: Test binary (Windows) | |
| if: matrix.os == 'windows-latest' | |
| shell: cmd | |
| run: | | |
| .\%BINARY%.exe --version | |
| .\%BINARY%.exe --help | |
| env: | |
| BINARY: ${{ matrix.binary }} | |
| create-release: | |
| needs: [build, build-packages, test-binaries] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Extract version from branch name | |
| id: extract_version | |
| run: | | |
| if [[ "${{ github.ref_name }}" =~ ^release/(.+)$ ]]; then | |
| VERSION=${BASH_REMATCH[1]} | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "tag_name=v${VERSION}" >> $GITHUB_OUTPUT | |
| echo "Extracted version: ${VERSION}" | |
| else | |
| echo "Error: Could not extract version from branch name: ${{ github.ref_name }}" | |
| exit 1 | |
| fi | |
| - name: Create and push release tag | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| TAG_NAME="${{ steps.extract_version.outputs.tag_name }}" | |
| VERSION="${{ steps.extract_version.outputs.version }}" | |
| RELEASE_BRANCH="release/$VERSION" | |
| echo "Processing tag: $TAG_NAME" | |
| echo "Processing release branch: $RELEASE_BRANCH" | |
| # Check if tag exists locally and delete it | |
| if git tag -l | grep -q "^${TAG_NAME}$"; then | |
| echo "Local tag $TAG_NAME exists, deleting it..." | |
| git tag -d "$TAG_NAME" | |
| fi | |
| # Check if tag exists on remote and delete it | |
| if git ls-remote --tags origin | grep -q "refs/tags/${TAG_NAME}$"; then | |
| echo "Remote tag $TAG_NAME exists, deleting it..." | |
| git push origin ":refs/tags/$TAG_NAME" | |
| fi | |
| # Create and push the tag | |
| git tag "$TAG_NAME" | |
| git push origin "$TAG_NAME" | |
| echo "Created and pushed tag: $TAG_NAME" | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Prepare release assets | |
| run: | | |
| mkdir -p release-assets | |
| find artifacts -name "httpc-*" -exec cp {} release-assets/ \; | |
| find artifacts -name "*.deb" -exec cp {} release-assets/ \; | |
| find artifacts -name "*.rpm" -exec cp {} release-assets/ \; | |
| ls -la release-assets/ | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ steps.extract_version.outputs.tag_name }} | |
| name: Release ${{ steps.extract_version.outputs.tag_name }} | |
| draft: false | |
| prerelease: false | |
| files: release-assets/* | |
| body: | | |
| ## What's Changed | |
| * Cross-platform release for Windows, macOS, and Linux | |
| * Linux packages available in DEB and RPM formats | |
| * Configuration profiles support for API endpoints | |
| * Flexible HTTP client with authentication support | |
| ## Installation | |
| ### Using Pre-built Binaries | |
| Download the appropriate binary for your platform from the assets below: | |
| ### Windows | |
| - `httpc-windows-x64.exe` - Windows 64-bit (Intel/AMD) | |
| ### macOS | |
| - `httpc-macos-x64` - macOS Intel (x64) | |
| - `httpc-macos-arm64` - macOS Apple Silicon (M1/M2) | |
| ### Linux | |
| - `httpc-linux-x64` - Linux 64-bit (Intel/AMD) | |
| - `httpc-linux-arm64` - Linux ARM64 | |
| - `httpc_*_amd64.deb` - Debian/Ubuntu package | |
| - `httpc-*.rpm` - Red Hat/Fedora/CentOS package | |
| ### Using Package Managers (Linux) | |
| **Debian/Ubuntu (.deb):** | |
| ```bash | |
| # Download the .deb file from assets below, then: | |
| sudo dpkg -i httpc_*_amd64.deb | |
| ``` | |
| **Red Hat/Fedora/CentOS (.rpm):** | |
| ```bash | |
| # Download the .rpm file from assets below, then: | |
| sudo rpm -i httpc-*.rpm | |
| # Or with DNF/YUM: | |
| sudo dnf install httpc-*.rpm | |
| sudo yum install httpc-*.rpm | |
| ``` | |
| ## Configuration | |
| httpc uses configuration profiles stored in `~/.httpc/profile`. The package installation will create an example file at: | |
| - Linux: `/etc/httpc/profiles.example` | |
| - Copy this to `~/.httpc/profile` and customize as needed | |
| Example profile configuration: | |
| ```ini | |
| [default] | |
| host = https://api.example.com | |
| @content-type = application/json | |
| @accept = application/json | |
| [local] | |
| host = http://localhost:8080 | |
| @content-type = application/json | |
| ``` | |
| ## Usage | |
| ```bash | |
| # Basic usage | |
| httpc GET https://api.example.com/users | |
| # Using a profile | |
| httpc -p local GET /api/data | |
| # With custom headers | |
| httpc -H "Authorization: Bearer token" GET /protected | |
| # POST with data | |
| httpc POST /api/data -d '{"key": "value"}' | |
| ``` | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| publish-homebrew: | |
| name: Publish to Homebrew | |
| runs-on: macos-latest | |
| needs: create-release | |
| steps: | |
| - name: Extract version from ref | |
| id: extract_version | |
| run: | | |
| if [[ "${{ github.ref_name }}" =~ ^release/(.+)$ ]]; then | |
| VERSION=${BASH_REMATCH[1]} | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| else | |
| echo "Error: Could not extract version from branch name: ${{ github.ref_name }}" | |
| exit 1 | |
| fi | |
| - name: Checkout homebrew tap | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: samwisely75/homebrew-tap | |
| token: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| path: homebrew-tap | |
| - name: Update formula | |
| working-directory: homebrew-tap | |
| run: | | |
| VERSION=${{ steps.extract_version.outputs.version }} | |
| TAG="v${VERSION}" | |
| # Calculate SHA256 from the release tarball | |
| SHA256=$(curl -L https://github.com/samwisely75/httpc/archive/refs/tags/${TAG}.tar.gz | sha256sum | cut -d ' ' -f 1) | |
| # Create or update the formula | |
| cat > Formula/httpc.rb << EOF | |
| class Httpc < Formula | |
| desc "A flexible HTTP client with profile support" | |
| homepage "https://github.com/samwisely75/httpc" | |
| version "${VERSION}" | |
| license "MIT" | |
| on_macos do | |
| on_arm do | |
| url "https://github.com/samwisely75/httpc/releases/download/${TAG}/httpc-macos-arm64" | |
| sha256 "$(curl -L https://github.com/samwisely75/httpc/releases/download/${TAG}/httpc-macos-arm64 | sha256sum | cut -d ' ' -f 1)" | |
| end | |
| on_intel do | |
| url "https://github.com/samwisely75/httpc/releases/download/${TAG}/httpc-macos-x64" | |
| sha256 "$(curl -L https://github.com/samwisely75/httpc/releases/download/${TAG}/httpc-macos-x64 | sha256sum | cut -d ' ' -f 1)" | |
| end | |
| end | |
| def install | |
| bin.install Dir["*"].first => "httpc" | |
| end | |
| test do | |
| assert_match "httpc #{version}", shell_output("#{bin}/httpc --version") | |
| end | |
| end | |
| EOF | |
| # Commit and push the changes | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add Formula/httpc.rb | |
| git commit -m "httpc ${VERSION}" | |
| git push | |
| publish-crates-io: | |
| name: Publish to Crates.io | |
| runs-on: ubuntu-latest | |
| needs: create-release | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/registry | |
| key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Cache cargo index | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/git | |
| key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Publish to crates.io | |
| run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }} | |
| merge-to-main: | |
| name: Merge Release to Main | |
| runs-on: ubuntu-latest | |
| needs: [create-release, build, build-packages, test-binaries] | |
| if: startsWith(github.ref, 'refs/heads/release/') | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Need full history for merge | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Merge release to main | |
| run: | | |
| # Determine the source branch | |
| SOURCE_BRANCH=${GITHUB_REF#refs/heads/} | |
| echo "Branch triggered: merging from $SOURCE_BRANCH" | |
| # Switch to main and merge | |
| git checkout main | |
| git pull origin main | |
| # Check if the release branch/tag is already merged | |
| if git merge-base --is-ancestor ${{ github.sha }} HEAD; then | |
| echo "Changes already merged into main" | |
| else | |
| echo "Merging $SOURCE_BRANCH to main..." | |
| git merge --no-ff ${{ github.sha }} -m "Merge release ${{ github.ref_name }} to main - All release artifacts and tests passed" | |
| # Push to main | |
| git push origin main | |
| echo "✅ Successfully merged release to main" | |
| fi | |
| - name: Update develop branch | |
| run: | | |
| # Also merge any release changes back to develop to keep it up to date | |
| git checkout develop | |
| git pull origin develop | |
| # Check if already merged | |
| if git merge-base --is-ancestor ${{ github.sha }} HEAD; then | |
| echo "Changes already in develop" | |
| else | |
| echo "Merging release changes back to develop..." | |
| git merge --no-ff ${{ github.sha }} -m "Merge release ${{ github.ref_name }} back to develop" | |
| git push origin develop | |
| echo "✅ Successfully updated develop branch" | |
| fi | |
| - name: Clean up release branch | |
| if: startsWith(github.ref, 'refs/heads/release/') | |
| run: | | |
| # Delete the release branch after successful merge | |
| RELEASE_BRANCH=${GITHUB_REF#refs/heads/} | |
| echo "Deleting release branch: $RELEASE_BRANCH" | |
| # Try to delete the remote branch | |
| if git ls-remote --heads origin | grep -q "refs/heads/$RELEASE_BRANCH"; then | |
| echo "Attempting to delete remote branch: refs/heads/$RELEASE_BRANCH" | |
| git push origin --delete "$RELEASE_BRANCH" || { | |
| echo "Standard delete failed, trying alternative syntax..." | |
| git push origin ":refs/heads/$RELEASE_BRANCH" || { | |
| echo "⚠️ Could not delete remote branch, may already be deleted" | |
| } | |
| } | |
| else | |
| echo "Remote branch $RELEASE_BRANCH not found, may already be deleted" | |
| fi | |
| echo "✅ Cleaned up release branch" |