From 8e4c9584b56ea8fc9b89a86ad12e3ff96895449f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:47:59 +0000 Subject: [PATCH 1/5] Initial plan From ef2c3a7b3e626368a60f769081bf213dac96ddbd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:57:25 +0000 Subject: [PATCH 2/5] Add GitHub Actions workflows for CI and releases Co-authored-by: halcycon <8266551+halcycon@users.noreply.github.com> --- .github/workflows/ci.yml | 118 ++++++++++++++ .github/workflows/release.yml | 296 ++++++++++++++++++++++++++++++++++ 2 files changed, 414 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b786904 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,118 @@ +name: CI + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + rust: [stable] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + + - 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Run tests + run: cargo test --workspace --verbose + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Run clippy + run: cargo clippy --workspace --all-targets --all-features -- -D warnings + + build: + name: Build + runs-on: ubuntu-latest + 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Build workspace + run: cargo build --workspace --verbose + + - name: Build release + run: cargo build --workspace --release --verbose diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..22f19c1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,296 @@ +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + +permissions: + contents: write + +jobs: + test: + name: Run tests + runs-on: ubuntu-latest + 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Run tests + run: cargo test --workspace --verbose + + build-linux: + name: Build for Linux (x86_64) + runs-on: ubuntu-latest + needs: test + 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-release-${{ hashFiles('**/Cargo.lock') }} + + - name: Build release binary + run: cargo build --release --verbose + + - name: Create release archive + run: | + mkdir -p release/rustalk-linux-x86_64 + cp target/release/rustalk release/rustalk-linux-x86_64/ + cp config.json release/rustalk-linux-x86_64/config.example.json + cp README.md LICENSE release/rustalk-linux-x86_64/ + cd release + tar czf rustalk-linux-x86_64.tar.gz rustalk-linux-x86_64 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustalk-linux-x86_64 + path: release/rustalk-linux-x86_64.tar.gz + + build-macos: + name: Build for macOS (x86_64) + runs-on: macos-latest + needs: test + 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-release-${{ hashFiles('**/Cargo.lock') }} + + - name: Build release binary + run: cargo build --release --verbose + + - name: Create release archive + run: | + mkdir -p release/rustalk-macos-x86_64 + cp target/release/rustalk release/rustalk-macos-x86_64/ + cp config.json release/rustalk-macos-x86_64/config.example.json + cp README.md LICENSE release/rustalk-macos-x86_64/ + cd release + tar czf rustalk-macos-x86_64.tar.gz rustalk-macos-x86_64 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustalk-macos-x86_64 + path: release/rustalk-macos-x86_64.tar.gz + + build-macos-arm: + name: Build for macOS (ARM64) + runs-on: macos-latest + needs: test + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-apple-darwin + + - 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-aarch64-cargo-build-target-release-${{ hashFiles('**/Cargo.lock') }} + + - name: Build release binary + run: cargo build --release --target aarch64-apple-darwin --verbose + + - name: Create release archive + run: | + mkdir -p release/rustalk-macos-arm64 + cp target/aarch64-apple-darwin/release/rustalk release/rustalk-macos-arm64/ + cp config.json release/rustalk-macos-arm64/config.example.json + cp README.md LICENSE release/rustalk-macos-arm64/ + cd release + tar czf rustalk-macos-arm64.tar.gz rustalk-macos-arm64 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustalk-macos-arm64 + path: release/rustalk-macos-arm64.tar.gz + + build-windows: + name: Build for Windows (x86_64) + runs-on: windows-latest + needs: test + 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: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-release-${{ hashFiles('**/Cargo.lock') }} + + - name: Build release binary + run: cargo build --release --verbose + + - name: Create release archive + shell: pwsh + run: | + New-Item -ItemType Directory -Force -Path release\rustalk-windows-x86_64 + Copy-Item target\release\rustalk.exe release\rustalk-windows-x86_64\ + Copy-Item config.json release\rustalk-windows-x86_64\config.example.json + Copy-Item README.md, LICENSE release\rustalk-windows-x86_64\ + Compress-Archive -Path release\rustalk-windows-x86_64 -DestinationPath release\rustalk-windows-x86_64.zip + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustalk-windows-x86_64 + path: release/rustalk-windows-x86_64.zip + + create-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: [build-linux, build-macos, build-macos-arm, build-windows] + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Create release + uses: softprops/action-gh-release@v2 + with: + draft: false + prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') || contains(github.ref, '-alpha') }} + files: | + artifacts/rustalk-linux-x86_64/rustalk-linux-x86_64.tar.gz + artifacts/rustalk-macos-x86_64/rustalk-macos-x86_64.tar.gz + artifacts/rustalk-macos-arm64/rustalk-macos-arm64.tar.gz + artifacts/rustalk-windows-x86_64/rustalk-windows-x86_64.zip + body: | + ## RusTalk Release ${{ github.ref_name }} + + High-performance SIP B2BUA / PBX / MS-Teams-compatible SBC built in Rust. + + ### Installation + + #### Linux / macOS + ```bash + tar xzf rustalk-*.tar.gz + cd rustalk-* + ./rustalk --help + ``` + + #### Windows + ```powershell + Expand-Archive rustalk-windows-x86_64.zip + cd rustalk-windows-x86_64 + .\rustalk.exe --help + ``` + + ### Quick Start + + 1. Copy `config.example.json` to `config.json` + 2. Edit the configuration to match your environment + 3. Run: `./rustalk start --config config.json` + + ### Documentation + + See [README.md](https://github.com/halcycon/RusTalk/blob/main/README.md) for full documentation. + + ### Checksums + + SHA256 checksums for release files: + ``` + $(cd artifacts && find . -name "*.tar.gz" -o -name "*.zip" | xargs sha256sum) + ``` + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d8419c9ba5bba0c2aa5bcad5bf1dc2a3178e926b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:00:04 +0000 Subject: [PATCH 3/5] Add release documentation and update README Co-authored-by: halcycon <8266551+halcycon@users.noreply.github.com> --- README.md | 31 +++++++ RELEASE.md | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 RELEASE.md diff --git a/README.md b/README.md index ea76c87..31bb946 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,22 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation. ### Installation +#### Option 1: Download Pre-built Binaries (Recommended) + +Download the latest release for your platform from the [Releases page](https://github.com/halcycon/RusTalk/releases): + +```bash +# Linux / macOS +tar xzf rustalk-*.tar.gz +cd rustalk-* +./rustalk --help + +# Windows +# Extract the .zip file and run rustalk.exe +``` + +#### Option 2: Build from Source + ```bash # Clone the repository git clone https://github.com/halcycon/RusTalk.git @@ -366,6 +382,21 @@ RusTalk supports PostgreSQL for configuration overlay and persistence: Configuration values in the database override those in config.json, allowing centralized management. +## Releases + +RusTalk uses automated GitHub Actions workflows for building and releasing binaries for multiple platforms. Pre-built binaries are available on the [Releases page](https://github.com/halcycon/RusTalk/releases). + +### Supported Platforms + +- Linux x86_64 (`.tar.gz`) +- macOS x86_64 (`.tar.gz`) +- macOS ARM64 / Apple Silicon (`.tar.gz`) +- Windows x86_64 (`.zip`) + +### Creating a Release + +See [RELEASE.md](RELEASE.md) for detailed instructions on creating and publishing releases. + ## Contributing Contributions are welcome! Please feel free to submit issues and pull requests. diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..a275ada --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,243 @@ +# Release Process + +This document describes how to create and publish releases for RusTalk. + +## Overview + +RusTalk uses GitHub Actions for automated building and releasing. The release workflow builds binaries for multiple platforms and creates GitHub releases with downloadable archives. + +## Supported Platforms + +- **Linux x86_64** (`.tar.gz`) +- **macOS x86_64** (`.tar.gz`) +- **macOS ARM64** (Apple Silicon) (`.tar.gz`) +- **Windows x86_64** (`.zip`) + +## Release Types + +The workflow automatically determines the release type based on the tag: + +- **Stable Release**: Tags like `v1.0.0`, `v1.2.3` +- **Pre-release**: Tags containing `-rc`, `-beta`, or `-alpha` (e.g., `v1.0.0-rc1`, `v1.0.0-beta2`) + +## Creating a Release + +### 1. Prepare the Release + +Before creating a release, ensure: + +- All tests pass: `cargo test --workspace` +- Code is properly formatted: `cargo fmt --all` +- Clippy checks are addressed: `cargo clippy --workspace` +- Documentation is up to date +- CHANGELOG is updated (if you maintain one) + +### 2. Update Version Numbers + +Update the version in `Cargo.toml`: + +```toml +[workspace.package] +version = "0.2.0" # Update to your new version +``` + +Then update the lock file: + +```bash +cargo update -p rustalk-core -p rustalk-edge -p rustalk-cloud -p rustalk-cli +``` + +### 3. Commit Version Update + +```bash +git add Cargo.toml Cargo.lock +git commit -m "Bump version to 0.2.0" +git push origin main +``` + +### 4. Create and Push the Tag + +```bash +# Create an annotated tag +git tag -a v0.2.0 -m "Release version 0.2.0" + +# Push the tag to GitHub +git push origin v0.2.0 +``` + +### 5. Monitor the Build + +1. Go to the [Actions tab](https://github.com/halcycon/RusTalk/actions) on GitHub +2. Watch the "Release" workflow run +3. The workflow will: + - Run tests on all platforms + - Build release binaries for each platform + - Create release archives + - Publish a GitHub release with all artifacts + +The entire process typically takes 15-30 minutes. + +### 6. Verify the Release + +1. Go to the [Releases page](https://github.com/halcycon/RusTalk/releases) +2. Check that the new release appears with all platform archives +3. Download and test one or more archives to verify they work + +## Manual Release (if needed) + +If you need to create a release manually or test the process locally: + +### Build for Your Platform + +```bash +# Build release binary +cargo build --release + +# Create release directory +mkdir -p release/rustalk-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) +cd release/rustalk-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) + +# Copy files +cp ../../target/release/rustalk . +cp ../../config.json config.example.json +cp ../../README.md ../../LICENSE . + +# Create archive +cd .. +tar czf rustalk-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m).tar.gz \ + rustalk-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) +``` + +### Cross-Compilation (Advanced) + +For cross-compiling to other platforms, use `cross`: + +```bash +# Install cross +cargo install cross + +# Build for Linux from macOS +cross build --release --target x86_64-unknown-linux-gnu + +# Build for Windows from Linux/macOS +cross build --release --target x86_64-pc-windows-gnu +``` + +## Release Checklist + +Before creating a release, verify: + +- [ ] All tests pass on main branch +- [ ] Version numbers updated in Cargo.toml +- [ ] Cargo.lock updated with `cargo update` +- [ ] Documentation is current +- [ ] Breaking changes are documented +- [ ] Security advisories are addressed +- [ ] Tag follows semantic versioning (MAJOR.MINOR.PATCH) + +After release: + +- [ ] Verify release appears on GitHub +- [ ] All platform archives are present +- [ ] Download and test at least one archive +- [ ] Release notes are accurate +- [ ] Announce the release (if applicable) + +## Semantic Versioning + +RusTalk follows [Semantic Versioning](https://semver.org/): + +- **MAJOR** version for incompatible API changes +- **MINOR** version for new functionality (backwards-compatible) +- **PATCH** version for backwards-compatible bug fixes + +Examples: +- `v0.1.0` → `v0.2.0`: New features added +- `v0.2.0` → `v0.2.1`: Bug fixes +- `v0.2.1` → `v1.0.0`: First stable release +- `v1.0.0` → `v2.0.0`: Breaking changes + +## Pre-releases + +For testing before a stable release: + +```bash +# Release candidate +git tag -a v1.0.0-rc1 -m "Release candidate 1 for version 1.0.0" +git push origin v1.0.0-rc1 + +# Beta release +git tag -a v1.0.0-beta1 -m "Beta 1 for version 1.0.0" +git push origin v1.0.0-beta1 + +# Alpha release +git tag -a v1.0.0-alpha1 -m "Alpha 1 for version 1.0.0" +git push origin v1.0.0-alpha1 +``` + +These will be marked as pre-releases on GitHub. + +## Troubleshooting + +### Build Fails + +If the release build fails: + +1. Check the [Actions log](https://github.com/halcycon/RusTalk/actions) for errors +2. Verify tests pass locally: `cargo test --workspace` +3. Verify it builds locally: `cargo build --release` +4. Check for platform-specific issues + +### Release Not Created + +If the GitHub release isn't created automatically: + +1. Verify the tag was pushed: `git ls-remote --tags origin` +2. Check the workflow ran: Look for the tag in the Actions tab +3. Verify the tag matches the pattern `v*` +4. Check workflow permissions in repository settings + +### Missing Artifacts + +If some platform archives are missing: + +1. Check which build job failed in the Actions log +2. Re-run failed jobs from the Actions interface +3. If necessary, delete the release and tag, then recreate + +## CI/CD Workflows + +### CI Workflow + +Runs on every push and pull request: +- Tests on Linux, macOS, and Windows +- Linting (rustfmt, clippy) +- Debug and release builds + +### Release Workflow + +Triggers on tags matching `v*`: +- Runs tests first +- Builds for all platforms in parallel +- Creates release packages +- Publishes GitHub release + +## Distribution Channels + +Currently, RusTalk is distributed via: + +- **GitHub Releases**: Binary downloads for all platforms +- **Source**: Clone and build from the repository + +Future distribution channels may include: + +- **Cargo**: `cargo install rustalk` +- **Homebrew**: `brew install rustalk` +- **apt/yum**: Linux package repositories +- **Docker**: Container images + +## Support + +For questions about releases: +- Open an issue on [GitHub](https://github.com/halcycon/RusTalk/issues) +- Check existing [releases](https://github.com/halcycon/RusTalk/releases) From bffc31f941cb76fb403cb7124598cc5c63fe180b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:02:25 +0000 Subject: [PATCH 4/5] Add version bump script and update gitignore for releases Co-authored-by: halcycon <8266551+halcycon@users.noreply.github.com> --- .gitignore | 5 +++++ scripts/bump-version.sh | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100755 scripts/bump-version.sh diff --git a/.gitignore b/.gitignore index 135c910..2705ced 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,8 @@ target rustalk-webui/dist rustalk-webui/node_modules rustalk-webui/.vite + +# Release artifacts +release/ +*.tar.gz +*.zip diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh new file mode 100755 index 0000000..5524489 --- /dev/null +++ b/scripts/bump-version.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Script to bump version numbers for RusTalk release + +set -e + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 0.2.0" + exit 1 +fi + +NEW_VERSION=$1 + +# Validate version format (basic semver check) +if ! [[ $NEW_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then + echo "Error: Invalid version format. Use format: MAJOR.MINOR.PATCH (e.g., 1.2.3 or 1.2.3-rc1)" + exit 1 +fi + +echo "Bumping version to $NEW_VERSION..." + +# Update workspace Cargo.toml +sed -i.bak "s/^version = \".*\"/version = \"$NEW_VERSION\"/" Cargo.toml + +# Update Cargo.lock +cargo update -p rustalk-core -p rustalk-edge -p rustalk-cloud -p rustalk-cli + +# Remove backup file +rm -f Cargo.toml.bak + +echo "✓ Version updated to $NEW_VERSION in Cargo.toml" +echo "✓ Cargo.lock updated" +echo "" +echo "Next steps:" +echo " 1. Review the changes: git diff" +echo " 2. Commit: git add Cargo.toml Cargo.lock && git commit -m 'Bump version to $NEW_VERSION'" +echo " 3. Tag: git tag -a v$NEW_VERSION -m 'Release version $NEW_VERSION'" +echo " 4. Push: git push origin main && git push origin v$NEW_VERSION" From 39b2a9c04e8e7223c95c705341e2cc310d623582 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:05:05 +0000 Subject: [PATCH 5/5] Fix security: Add explicit permissions to CI workflow jobs Co-authored-by: halcycon <8266551+halcycon@users.noreply.github.com> --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b786904..e5033a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,8 @@ jobs: test: name: Test runs-on: ${{ matrix.os }} + permissions: + contents: read strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] @@ -50,6 +52,8 @@ jobs: lint: name: Lint runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout code uses: actions/checkout@v4 @@ -86,6 +90,8 @@ jobs: build: name: Build runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout code uses: actions/checkout@v4