mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 08:36:13 +00:00
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
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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"]
|
||||
@@ -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)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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'
|
||||
});
|
||||
@@ -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)"
|
||||
+230
@@ -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
|
||||
@@ -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! 🚀
|
||||
+62
-13
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user