From b6adf5176767fc37206b2212b1efd1e759fdbe6b Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Fri, 9 Jan 2026 12:54:31 +0100 Subject: [PATCH] feat: Add comprehensive CI/CD pipeline with GitHub Actions - Add CI workflow with multi-version Go testing, linting, security scans - Add automated release workflow triggered on tag push - Include Dependabot for dependency management - Add professional issue templates for bugs and features - Configure golangci-lint with production-ready settings - Update local release script to complement automation - Support cross-platform builds for 7 platforms - Automated release notes and checksum generation --- .github/ISSUE_TEMPLATE/bug_report.yml | 201 +++++++++++ .github/ISSUE_TEMPLATE/feature_request.yml | 205 +++++++++++ .github/dependabot.yml | 135 +++++++ .github/markdown-link-check.json | 45 +++ .github/workflows/ci.yml | 260 ++++++++++++++ .github/workflows/release.yml | 400 +++++++++++++++++++++ .golangci.yml | 230 ++++++++++++ scripts/post-release.md | 210 +++++++++++ scripts/prepare-release.sh | 75 +++- 9 files changed, 1748 insertions(+), 13 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/markdown-link-check.json create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 .golangci.yml create mode 100644 scripts/post-release.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..772743e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,201 @@ +name: Bug Report +description: File a bug report to help us improve the library +title: "[Bug]: " +labels: ["bug", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! Please provide as much detail as possible to help us diagnose and fix the issue. + + - type: input + id: version + attributes: + label: Library Version + description: What version of the library are you using? + placeholder: "v1.0.0" + validations: + required: true + + - type: dropdown + id: go-version + attributes: + label: Go Version + description: What version of Go are you using? + options: + - "1.23" + - "1.22" + - "1.21" + - "1.20" + - "Other (please specify in description)" + validations: + required: true + + - type: dropdown + id: operating-system + attributes: + label: Operating System + description: What operating system are you running on? + options: + - "Linux" + - "macOS" + - "Windows" + - "FreeBSD" + - "Other (please specify in description)" + validations: + required: true + + - type: input + id: device-model + attributes: + label: Bose Device Model + description: What Bose SoundTouch device are you trying to control? + placeholder: "SoundTouch 10, SoundTouch 20, etc." + validations: + required: true + + - type: input + id: device-firmware + attributes: + label: Device Firmware Version + description: What firmware version is your device running? (Check in Bose app or via /info endpoint) + placeholder: "4.8.1.4567.891234567" + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is. + placeholder: "Describe what happened and what you expected to happen..." + validations: + required: true + + - type: textarea + id: reproduction-steps + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior + placeholder: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected Behavior + description: A clear and concise description of what you expected to happen. + placeholder: "What should have happened instead?" + validations: + required: true + + - type: textarea + id: code-sample + attributes: + label: Code Sample + description: Please provide a minimal code sample that reproduces the issue + render: go + placeholder: | + package main + + import ( + "fmt" + "github.com/user_account/bose-soundtouch/pkg/client" + ) + + func main() { + // Your code that demonstrates the issue + } + validations: + required: false + + - type: textarea + id: logs + attributes: + label: Error Messages / Logs + description: Please include any relevant error messages, stack traces, or log output + render: shell + placeholder: | + Error: connection refused + at github.com/user_account/bose-soundtouch/pkg/client.(*Client).makeRequest + ... + validations: + required: false + + - type: dropdown + id: component + attributes: + label: Component + description: Which component is affected? + multiple: true + options: + - "Client Library (pkg/client)" + - "WebSocket Events" + - "Device Discovery" + - "CLI Tool" + - "Models/XML Parsing" + - "Documentation" + - "Examples" + - "Build/Release" + validations: + required: false + + - type: dropdown + id: severity + attributes: + label: Severity + description: How severe is this bug? + options: + - "Low - Minor inconvenience" + - "Medium - Affects functionality but workaround exists" + - "High - Blocks major functionality" + - "Critical - Application crashes or data loss" + validations: + required: true + + - type: textarea + id: network-info + attributes: + label: Network Configuration + description: Details about your network setup (if relevant to the issue) + placeholder: | + - Device IP: 192.168.1.100 + - Network type: WiFi/Ethernet + - Router model: + - Any firewalls or network restrictions: + validations: + required: false + + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Add any other context about the problem here + placeholder: "Screenshots, network traces, related issues, etc." + validations: + required: false + + - type: checkboxes + id: troubleshooting + attributes: + label: Troubleshooting Steps + description: Have you tried these troubleshooting steps? + options: + - label: "I have checked the [Troubleshooting Guide](docs/TROUBLESHOOTING.md)" + - label: "I have verified my device is reachable (ping test)" + - label: "I have tested with the CLI tool" + - label: "I have checked for similar existing issues" + - label: "I am using the latest version of the library" + + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our Code of Conduct + options: + - label: "I agree to follow this project's Code of Conduct" + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..caab493 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,205 @@ +name: Feature Request +description: Suggest an idea or enhancement for this project +title: "[Feature]: " +labels: ["enhancement", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a new feature! Please provide as much detail as possible to help us understand your request and its potential impact. + + - type: input + id: version + attributes: + label: Library Version + description: What version of the library are you currently using? + placeholder: "v1.0.0" + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Problem Description + description: Is your feature request related to a problem? Please describe what you're trying to accomplish. + placeholder: "I'm always frustrated when... / I need to be able to... / Currently it's not possible to..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: Describe the solution you'd like to see implemented. + placeholder: "I would like to see... / A new function that... / An option to..." + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Describe any alternative solutions or features you've considered. + placeholder: "I considered... / Another approach could be... / Workaround I'm currently using..." + validations: + required: false + + - type: dropdown + id: component + attributes: + label: Component + description: Which component would this feature affect? + multiple: true + options: + - "Client Library (pkg/client)" + - "WebSocket Events" + - "Device Discovery" + - "CLI Tool" + - "Models/XML Parsing" + - "Documentation" + - "Examples" + - "New API Endpoint" + - "Performance Optimization" + - "Developer Experience" + validations: + required: true + + - type: dropdown + id: device-compatibility + attributes: + label: Device Compatibility + description: Which Bose SoundTouch devices should this feature support? + multiple: true + options: + - "All SoundTouch devices" + - "SoundTouch 10" + - "SoundTouch 20" + - "SoundTouch 30" + - "SoundTouch Portable" + - "SoundTouch Wave" + - "Other (specify in description)" + validations: + required: false + + - type: dropdown + id: priority + attributes: + label: Priority + description: How important is this feature to you? + options: + - "Low - Nice to have" + - "Medium - Would improve my workflow" + - "High - Important for my use case" + - "Critical - Blocking my project" + validations: + required: true + + - type: dropdown + id: api-type + attributes: + label: API Type (if applicable) + description: What type of API enhancement is this? + options: + - "Not applicable" + - "New Bose SoundTouch endpoint" + - "Enhancement to existing endpoint" + - "Client library improvement" + - "WebSocket event enhancement" + - "Discovery enhancement" + - "CLI command addition" + validations: + required: false + + - type: textarea + id: use-case + attributes: + label: Use Case / User Story + description: Describe your specific use case or user story + placeholder: | + As a [type of user], I want to [goal] so that [benefit]. + + Example: As a home automation developer, I want to create custom zones so that I can group speakers dynamically based on user preferences. + validations: + required: true + + - type: textarea + id: example-api + attributes: + label: Desired API Example + description: Show how you'd like the API to work (if applicable) + render: go + placeholder: | + // Example of how you envision using this feature + client := soundtouch.New("192.168.1.100", 8090) + + // Your desired API call + result, err := client.NewFeature(options) + if err != nil { + // handle error + } + + // Use the result + fmt.Println(result) + validations: + required: false + + - type: textarea + id: technical-details + attributes: + label: Technical Details + description: Any technical considerations, constraints, or implementation ideas? + placeholder: | + - Should this be backward compatible? + - Any performance considerations? + - Integration with existing features? + - External dependencies needed? + validations: + required: false + + - type: checkboxes + id: implementation + attributes: + label: Implementation + description: Are you willing to help implement this feature? + options: + - label: "I can help implement this feature" + - label: "I can provide testing/feedback" + - label: "I can help with documentation" + - label: "I need someone else to implement this" + + - type: textarea + id: research + attributes: + label: Research & References + description: Have you found any relevant resources, similar implementations, or Bose documentation? + placeholder: | + - Links to relevant documentation + - Similar features in other libraries + - Bose SoundTouch API references + - Related GitHub issues or discussions + validations: + required: false + + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: Please confirm the following + options: + - label: "I have searched for existing issues and feature requests" + required: true + - label: "I have checked the [API Cookbook](docs/API-COOKBOOK.md) for existing functionality" + required: true + - label: "This feature is related to Bose SoundTouch functionality" + required: true + - label: "I have considered backward compatibility" + + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this feature request, you agree to follow our Code of Conduct + options: + - label: "I agree to follow this project's Code of Conduct" + required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..dd8791b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,135 @@ +# Dependabot configuration for Bose SoundTouch Go Library +# See: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + # Go modules dependency updates + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + timezone: "UTC" + open-pull-requests-limit: 5 + reviewers: + - "user_account" + assignees: + - "user_account" + commit-message: + prefix: "deps" + prefix-development: "deps-dev" + include: "scope" + labels: + - "dependencies" + - "go" + pull-request-branch-name: + separator: "/" + rebase-strategy: "auto" + allow: + # Allow all dependency types + - dependency-type: "all" + ignore: + # Ignore major version updates for stable dependencies (manual review preferred) + - dependency-name: "github.com/gorilla/websocket" + update-types: ["version-update:semver-major"] + - dependency-name: "github.com/hashicorp/mdns" + update-types: ["version-update:semver-major"] + groups: + # Group Go standard library and toolchain updates + golang: + patterns: + - "golang.org/*" + update-types: + - "patch" + - "minor" + # Group testing dependencies + testing: + patterns: + - "*test*" + - "*mock*" + - "*assert*" + update-types: + - "patch" + - "minor" + + # GitHub Actions workflow dependency updates + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "tuesday" + time: "09:00" + timezone: "UTC" + open-pull-requests-limit: 3 + reviewers: + - "user_account" + assignees: + - "user_account" + commit-message: + prefix: "ci" + include: "scope" + labels: + - "dependencies" + - "github-actions" + - "ci" + pull-request-branch-name: + separator: "/" + rebase-strategy: "auto" + allow: + - dependency-type: "all" + groups: + # Group actions from the same organization + actions-core: + patterns: + - "actions/*" + update-types: + - "patch" + - "minor" + # Group setup actions + setup-actions: + patterns: + - "*setup-*" + update-types: + - "patch" + - "minor" + # Group security-related actions + security-actions: + patterns: + - "*security*" + - "*scan*" + - "securecodewarrior/*" + - "codecov/*" + update-types: + - "patch" + - "minor" + + # Docker dependencies (if we add Dockerfiles in the future) + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + day: "wednesday" + time: "09:00" + timezone: "UTC" + open-pull-requests-limit: 2 + reviewers: + - "user_account" + assignees: + - "user_account" + commit-message: + prefix: "docker" + include: "scope" + labels: + - "dependencies" + - "docker" + pull-request-branch-name: + separator: "/" + rebase-strategy: "auto" + allow: + - dependency-type: "all" + # Only check if Dockerfile exists + ignore: + # Ignore base image major updates (requires manual testing) + - dependency-name: "*" + update-types: ["version-update:semver-major"] diff --git a/.github/markdown-link-check.json b/.github/markdown-link-check.json new file mode 100644 index 0000000..b78d570 --- /dev/null +++ b/.github/markdown-link-check.json @@ -0,0 +1,45 @@ +{ + "timeout": "20s", + "retryOn429": true, + "retryCount": 3, + "fallbackRetryDelay": "30s", + "aliveStatusCodes": [200, 206], + "ignorePatterns": [ + { + "pattern": "^http://localhost" + }, + { + "pattern": "^https://localhost" + }, + { + "pattern": "^http://127.0.0.1" + }, + { + "pattern": "^http://192.168." + }, + { + "pattern": "^http://10." + }, + { + "pattern": "^http://172." + }, + { + "pattern": "^https://pkg.go.dev.*badge" + } + ], + "replacementPatterns": [ + { + "pattern": "^/", + "replacement": "{{BASEURL}}/" + } + ], + "httpHeaders": [ + { + "urls": ["https://github.com", "https://api.github.com"], + "headers": { + "Accept-Encoding": "zstd, br, gzip, deflate", + "User-Agent": "Mozilla/5.0 (compatible; LinkChecker)" + } + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cc9b7e6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,260 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + go-version: ['1.21', '1.22', '1.23'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + + - name: Cache Go modules + uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go-${{ matrix.go-version }}- + + - name: Download dependencies + run: go mod download + + - name: Verify dependencies + run: go mod verify + + - name: Run tests + run: go test -v -race -coverprofile=coverage.out ./... + + - name: Upload coverage to Codecov + if: matrix.go-version == '1.23' + uses: codecov/codecov-action@v4 + with: + file: ./coverage.out + flags: unittests + name: codecov-umbrella + fail_ci_if_error: false + + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v4 + with: + version: latest + args: --timeout=5m + + build: + name: Build + runs-on: ubuntu-latest + strategy: + matrix: + goos: [linux, darwin, windows] + goarch: [amd64, arm64] + exclude: + # Windows ARM64 builds are experimental + - goos: windows + goarch: arm64 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Build CLI + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + run: | + output_name="soundtouch-cli-${{ matrix.goos }}-${{ matrix.goarch }}" + if [ "${{ matrix.goos }}" = "windows" ]; then + output_name="${output_name}.exe" + fi + go build -o "$output_name" ./cmd/soundtouch-cli + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: soundtouch-cli-${{ matrix.goos }}-${{ matrix.goarch }} + path: soundtouch-cli-* + + security: + name: Security Scan + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Run Gosec Security Scanner + uses: securecodewarrior/github-action-gosec@master + with: + args: ./... + + - name: Run Nancy vulnerability scanner + run: | + go install github.com/sonatypecommunity/nancy@latest + go list -json -deps ./... | nancy sleuth + + docs: + name: Documentation Check + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check documentation links + uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: 'yes' + use-verbose-mode: 'yes' + config-file: '.github/markdown-link-check.json' + + - name: Validate API documentation + run: | + # Check that all documented endpoints exist in code + echo "Validating API documentation consistency..." + + # Extract endpoint patterns from cookbook + if [ -f "docs/API-COOKBOOK.md" ]; then + echo "✓ API Cookbook exists" + else + echo "✗ API Cookbook missing" + exit 1 + fi + + # Check getting started guide + if [ -f "docs/GETTING-STARTED.md" ]; then + echo "✓ Getting Started guide exists" + else + echo "✗ Getting Started guide missing" + exit 1 + fi + + integration: + name: Integration Test + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Test CLI build and help + run: | + go build -o soundtouch-cli ./cmd/soundtouch-cli + ./soundtouch-cli -help + + - name: Test library imports + run: | + cat > test_import.go << 'EOF' + package main + + import ( + "fmt" + "github.com/user_account/bose-soundtouch/pkg/client" + "github.com/user_account/bose-soundtouch/pkg/models" + "github.com/user_account/bose-soundtouch/pkg/discovery" + ) + + func main() { + // Test basic client creation + c := client.New("192.168.1.100", 8090) + fmt.Printf("Client created for %s\n", c.BaseURL()) + + // Test models can be imported + var info models.Info + fmt.Printf("Info model available: %T\n", info) + + // Test discovery can be imported + var scanner discovery.Scanner + fmt.Printf("Scanner available: %T\n", scanner) + + fmt.Println("All imports successful!") + } + EOF + + go run test_import.go + rm test_import.go + + notify: + name: Notify Status + runs-on: ubuntu-latest + needs: [test, lint, build, security, docs] + if: always() + + steps: + - name: Check overall status + run: | + if [[ "${{ needs.test.result }}" == "success" && \ + "${{ needs.lint.result }}" == "success" && \ + "${{ needs.build.result }}" == "success" && \ + "${{ needs.security.result }}" == "success" && \ + "${{ needs.docs.result }}" == "success" ]]; then + echo "✅ All CI checks passed!" + echo "status=success" >> $GITHUB_OUTPUT + else + echo "❌ Some CI checks failed" + echo "status=failure" >> $GITHUB_OUTPUT + exit 1 + fi + id: status + + - name: Update commit status + if: always() + uses: actions/github-script@v7 + with: + script: | + const state = '${{ steps.status.outputs.status }}' === 'success' ? 'success' : 'failure'; + const description = state === 'success' ? 'All checks passed' : 'Some checks failed'; + + github.rest.repos.createCommitStatus({ + owner: context.repo.owner, + repo: context.repo.repo, + sha: context.sha, + state: state, + description: description, + context: 'CI Pipeline' + }); diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e9a872a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,400 @@ +name: Release + +on: + push: + tags: + - 'v*' + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Tag to release (e.g., v1.0.0)' + required: true + default: 'v1.0.0' + +env: + GO_VERSION: '1.23' + +jobs: + validate: + name: Validate Release + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + is_prerelease: ${{ steps.version.outputs.is_prerelease }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate tag format + id: version + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + TAG_NAME="${{ github.event.inputs.tag }}" + else + TAG_NAME="${GITHUB_REF#refs/tags/}" + fi + + echo "Tag name: $TAG_NAME" + + # Validate semantic versioning format + if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then + echo "❌ Invalid tag format: $TAG_NAME" + echo "Expected format: v1.2.3 or v1.2.3-beta.1" + exit 1 + fi + + # Extract version without 'v' prefix + VERSION=${TAG_NAME#v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + + # Check if prerelease (contains hyphen) + if [[ "$TAG_NAME" =~ - ]]; then + echo "is_prerelease=true" >> $GITHUB_OUTPUT + echo "📦 Prerelease detected: $TAG_NAME" + else + echo "is_prerelease=false" >> $GITHUB_OUTPUT + echo "🚀 Stable release detected: $TAG_NAME" + fi + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Run tests before release + run: | + echo "Running final tests before release..." + go test -v ./... + echo "✅ All tests passed" + + build: + name: Build Release Binaries + runs-on: ubuntu-latest + needs: validate + strategy: + matrix: + include: + - goos: linux + goarch: amd64 + - goos: linux + goarch: arm64 + - goos: linux + goarch: arm + goarm: 7 + - goos: darwin + goarch: amd64 + - goos: darwin + goarch: arm64 + - goos: windows + goarch: amd64 + - goos: freebsd + goarch: amd64 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Cache Go modules + uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }} + + - name: Build binary + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GOARM: ${{ matrix.goarm }} + CGO_ENABLED: 0 + run: | + # Determine output filename + BINARY_NAME="soundtouch-cli" + ARCH_SUFFIX="${{ matrix.goos }}-${{ matrix.goarch }}" + + if [[ "${{ matrix.goarm }}" != "" ]]; then + ARCH_SUFFIX="${ARCH_SUFFIX}v${{ matrix.goarm }}" + fi + + if [[ "${{ matrix.goos }}" == "windows" ]]; then + OUTPUT_NAME="${BINARY_NAME}-v${{ needs.validate.outputs.version }}-${ARCH_SUFFIX}.exe" + else + OUTPUT_NAME="${BINARY_NAME}-v${{ needs.validate.outputs.version }}-${ARCH_SUFFIX}" + fi + + echo "Building: $OUTPUT_NAME" + + # Build with optimizations and version info + go build \ + -ldflags="-s -w -X main.version=v${{ needs.validate.outputs.version }} -X main.commit=${{ github.sha }} -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + -o "$OUTPUT_NAME" \ + ./cmd/soundtouch-cli + + # Verify binary was created and is executable + ls -la "$OUTPUT_NAME" + file "$OUTPUT_NAME" + + echo "binary_name=$OUTPUT_NAME" >> $GITHUB_OUTPUT + id: build + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.build.outputs.binary_name }} + path: ${{ steps.build.outputs.binary_name }} + retention-days: 1 + + checksums: + name: Generate Checksums + runs-on: ubuntu-latest + needs: [validate, build] + + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./binaries + + - name: Generate checksums + run: | + cd binaries + + # Flatten directory structure (artifacts are in subdirs) + find . -name "soundtouch-cli-*" -exec mv {} . \; + + # Remove empty directories + find . -type d -empty -delete + + # Generate SHA256 checksums + sha256sum soundtouch-cli-* > checksums.sha256 + + # Generate SHA512 checksums + sha512sum soundtouch-cli-* > checksums.sha512 + + echo "📋 Generated checksums:" + cat checksums.sha256 + + # Verify all expected files are present + EXPECTED_COUNT=7 # Based on build matrix + ACTUAL_COUNT=$(ls soundtouch-cli-* | wc -l) + + if [[ $ACTUAL_COUNT -ne $EXPECTED_COUNT ]]; then + echo "❌ Expected $EXPECTED_COUNT binaries, found $ACTUAL_COUNT" + ls -la + exit 1 + fi + + echo "✅ All $ACTUAL_COUNT binaries present" + + - name: Upload checksums + uses: actions/upload-artifact@v4 + with: + name: checksums + path: | + binaries/checksums.sha256 + binaries/checksums.sha512 + retention-days: 1 + + - name: Upload all release assets + uses: actions/upload-artifact@v4 + with: + name: release-assets + path: binaries/ + retention-days: 1 + + create_release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: [validate, checksums] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download release assets + uses: actions/download-artifact@v4 + with: + name: release-assets + path: ./release-assets + + - name: Generate release notes + id: release_notes + run: | + TAG_NAME="${GITHUB_REF#refs/tags/}" + VERSION="${TAG_NAME#v}" + + # Generate comprehensive release notes + cat > release_notes.md << EOF + # Bose SoundTouch Go Library $TAG_NAME + + A comprehensive Go library for controlling Bose SoundTouch speakers with 100% API coverage, real-time WebSocket events, and production-ready features. + + ## 🎯 Key Features + + - **100% API Coverage**: All 19 official endpoints + 6 useful extensions (25 total) + - **Real-time Events**: WebSocket support with auto-reconnect and comprehensive event handling + - **Multiroom Control**: Complete zone management and coordination + - **Production Ready**: Connection pooling, error handling, circuit breakers, monitoring + - **Excellent Documentation**: 4000+ lines including Getting Started, Cookbook, Troubleshooting, and Deployment guides + - **CLI Tool**: Full-featured command-line interface with all endpoints + + ## 🚀 Quick Start + + \`\`\`bash + go get github.com/user_account/bose-soundtouch@$TAG_NAME + \`\`\` + + \`\`\`go + package main + + import ( + "fmt" + "log" + + "github.com/user_account/bose-soundtouch/pkg/client" + ) + + func main() { + // Create client + c := client.New("192.168.1.100", 8090) + + // Get device info + info, err := c.GetInfo() + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Device: %s\\n", info.Name) + } + \`\`\` + + ## 📚 Documentation + + - [Getting Started Guide](docs/GETTING-STARTED.md) - 10-minute tutorial from discovery to WebSocket monitoring + - [API Cookbook](docs/API-COOKBOOK.md) - 1000+ lines of real-world patterns and examples + - [Troubleshooting Guide](docs/TROUBLESHOOTING.md) - Systematic issue resolution + - [Deployment Guide](docs/DEPLOYMENT.md) - Production deployment examples (Docker, K8s, systemd) + + ## 🔧 CLI Tool + + Download the CLI tool for your platform from the assets below: + + \`\`\`bash + # Quick device discovery + ./soundtouch-cli -discover + + # Get device information + ./soundtouch-cli -host 192.168.1.100 -info + + # Monitor real-time events + ./soundtouch-cli -host 192.168.1.100 -nowplaying + \`\`\` + + ## 🧪 Tested Hardware + + - Bose SoundTouch 10 + - Bose SoundTouch 20 + - All core functionality validated on real devices + + ## 📈 What's New in $TAG_NAME + + $(git log --pretty=format:"- %s" $(git describe --tags --abbrev=0 HEAD^)..HEAD 2>/dev/null || echo "- Initial release with complete feature set") + + ## 🏗️ Supported Platforms + + This release includes pre-built binaries for: + - Linux (amd64, arm64, armv7) + - macOS (Intel & Apple Silicon) + - Windows (amd64) + - FreeBSD (amd64) + + ## 🔐 Checksums + + SHA256 checksums are provided in \`checksums.sha256\` to verify download integrity. + + ## 🤝 Contributing + + Contributions welcome! See our documentation for examples and patterns. + + ## 📄 License + + MIT License - see [LICENSE](LICENSE) file. + EOF + + echo "release_notes_file=release_notes.md" >> $GITHUB_OUTPUT + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.ref_name }} + name: "Bose SoundTouch Go Library ${{ github.ref_name }}" + body_path: ${{ steps.release_notes.outputs.release_notes_file }} + draft: false + prerelease: ${{ needs.validate.outputs.is_prerelease == 'true' }} + files: | + release-assets/soundtouch-cli-* + release-assets/checksums.sha256 + release-assets/checksums.sha512 + fail_on_unmatched_files: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + update_release: + name: Update Existing Release + runs-on: ubuntu-latest + needs: [validate, checksums] + if: github.event_name == 'release' && github.event.action == 'published' + + steps: + - name: Download release assets + uses: actions/download-artifact@v4 + with: + name: release-assets + path: ./release-assets + + - name: Upload additional assets to existing release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.event.release.tag_name }} + files: | + release-assets/soundtouch-cli-* + release-assets/checksums.sha256 + release-assets/checksums.sha512 + fail_on_unmatched_files: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + notify: + name: Post-Release Notifications + runs-on: ubuntu-latest + needs: [validate, create_release] + if: always() && (needs.create_release.result == 'success' || needs.update_release.result == 'success') + + steps: + - name: Notify success + run: | + echo "🎉 Release ${{ needs.validate.outputs.version }} completed successfully!" + echo "📦 Binaries built for 7 platforms" + echo "🔐 Checksums generated and verified" + echo "📋 Release notes automatically generated" + echo "" + echo "🔗 Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ github.ref_name }}" + echo "" + echo "Next steps:" + echo "- Monitor download metrics" + echo "- Update documentation if needed" + echo "- Announce to community (see scripts/post-release.md)" diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..0a5be25 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,230 @@ +# golangci-lint configuration for Bose SoundTouch Go Library +# See: https://golangci-lint.run/usage/configuration/ + +run: + timeout: 5m + issues-exit-code: 1 + tests: true + skip-dirs: + - vendor + - build + - scripts + skip-files: + - ".*\\.pb\\.go$" + - ".*_gen\\.go$" + +output: + format: colored-line-number + print-issued-lines: true + print-linter-name: true + uniq-by-line: true + sort-results: true + +linters: + enable: + # Default linters + - errcheck # Check for unchecked errors + - gosimple # Simplify code + - govet # Vet examines Go source code + - ineffassign # Detect ineffectual assignments + - staticcheck # Go static analysis + - typecheck # Parse and type-check Go code + - unused # Check for unused constants, variables, functions and types + + # Additional useful linters for production code + - gofmt # Check whether code was gofmt-ed + - goimports # Check import sorting + - misspell # Find commonly misspelled English words + - unconvert # Remove unnecessary type conversions + - unparam # Report unused function parameters + - gocyclo # Compute cyclomatic complexities + - gocritic # Most opinionated Go source code linter + - gosec # Inspect source code for security problems + - exportloopref # Check for pointers to enclosing loop variables + - nolintlint # Reports ill-formed or insufficient nolint directives + - revive # Fast, configurable, extensible, flexible, and beautiful linter + - stylecheck # Stylecheck is a replacement for golint + - whitespace # Tool for detection of leading and trailing whitespace + - wsl # Whitespace Linter - Forces you to use empty lines + - predeclared # Find code that shadows one of Go's predeclared identifiers + - thelper # Detect golang test helpers without t.Helper() call + - tparallel # Detect inappropriate usage of t.Parallel() method in tests + - bodyclose # Check whether HTTP response body is closed successfully + - nilerr # Find the code that returns nil even if it checks that the error is not nil + - nilnil # Check that there is no simultaneous return of nil error and an invalid value + - errchkjson # Check types passed to the json encoding functions + - errorlint # Find code that will cause problems with the error wrapping scheme + - contextcheck # Check the function whether use a non-inherited context + + disable: + - gocognit # Can be too strict for some cases + - funlen # Function length can vary based on complexity + - lll # Line length limit - we'll handle this with gofmt + - gomnd # Magic numbers detector - can be overly aggressive + - exhaustive # Can be too strict for enums + - testpackage # Not always necessary to put tests in separate package + - wrapcheck # Error wrapping can be context-dependent + - nlreturn # Can conflict with other formatting preferences + - gofumpt # Use standard gofmt instead + +linters-settings: + errcheck: + check-type-assertions: true + check-blank: false + exclude-functions: + - (*os.File).Close + - (*bytes.Buffer).Write + - (*bytes.Buffer).WriteString + + govet: + check-shadowing: true + enable-all: true + disable: + - fieldalignment # Can be overly aggressive + + gocyclo: + min-complexity: 15 + + gocritic: + enabled-checks: + - appendAssign + - argOrder + - assignOp + - badCond + - boolExprSimplify + - builtinShadow + - captLocal + - caseOrder + - defaultCaseOrder + - dupArg + - dupBranchBody + - dupCase + - dupSubExpr + - elseif + - emptyFallthrough + - equalFold + - exitAfterDefer + - flagDeref + - flagName + - hexLiteral + - indexAlloc + - initClause + - methodExprCall + - nestingReduce + - newDeref + - nilValReturn + - offBy1 + - paramTypeCombine + - ptrToRefParam + - rangeExprCopy + - rangeValCopy + - regexpMust + - singleCaseSwitch + - sloppyLen + - stringXbytes + - switchTrue + - typeAssertChain + - typeSwitchVar + - underef + - unlambda + - unslice + - valSwap + - weakCond + - yodaStyleExpr + + gosec: + excludes: + - G104 # Audit errors not checked - handled by errcheck + config: + G301: "0755" # Poor file permissions + G302: "0755" # Poor file permissions + G306: "0755" # Poor file permissions + + revive: + rules: + - name: var-naming + arguments: [["ID", "URL", "HTTP", "JSON", "XML", "API", "UUID", "SQL"], []] + - name: exported + arguments: [true] + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: empty-block + - name: error-naming + - name: error-return + - name: error-strings + - name: errorf + - name: increment-decrement + - name: indent-error-flow + - name: package-comments + - name: range + - name: receiver-naming + - name: redefines-builtin-id + - name: superfluous-else + - name: time-naming + - name: unexported-return + - name: unreachable-code + - name: unused-parameter + - name: var-declaration + - name: waitgroup-by-value + + stylecheck: + checks: ["all", "-ST1003"] # Disable ST1003 (should not use underscores in Go names) + + whitespace: + multi-if: false + multi-func: false + + wsl: + strict-append: true + allow-assign-and-call: true + allow-assign-and-anything: false + allow-multiline-assign: true + force-case-trailing-whitespace: 0 + +issues: + exclude-rules: + # Exclude some linters from running on tests files + - path: _test\.go + linters: + - gosec # Security issues less critical in tests + - gocritic # Can be overly strict for test code + - wsl # Whitespace less critical in tests + - gocyclo # Complexity less critical in tests + + # Exclude specific rules for generated files + - path: ".*\\.pb\\.go$" + linters: + - all + + # Exclude some staticcheck messages + - linters: + - staticcheck + text: "SA9003:" # Empty branch + + # Exclude some gosimple messages + - linters: + - gosimple + text: "S1002:" # Omit comparison with boolean constant + + # Allow main functions to not check errors in examples + - path: cmd/.*\.go + text: "Error return value of.*is not checked" + linters: + - errcheck + + # Allow long lines in CLI help text and similar + - path: cmd/.*\.go + text: "Line is.*characters" + linters: + - lll + + exclude-use-default: false + max-issues-per-linter: 0 + max-same-issues: 0 + new: false + +severity: + default-severity: error + case-sensitive: false diff --git a/scripts/post-release.md b/scripts/post-release.md new file mode 100644 index 0000000..7952115 --- /dev/null +++ b/scripts/post-release.md @@ -0,0 +1,210 @@ +# Post-Release Promotion Checklist + +After successfully releasing v1.0.0, follow this checklist to maximize visibility and adoption. + +## ✅ Immediate Actions (Within 24 hours) + +### Go Package Registry +- [ ] Verify pkg.go.dev indexing: https://pkg.go.dev/github.com/user_account/bose-soundtouch +- [ ] If not indexed, submit via: `go get github.com/user_account/bose-soundtouch@v1.0.0` +- [ ] Check documentation rendering on pkg.go.dev + +### Community Engagement +- [ ] **r/golang** Reddit post: + ``` + Title: "Bose SoundTouch Go Library v1.0.0 - 100% API Coverage + WebSocket Events" + Content: Highlight production-ready features, real hardware testing, excellent docs + ``` + +- [ ] **Gopher Slack** (#general, #show-and-tell): + ``` + "Just released a comprehensive Go library for Bose SoundTouch speakers 🎵 + ✅ 100% API coverage (19/19 official endpoints) + ✅ Real-time WebSocket events + ✅ 4000+ lines of documentation + ✅ CLI tool with cross-platform binaries + Tested on real hardware! https://github.com/user_account/bose-soundtouch" + ``` + +- [ ] **Hacker News** submission: + ``` + Title: "Bose SoundTouch Go Library – Complete API with WebSocket Events" + URL: https://github.com/user_account/bose-soundtouch + ``` + +### Social Media +- [ ] **Twitter/X** announcement: + ``` + "🎵 Just released Bose SoundTouch Go Library v1.0.0! + + ✅ 100% API coverage + ✅ Real-time WebSocket events + ✅ Production-ready patterns + ✅ Comprehensive docs & CLI + ✅ Real hardware tested + + Perfect for home automation & music control apps + + #golang #IoT #music #opensource + https://github.com/user_account/bose-soundtouch" + ``` + +- [ ] **LinkedIn** professional post (if applicable) + +## 📋 Medium-term Actions (Within 1 week) + +### Documentation & Examples +- [ ] **Blog post** on personal site/Medium: + ``` + Title ideas: + - "Building a Production-Ready Go Library for IoT Devices" + - "100% API Coverage: Lessons from Building the Bose SoundTouch Go Client" + - "Real Hardware Testing: Why It Matters for IoT Libraries" + ``` + +- [ ] **Dev.to article** with practical examples +- [ ] Create **example projects** repository: + - Home automation integration + - Discord bot for music control + - Web dashboard example + +### Community Lists & Directories +- [ ] Submit to **awesome-go**: https://github.com/avelino/awesome-go + ``` + Category: Audio and Music + Entry: [bose-soundtouch](https://github.com/user_account/bose-soundtouch) - Go library for controlling Bose SoundTouch speakers with 100% API coverage and WebSocket events. + ``` + +- [ ] Submit to **go-awesome**: https://github.com/shivammg/go-awesome +- [ ] List on **awesome-home-assistant**: https://github.com/frenck/awesome-home-assistant +- [ ] Add to **IoT awesome lists**: Search for IoT/smart home Go libraries lists + +### Technical Communities +- [ ] **Go Forum** announcement: https://forum.golangbridge.org/ +- [ ] **Home Assistant Community**: https://community.home-assistant.io/ +- [ ] **Bose Community Forums** (if they exist) +- [ ] **Smart Home subreddits**: r/homeautomation, r/smarthome + +## 🚀 Long-term Growth (Ongoing) + +### Integration Examples +- [ ] **Home Assistant** custom component example +- [ ] **Node-RED** integration guide +- [ ] **Docker Compose** stack for monitoring multiple speakers +- [ ] **Kubernetes** operator for speaker management + +### Technical Content +- [ ] **YouTube video**: "Building Go Libraries for IoT Devices" +- [ ] **Conference talk** submission: GopherCon, local Go meetups +- [ ] **Podcast appearances**: Go Time, other tech podcasts + +### Package Ecosystem +- [ ] Create **Docker Hub** official image +- [ ] **Helm chart** for Kubernetes deployment +- [ ] **Homebrew formula** for easy CLI installation: + ```bash + brew install user_account/tap/soundtouch-cli + ``` + +## 📊 Success Metrics to Track + +### Immediate (1 week) +- [ ] GitHub stars: Target 50+ +- [ ] pkg.go.dev page views: Monitor via GitHub insights +- [ ] CLI downloads: Track release download counts +- [ ] Reddit/HN engagement: Upvotes, comments, discussions + +### Medium-term (1 month) +- [ ] GitHub stars: Target 100+ +- [ ] Issues/PRs from community: Sign of adoption +- [ ] Mentions in other projects: Search GitHub for imports +- [ ] Blog post views/shares + +### Long-term (3 months) +- [ ] Featured in awesome-go lists +- [ ] Integration examples from community +- [ ] Forks and derivative projects +- [ ] Speaking opportunities + +## 📝 Content Templates + +### GitHub Issue Template for Feature Requests +```markdown +**Is your feature request related to a problem?** +A clear description of what the problem is. + +**Describe the solution you'd like** +What you want to happen. + +**Additional context** +Any other context or screenshots. + +**Hardware tested** +Which Bose SoundTouch model(s) you're using. +``` + +### Email Template for Bloggers/Podcasters +``` +Subject: Go Library for Bose SoundTouch Speakers - 100% API Coverage + +Hi [Name], + +I recently released a comprehensive Go library for controlling Bose SoundTouch speakers that might interest your audience: + +🎯 Key highlights: +- 100% API coverage with real hardware validation +- Production-ready patterns and extensive documentation +- WebSocket events for real-time control +- Cross-platform CLI tool + +The project demonstrates several interesting engineering challenges: +- IoT device discovery and control +- WebSocket event handling with auto-reconnect +- XML parsing and validation for legacy APIs +- Cross-platform binary distribution + +Would this be interesting for [blog/podcast]? I'd be happy to discuss the technical details and lessons learned. + +GitHub: https://github.com/user_account/bose-soundtouch + +Best regards, +[Your name] +``` + +## 🎯 Priority Ranking + +**High Impact, Low Effort:** +1. Reddit r/golang post +2. Gopher Slack announcement +3. awesome-go submission +4. Twitter announcement + +**High Impact, Medium Effort:** +5. Blog post on Dev.to +6. Home automation community posts +7. Example projects repository + +**Medium Impact, High Effort:** +8. YouTube video/conference talk +9. Podcast appearances +10. Advanced integration examples + +## 🚨 Common Pitfalls to Avoid + +- [ ] **Don't spam**: Space out announcements across communities +- [ ] **Provide value**: Focus on technical merit, not just promotion +- [ ] **Engage genuinely**: Respond to comments and questions promptly +- [ ] **Keep improving**: Address feedback and issues quickly +- [ ] **Document learnings**: Track what promotion strategies work best + +--- + +## ✅ Completion Checklist + +When you've completed a section, check it off and note the date: + +- [ ] Immediate Actions completed: ___/___/___ +- [ ] Medium-term Actions completed: ___/___/___ +- [ ] First success metrics achieved: ___/___/___ + +**Remember**: Great libraries grow through genuine utility and community engagement, not just promotion. Focus on helping developers solve real problems! 🚀 \ No newline at end of file diff --git a/scripts/prepare-release.sh b/scripts/prepare-release.sh index 2bdeabf..56644e9 100755 --- a/scripts/prepare-release.sh +++ b/scripts/prepare-release.sh @@ -1,14 +1,17 @@ #!/bin/bash -# Bose SoundTouch Go Library - Release Preparation Script -# This script prepares everything needed for a GitHub release +# Bose SoundTouch Go Library - Local Release Preparation Script +# This script prepares everything needed for a local release build +# Note: GitHub workflows handle automated releases on tag push set -e VERSION=${1:-"v1.0.0"} GITHUB_REPO="user_account/bose-soundtouch" -echo "🚀 Preparing release $VERSION for $GITHUB_REPO" +echo "🚀 Preparing local release build $VERSION for $GITHUB_REPO" +echo "💡 Note: This is for local testing. Use 'git tag && git push --tags' for automated release" +echo "" # Verify we're in the right directory if [ ! -f "go.mod" ] || [ ! -d "pkg/client" ]; then @@ -39,24 +42,51 @@ echo "✅ All tests passed" echo "🔨 Building CLI for multiple platforms..." mkdir -p build/releases -# Build for common platforms +# Build for common platforms (same as CI) PLATFORMS=( "linux/amd64" "linux/arm64" + "linux/arm" "darwin/amd64" "darwin/arm64" "windows/amd64" + "freebsd/amd64" ) -for platform in "${PLATFORMS[@]}"; do +GOARM_VALUES=( + "" # linux/amd64 + "" # linux/arm64 + "7" # linux/arm + "" # darwin/amd64 + "" # darwin/arm64 + "" # windows/amd64 + "" # freebsd/amd64 +) + +for i in "${!PLATFORMS[@]}"; do + platform="${PLATFORMS[$i]}" + goarm="${GOARM_VALUES[$i]}" + IFS="/" read -r GOOS GOARCH <<< "$platform" - OUTPUT_NAME="soundtouch-cli-$VERSION-$GOOS-$GOARCH" + + ARCH_SUFFIX="$GOOS-$GOARCH" + if [[ "$goarm" != "" ]]; then + ARCH_SUFFIX="${ARCH_SUFFIX}v$goarm" + fi + + OUTPUT_NAME="soundtouch-cli-$VERSION-$ARCH_SUFFIX" if [ "$GOOS" = "windows" ]; then OUTPUT_NAME="$OUTPUT_NAME.exe" fi - echo " Building for $GOOS/$GOARCH..." - GOOS=$GOOS GOARCH=$GOARCH go build -o "build/releases/$OUTPUT_NAME" ./cmd/soundtouch-cli + echo " Building for $GOOS/$GOARCH${goarm:+v$goarm}..." + + env_vars="GOOS=$GOOS GOARCH=$GOARCH CGO_ENABLED=0" + if [[ "$goarm" != "" ]]; then + env_vars="$env_vars GOARM=$goarm" + fi + + eval "$env_vars go build -ldflags='-s -w -X main.version=$VERSION' -o 'build/releases/$OUTPUT_NAME' ./cmd/soundtouch-cli" done echo "✅ Built CLI for all platforms" @@ -83,6 +113,7 @@ A comprehensive Go library for controlling Bose SoundTouch speakers with 100% AP - **Production Ready**: Connection pooling, error handling, circuit breakers, monitoring - **Excellent Documentation**: 4000+ lines including Getting Started, Cookbook, Troubleshooting, and Deployment guides - **CLI Tool**: Full-featured command-line interface with all endpoints +- **CI/CD Pipeline**: Automated testing, linting, security scans, and releases ## 🚀 Quick Start @@ -162,7 +193,19 @@ MIT License - see [LICENSE](LICENSE) file. ## 🙏 Acknowledgments Built with real hardware testing and community feedback. Special thanks to the Bose developer community. -EOF + + ## 🏗️ Supported Platforms + + This release includes pre-built binaries for: + - Linux (amd64, arm64, armv7) + - macOS (Intel & Apple Silicon) + - Windows (amd64) + - FreeBSD (amd64) + + ## 🔐 Checksums + + SHA256 checksums are provided to verify download integrity. + EOF echo "✅ Generated release notes" @@ -173,11 +216,17 @@ echo "" echo "📦 Files ready for release:" ls -la build/releases/ echo "" -echo "📋 Next steps:" +echo "📋 Next steps for automated release:" echo "1. Push any remaining commits: git push origin main" echo "2. Create and push tag: git tag $VERSION && git push origin $VERSION" -echo "3. Create GitHub release with files in build/releases/" -echo "4. Use build/RELEASE_NOTES.md as release description" +echo "3. GitHub Actions will automatically:" +echo " - Run full CI pipeline (tests, linting, security)" +echo " - Build binaries for all platforms" +echo " - Generate checksums and release notes" +echo " - Create GitHub release with all assets" echo "" -echo "🔗 Release URL will be: https://github.com/$GITHUB_REPO/releases/tag/$VERSION" +echo "🔗 Release will be at: https://github.com/$GITHUB_REPO/releases/tag/$VERSION" +echo "📊 Monitor CI at: https://github.com/$GITHUB_REPO/actions" +echo "" +echo "🧪 Local build completed - use for testing before tagging!" EOF