Add or update .codecov copy.yml

This commit is contained in:
ProtoTess
2026-01-16 04:11:59 +00:00
parent ef340c0e5a
commit 66f6a4e838
391 changed files with 131885 additions and 0 deletions
+275
View File
@@ -0,0 +1,275 @@
# Contributing to onvif-go
Thank you for your interest in contributing to onvif-go! 🎉
## Code of Conduct
This project adheres to a code of conduct. By participating, you are expected to uphold this code. Please be respectful and considerate in all interactions.
## How Can I Contribute?
### Reporting Bugs
Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include:
- Clear, descriptive title
- Steps to reproduce the issue
- Expected vs actual behavior
- Code samples
- Your environment (Go version, OS, camera model)
- Error messages or logs
### Suggesting Features
Feature requests are welcome! Please:
- Use a clear, descriptive title
- Provide detailed description of the proposed feature
- Explain the use case and benefits
- Consider if the feature fits the project scope
### Camera Compatibility Reports
Help us maintain compatibility information:
- Report both working and non-working cameras
- Include manufacturer, model, and firmware version
- Run `onvif-diagnostics` and share the output
- Note any special configuration needed
### Pull Requests
#### Before Submitting
1. Check if there's an existing PR for the same change
2. For major changes, open an issue first to discuss
3. Ensure your code follows the project style
4. Add tests for new functionality
5. Update documentation as needed
#### Submission Process
1. **Fork** the repository
2. **Create** a feature branch from `main`:
```bash
git checkout -b feature/amazing-feature
```
3. **Make** your changes:
- Write clear, descriptive commit messages
- Follow Go best practices and idioms
- Add comments for complex logic
- Include tests
4. **Test** your changes:
```bash
make test
make lint
```
5. **Commit** using conventional commits:
```bash
git commit -m "feat: add GetAnalyticsConfigurations support"
git commit -m "fix: correct PTZ coordinate calculation"
git commit -m "docs: update README with new examples"
```
6. **Push** to your fork:
```bash
git push origin feature/amazing-feature
```
7. **Open** a Pull Request with:
- Clear title and description
- Reference related issues
- List of changes made
- Testing performed
## Development Setup
### Prerequisites
- Go 1.21 or later
- Make (optional, for Makefile targets)
- golangci-lint for linting
### Clone and Build
```bash
git clone https://github.com/0x524a/onvif-go.git
cd onvif-go
go build ./...
```
### Running Tests
```bash
# Run all tests
make test
# Run tests with coverage
make test-coverage
# Run tests with race detection
go test -race ./...
# Run specific package tests
go test ./discovery/...
```
### Linting
```bash
make lint
```
## Coding Standards
### Go Style
- Follow [Effective Go](https://golang.org/doc/effective_go)
- Use `gofmt` for formatting
- Keep functions focused and small
- Write self-documenting code
### Naming Conventions
- Use descriptive variable names
- Follow Go naming conventions (camelCase for private, PascalCase for public)
- Avoid abbreviations unless widely understood
### Error Handling
- Always check errors
- Provide context in error messages
- Use `fmt.Errorf` with `%w` for error wrapping
### Documentation
- Add GoDoc comments for all exported types and functions
- Include usage examples for complex features
- Update README.md when adding new features
### Testing
- Write table-driven tests when applicable
- Test both success and failure cases
- Mock external dependencies
- Aim for >80% coverage for new code
### Example Test
```go
func TestGetDeviceInformation(t *testing.T) {
tests := []struct {
name string
setup func(*testing.T) *Client
want *DeviceInformation
wantErr bool
}{
{
name: "success",
setup: func(t *testing.T) *Client {
// Setup mock
},
want: &DeviceInformation{
Manufacturer: "Test",
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := tt.setup(t)
got, err := client.GetDeviceInformation(context.Background())
if (err != nil) != tt.wantErr {
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("got %v, want %v", got, tt.want)
}
})
}
}
```
## Commit Message Guidelines
We use [Conventional Commits](https://www.conventionalcommits.org/):
- `feat:` - New feature
- `fix:` - Bug fix
- `docs:` - Documentation changes
- `test:` - Test additions or modifications
- `refactor:` - Code refactoring
- `perf:` - Performance improvements
- `chore:` - Maintenance tasks
Examples:
```
feat: add support for Event service
fix: correct PTZ velocity calculation in ContinuousMove
docs: add examples for imaging settings
test: add integration tests for Hikvision cameras
```
## Project Structure
```
onvif-go/
├── client.go # Main ONVIF client
├── types.go # ONVIF type definitions
├── device.go # Device service
├── media.go # Media service
├── ptz.go # PTZ service
├── imaging.go # Imaging service
├── soap/ # SOAP client
├── discovery/ # WS-Discovery
├── server/ # ONVIF server implementation
├── testing/ # Test utilities
├── testdata/ # Test fixtures
├── cmd/ # Command-line tools
└── examples/ # Usage examples
```
## Adding New Features
### Client Features
1. Add method to appropriate service file (device.go, media.go, etc.)
2. Define request/response types in types.go
3. Add tests
4. Update documentation
5. Add example if useful
### Server Features
1. Add handler to server service file
2. Define request/response types
3. Register handler in server.go
4. Add tests
5. Update server documentation
## Review Process
1. Automated checks run on all PRs (tests, linting)
2. Maintainers review code and provide feedback
3. Address review comments
4. Once approved, PR will be merged
## Getting Help
- 💬 [GitHub Discussions](https://github.com/0x524a/onvif-go/discussions) - Ask questions
- 🐛 [GitHub Issues](https://github.com/0x524a/onvif-go/issues) - Report bugs
- 📖 [Documentation](https://pkg.go.dev/github.com/0x524a/onvif-go) - Read the docs
## License
By contributing, you agree that your contributions will be licensed under the MIT License.
---
Thank you for contributing to onvif-go! Your efforts help make ONVIF integration better for everyone. 🚀
+102
View File
@@ -0,0 +1,102 @@
name: 🐛 Bug Report
description: Report a bug or unexpected behavior
title: "[BUG] "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report this bug! Please fill out the information below.
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the bug is
placeholder: Describe the bug...
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to Reproduce
description: Steps to reproduce the behavior
placeholder: |
1. Connect to camera at...
2. Call method...
3. See error...
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: What you expected to happen
placeholder: I expected...
validations:
required: true
- type: textarea
id: code
attributes:
label: Code Sample
description: Minimal code sample to reproduce the issue
render: go
placeholder: |
package main
import "github.com/0x524a/onvif-go"
func main() {
// Your code here
}
- type: input
id: go-version
attributes:
label: Go Version
description: Output of `go version`
placeholder: go version go1.21.0 linux/amd64
validations:
required: true
- type: input
id: lib-version
attributes:
label: Library Version
description: Git commit hash or release version
placeholder: v1.0.0 or commit abc123
- type: input
id: camera
attributes:
label: Camera Model/Brand
description: If applicable
placeholder: Hikvision DS-2CD2xx, Axis M1065-L, etc.
- type: dropdown
id: os
attributes:
label: Operating System
options:
- Linux
- macOS
- Windows
- Other
validations:
required: true
- type: textarea
id: logs
attributes:
label: Error Output/Logs
description: Paste any error messages or logs
render: shell
- type: textarea
id: context
attributes:
label: Additional Context
description: Any other context about the problem
@@ -0,0 +1,86 @@
name: 📷 Camera Compatibility Report
description: Report compatibility with a specific camera model
title: "[CAMERA] "
labels: ["camera-compatibility"]
body:
- type: markdown
attributes:
value: |
Help us track camera compatibility! Share your experience with a specific camera model.
- type: input
id: manufacturer
attributes:
label: Camera Manufacturer
placeholder: Hikvision, Axis, Dahua, Bosch, etc.
validations:
required: true
- type: input
id: model
attributes:
label: Camera Model
placeholder: DS-2CD2xx, M1065-L, IPC-HDW2xxx, etc.
validations:
required: true
- type: input
id: firmware
attributes:
label: Firmware Version
placeholder: V5.7.3 build 220727
- type: dropdown
id: status
attributes:
label: Compatibility Status
options:
- ✅ Fully Working
- ⚠️ Partially Working
- ❌ Not Working
validations:
required: true
- type: checkboxes
id: features
attributes:
label: Working Features
description: Which features work with this camera?
options:
- label: Device Information
- label: Media Profiles
- label: Stream URIs (RTSP)
- label: Snapshots
- label: PTZ Control
- label: Imaging Settings
- label: Discovery
- type: textarea
id: issues
attributes:
label: Known Issues
description: Describe any issues or limitations
placeholder: PTZ presets don't work, imaging settings return error, etc.
- type: textarea
id: notes
attributes:
label: Additional Notes
description: Any special configuration or workarounds needed
placeholder: Requires authentication, needs specific settings, etc.
- type: checkboxes
id: test-results
attributes:
label: Test Results
description: Have you run the diagnostic tool?
options:
- label: I have run onvif-diagnostics and can attach the output
required: false
- type: textarea
id: diagnostic-output
attributes:
label: Diagnostic Output
description: Paste the output from onvif-diagnostics if available
render: json
+11
View File
@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 💬 Discussions
url: https://github.com/0x524a/onvif-go/discussions
about: Ask questions and discuss ideas with the community
- name: 📖 Documentation
url: https://pkg.go.dev/github.com/0x524a/onvif-go
about: Read the API documentation
- name: 📚 Examples
url: https://github.com/0x524a/onvif-go/tree/main/examples
about: Browse code examples
@@ -0,0 +1,75 @@
name: ✨ Feature Request
description: Suggest a new feature or enhancement
title: "[FEATURE] "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thank you for suggesting a new feature! Please provide details below.
- type: textarea
id: problem
attributes:
label: Problem Statement
description: Is your feature request related to a problem? Please describe.
placeholder: I'm always frustrated when...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: Describe the solution you'd like
placeholder: I would like to see...
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: Describe any alternative solutions or features you've considered
placeholder: I also considered...
- type: dropdown
id: category
attributes:
label: Feature Category
description: Which area does this feature relate to?
options:
- Client - Device Service
- Client - Media Service
- Client - PTZ Service
- Client - Imaging Service
- Client - Discovery
- Server Implementation
- Documentation
- Testing/Examples
- Performance
- Other
validations:
required: true
- type: textarea
id: use-case
attributes:
label: Use Case
description: Describe your use case for this feature
placeholder: This would help with...
- type: checkboxes
id: contribution
attributes:
label: Contribution
description: Would you be willing to contribute this feature?
options:
- label: I would be willing to submit a PR for this feature
required: false
- type: textarea
id: context
attributes:
label: Additional Context
description: Add any other context, screenshots, or examples
+79
View File
@@ -0,0 +1,79 @@
## Description
<!-- Provide a clear and concise description of your changes -->
## Type of Change
<!-- Mark the relevant option with an "x" -->
- [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
- [ ] ✨ New feature (non-breaking change which adds functionality)
- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] 📝 Documentation update
- [ ] 🧪 Test improvements
- [ ] ♻️ Code refactoring
- [ ] ⚡ Performance improvement
## Related Issues
<!-- Link to related issues using #issue_number -->
Fixes #
Relates to #
## Changes Made
<!-- List the main changes in this PR -->
-
-
-
## Testing Performed
<!-- Describe the tests you ran to verify your changes -->
- [ ] Unit tests pass locally
- [ ] Added new tests for new functionality
- [ ] Tested with real ONVIF camera(s)
- [ ] Ran `make lint` with no errors
- [ ] Ran `make test` with all tests passing
### Camera Testing (if applicable)
<!-- If you tested with physical cameras, provide details -->
- **Camera Model**:
- **Firmware Version**:
- **Test Results**:
## Documentation
<!-- Mark what documentation was updated -->
- [ ] Code comments added/updated
- [ ] README.md updated
- [ ] Examples added/updated
- [ ] API documentation (GoDoc) updated
- [ ] CHANGELOG.md updated
## Checklist
<!-- Ensure all items are complete before submitting -->
- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published
## Breaking Changes
<!-- If this introduces breaking changes, describe them and migration path -->
## Screenshots/Examples
<!-- If applicable, add screenshots or example code -->
```go
// Example usage
```
## Additional Context
<!-- Add any other context about the PR here -->
## Reviewer Notes
<!-- Any specific areas you'd like reviewers to focus on -->
+180
View File
@@ -0,0 +1,180 @@
# GitHub Actions Workflows
This directory contains all CI/CD workflows for the ONVIF Go library.
## Workflows
### 🔄 CI (`ci.yml`) - Main Pipeline
**Unified continuous integration workflow with fail-fast behavior.**
The CI pipeline runs sequentially - if any stage fails, subsequent stages are skipped:
```
fmt → lint → test → sonarcloud
↘ build
```
**Stages:**
| Stage | Description | Depends On |
|-------|-------------|------------|
| **fmt** | Format check using `gofmt -s` | - |
| **lint** | Static analysis with `go vet` and `golangci-lint` | fmt |
| **test** | Unit tests with race detector + coverage | lint |
| **sonarcloud** | Code quality & security analysis (push to master only) | test |
| **build** | Build verification for all packages | test |
| **ci-success** | Final status check | all |
**Features:**
- ✅ Fail-fast: stops immediately if any check fails
- ✅ Codecov integration for coverage reporting
- ✅ SonarCloud integration for code quality
- ✅ Go module caching for faster builds
- ✅ Concurrency control (cancels in-progress runs)
**Triggers:**
- Push to `master`, `main`
- All pull requests targeting `master`, `main`
**Required for PR Merge:**
All stages must pass before a PR can be merged. Configure branch protection rules in GitHub:
1. Go to **Settings → Branches → Branch protection rules**
2. Add rule for `master`
3. Enable **Require status checks to pass before merging**
4. Select these required checks:
- `Format Check`
- `Lint`
- `Test & Coverage`
- `SonarCloud Analysis`
- `Build Verification`
- `CI Success`
---
### 🧪 Extended Tests (`test.yml`)
Extended testing workflow for comprehensive test coverage.
**Jobs:**
- **test-older-versions** - Test on older Go versions (1.19, 1.20)
- **benchmark** - Run benchmark tests
- **race-detector** - Extended race detector tests
**Triggers:**
- Manual dispatch
- Weekly schedule (Sunday 2 AM UTC)
- Push to `master`/`main` when Go files change
---
### 🚀 Release (`release.yml`)
Automated release workflow for creating GitHub releases.
**Jobs:**
- **build** - Build binaries for all platforms (Linux, Windows, macOS, multiple architectures)
- **release** - Create GitHub release with artifacts
- **docker** - Build and push Docker images to GHCR
**Triggers:**
- Push tags matching `v*.*.*`
- Manual dispatch with version input
---
### 🔒 Security (`security.yml`)
Security scanning workflow.
**Jobs:**
- **gosec** - Security scanner
- **govulncheck** - Vulnerability checker
**Triggers:**
- Push to `master`/`main`
- Pull requests
- Weekly schedule
---
### 📚 Documentation (`docs.yml`)
Documentation validation workflow.
**Triggers:**
- Push to `master`/`main` when docs change
- Manual dispatch
---
### 🔐 Dependency Review (`dependency-review.yml`)
Dependency vulnerability review.
**Triggers:**
- Pull requests
---
## CI Pipeline Flow
```
┌─────────────────────────────────────────────────────────────────┐
│ CI PIPELINE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────────────────────┐ │
│ │ FMT │────▶│ LINT │────▶│ TEST + COVERAGE │ │
│ └─────────┘ └─────────┘ └───────────┬─────────────┘ │
│ │ │
│ ┌─────────┴─────────┐ │
│ ▼ ▼ │
│ ┌────────────┐ ┌───────────┐ │
│ │ SONARCLOUD │ │ BUILD │ │
│ │ (push only)│ └───────────┘ │
│ └────────────┘ │ │
│ │ │ │
│ └─────────┬─────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ CI SUCCESS │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
❌ If any stage fails, the pipeline stops immediately (fail-fast)
️ SonarCloud only runs on push to master/main (skipped for PRs)
```
---
## SonarCloud Configuration
Security Hotspot analysis excludes:
- Test files (`**/*_test.go`)
- CI configuration (`**/.github/**`)
- Test utilities (`**/testing/**`, `**/testdata/**`)
- Example code (`**/examples/**`)
- CLI tools (`**/cmd/**`)
This ensures security analysis focuses on production library code.
---
## Required Secrets
| Secret | Required | Description |
|--------|----------|-------------|
| `CODECOV_TOKEN` | Yes | Coverage reporting to Codecov |
| `SONAR_TOKEN` | Yes | SonarCloud code analysis |
| `DOCKERHUB_USERNAME` | No | Docker Hub releases |
| `DOCKERHUB_TOKEN` | No | Docker Hub releases |
---
## Workflow Status
- ✅ Go 1.24 as primary version
- ✅ Unified fail-fast CI pipeline
- ✅ Go module caching for faster builds
- ✅ Artifact uploads for coverage and releases
- ✅ Concurrency control
---
*Last Updated: December 3, 2025*
+255
View File
@@ -0,0 +1,255 @@
name: CI
on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
types: [opened, synchronize, reopened]
permissions:
contents: read
checks: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
GO_VERSION: '1.24.x'
jobs:
# Stage 1: Format Check (fastest - fail immediately if code isn't formatted)
fmt:
name: Format Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Check formatting
run: |
unformatted=$(gofmt -s -l . | grep -v vendor || true)
if [ -n "$unformatted" ]; then
echo "❌ The following files are not properly formatted:"
echo "$unformatted"
echo ""
echo "Run 'gofmt -s -w .' to fix formatting issues"
exit 1
fi
echo "✅ All files are properly formatted"
# Stage 2: Lint (depends on fmt)
lint:
name: Lint
runs-on: ubuntu-latest
needs: fmt
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ env.GO_VERSION }}-
- name: Download dependencies
run: go mod download
- name: Run go vet
run: go vet ./...
- name: Run golangci-lint
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v6.5.0
with:
version: v2.1.6
args: --timeout=5m
# Stage 3: Test with Coverage (depends on lint)
test:
name: Test & Coverage
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Full history for SonarCloud
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ env.GO_VERSION }}-
- name: Download dependencies
run: go mod download
- name: Run tests with coverage
run: |
go test -v -race -covermode=atomic -coverprofile=coverage.out -json ./... > test-report.json 2>&1 || true
# Ensure coverage file exists even if tests fail
if [ ! -f coverage.out ]; then
echo "mode: atomic" > coverage.out
fi
- name: Display coverage summary
run: |
echo "📊 Coverage Summary:"
go tool cover -func=coverage.out | tail -20
- name: Upload coverage artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: coverage-reports
path: |
coverage.out
test-report.json
retention-days: 7
- name: Upload to Codecov
uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v4.6.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.out
flags: unittests
name: codecov-onvif-go
# Don't fail on PRs from forks where token may not be available
fail_ci_if_error: ${{ github.event_name == 'push' }}
verbose: true
# Stage 4: SonarCloud Analysis (depends on test)
# Only runs on push to master/main when SONAR_TOKEN is available
# Skipped for PRs from forks where secrets are not accessible
sonarcloud:
name: SonarCloud Analysis
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && github.repository == '0x524a/onvif-go'
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Full history for accurate blame information
- name: Download coverage reports
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: coverage-reports
- name: Verify coverage file
run: |
echo "📁 Downloaded files:"
ls -la
if [ -f coverage.out ]; then
echo "✅ Coverage file found"
head -5 coverage.out
else
echo "⚠️ Coverage file not found, creating empty one"
echo "mode: atomic" > coverage.out
fi
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@4006f663ecaf1f8093e8e4abb9227f6041f52216 # v3.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# Stage 5: Build Verification (depends on test, runs in parallel with sonarcloud)
build:
name: Build Verification
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ env.GO_VERSION }}-
- name: Download dependencies
run: go mod download
- name: Build library
run: go build -v ./...
- name: Build CLI tools
run: |
echo "🔨 Building CLI tools..."
go build -v -o bin/onvif-cli ./cmd/onvif-cli
go build -v -o bin/onvif-quick ./cmd/onvif-quick
go build -v -o bin/onvif-server ./cmd/onvif-server
go build -v -o bin/onvif-diagnostics ./cmd/onvif-diagnostics
echo "✅ All CLI tools built successfully"
# Final status check
ci-success:
name: CI Success
runs-on: ubuntu-latest
needs: [fmt, lint, test, sonarcloud, build]
if: always()
steps:
- name: Check all jobs status
run: |
if [[ "${{ needs.fmt.result }}" != "success" ]]; then
echo "❌ Format check failed"
exit 1
fi
if [[ "${{ needs.lint.result }}" != "success" ]]; then
echo "❌ Lint check failed"
exit 1
fi
if [[ "${{ needs.test.result }}" != "success" ]]; then
echo "❌ Tests failed"
exit 1
fi
# SonarCloud is optional - only fails if it ran and failed (not if skipped)
if [[ "${{ needs.sonarcloud.result }}" == "failure" ]]; then
echo "❌ SonarCloud analysis failed"
exit 1
fi
if [[ "${{ needs.sonarcloud.result }}" == "skipped" ]]; then
echo "️ SonarCloud analysis skipped (only runs on push to master/main)"
fi
if [[ "${{ needs.build.result }}" != "success" ]]; then
echo "❌ Build verification failed"
exit 1
fi
echo "✅ All CI checks passed successfully!"
@@ -0,0 +1,22 @@
name: Dependency Review
on:
pull_request:
branches: [ master, main, develop ]
permissions:
contents: read
jobs:
dependency-review:
name: Review Dependencies
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Dependency Review
uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1
with:
fail-on-severity: moderate
+33
View File
@@ -0,0 +1,33 @@
name: Documentation
on:
push:
branches: [ master, main ]
paths:
- 'docs/**'
- '*.md'
workflow_dispatch:
permissions:
contents: read
jobs:
docs-check:
name: Documentation Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Check for broken links
uses: lycheeverse/lychee-action@f81112d0d2814ded911bd23e3beaa9dda9093915 # v2.3.0
with:
args: --verbose --no-progress docs/ *.md
continue-on-error: true
- name: Validate markdown
uses: DavidAnson/markdownlint-cli2-action@05f32210e84442804257b2c8a4c84aa7067b5e06 # v19.0.0
with:
globs: 'docs/**/*.md'
continue-on-error: true
+286
View File
@@ -0,0 +1,286 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., v1.2.3)'
required: true
permissions:
contents: write
jobs:
build:
name: Build Release Binaries
runs-on: ubuntu-latest
strategy:
matrix:
include:
# Linux
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
- goos: linux
goarch: arm
goarm: 7
# Windows
- goos: windows
goarch: amd64
- goos: windows
goarch: arm64
# macOS
- goos: darwin
goarch: amd64
- goos: darwin
goarch: arm64
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '1.24.x'
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION=${GITHUB_REF#refs/tags/}
fi
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "Version: ${VERSION}"
- name: Build binaries
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
CGO_ENABLED: 0
run: |
VERSION=${{ steps.version.outputs.VERSION }}
SHORT_SHA=${{ steps.version.outputs.SHORT_SHA }}
LDFLAGS="-s -w -X main.Version=${VERSION} -X main.Commit=${SHORT_SHA}"
# Set file extension for Windows
EXT=""
if [ "${{ matrix.goos }}" = "windows" ]; then
EXT=".exe"
fi
# Build all CLI tools
mkdir -p dist
echo "🔨 Building onvif-cli..."
go build -ldflags="${LDFLAGS}" -o "dist/onvif-cli-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-cli
echo "🔨 Building onvif-quick..."
go build -ldflags="${LDFLAGS}" -o "dist/onvif-quick-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-quick
echo "🔨 Building onvif-server..."
go build -ldflags="${LDFLAGS}" -o "dist/onvif-server-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-server
echo "🔨 Building onvif-diagnostics..."
go build -ldflags="${LDFLAGS}" -o "dist/onvif-diagnostics-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-diagnostics
- name: Create archive
run: |
VERSION=${{ steps.version.outputs.VERSION }}
PLATFORM="${{ matrix.goos }}-${{ matrix.goarch }}"
ARCHIVE_NAME="onvif-go-${VERSION}-${PLATFORM}"
mkdir -p releases staging
# Copy binaries with clean names (without platform suffix)
if [ "${{ matrix.goos }}" = "windows" ]; then
cp dist/onvif-cli-${{ matrix.goos }}-${{ matrix.goarch }}.exe staging/onvif-cli.exe
cp dist/onvif-quick-${{ matrix.goos }}-${{ matrix.goarch }}.exe staging/onvif-quick.exe
cp dist/onvif-server-${{ matrix.goos }}-${{ matrix.goarch }}.exe staging/onvif-server.exe
cp dist/onvif-diagnostics-${{ matrix.goos }}-${{ matrix.goarch }}.exe staging/onvif-diagnostics.exe
else
cp dist/onvif-cli-${{ matrix.goos }}-${{ matrix.goarch }} staging/onvif-cli
cp dist/onvif-quick-${{ matrix.goos }}-${{ matrix.goarch }} staging/onvif-quick
cp dist/onvif-server-${{ matrix.goos }}-${{ matrix.goarch }} staging/onvif-server
cp dist/onvif-diagnostics-${{ matrix.goos }}-${{ matrix.goarch }} staging/onvif-diagnostics
fi
# Copy documentation
cp README.md LICENSE staging/ 2>/dev/null || true
# Create archive from staging directory
if [ "${{ matrix.goos }}" = "windows" ]; then
cd staging
zip -r "../releases/${ARCHIVE_NAME}.zip" .
cd ..
else
cd staging
tar czf "../releases/${ARCHIVE_NAME}.tar.gz" .
cd ..
fi
echo "✅ Created ${ARCHIVE_NAME}.tar.gz"
- name: Generate checksums
run: |
cd releases
if command -v sha256sum >/dev/null 2>&1; then
sha256sum * > checksums-${{ matrix.goos }}-${{ matrix.goarch }}.txt
else
shasum -a 256 * > checksums-${{ matrix.goos }}-${{ matrix.goarch }}.txt
fi
- name: Upload artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: release-${{ matrix.goos }}-${{ matrix.goarch }}
path: releases/*
retention-days: 7
release:
name: Create GitHub Release
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: all-releases
pattern: release-*
merge-multiple: true
- name: Generate combined checksums
run: |
cd all-releases
# Combine all checksum files
cat checksums-*.txt > checksums.txt 2>/dev/null || true
# Remove individual checksum files
rm -f checksums-*.txt
- name: Get version and changelog
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION=${GITHUB_REF#refs/tags/}
fi
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
# Generate changelog from commits since last tag
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
if [ -n "$PREV_TAG" ]; then
echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
git log --pretty=format:"- %s (%h)" ${PREV_TAG}..HEAD >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
else
echo "CHANGELOG=Initial release" >> $GITHUB_OUTPUT
fi
- name: Create Release
uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.2
with:
files: all-releases/*
draft: false
prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') || contains(github.ref, '-alpha') }}
generate_release_notes: true
make_latest: true
body: |
## Release ${{ steps.version.outputs.VERSION }}
### 📦 Installation
Download the appropriate binary for your platform below.
#### Linux/macOS
```bash
# Download and extract
wget https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.VERSION }}/onvif-go-${{ steps.version.outputs.VERSION }}-linux-amd64.tar.gz
tar xzf onvif-go-${{ steps.version.outputs.VERSION }}-linux-amd64.tar.gz
# Make executable and move to PATH
chmod +x onvif-cli
sudo mv onvif-cli /usr/local/bin/onvif-cli
```
#### Windows
Download the `.zip` file for your architecture and extract it.
#### Go Library
```bash
go get github.com/${{ github.repository }}@${{ steps.version.outputs.VERSION }}
```
### 🔐 Checksums
SHA256 checksums are available in `checksums.txt`
### 📝 Changes
${{ steps.version.outputs.CHANGELOG }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
docker:
name: Build and Push Docker Image
needs: build
runs-on: ubuntu-latest
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up QEMU
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.6.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Login to GitHub Container Registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
# Remove 'v' prefix if present
VERSION=${VERSION#v}
else
VERSION=${GITHUB_REF#refs/tags/v}
fi
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v5.5.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ steps.version.outputs.VERSION }}
cache-from: type=gha
cache-to: type=gha,mode=max
+69
View File
@@ -0,0 +1,69 @@
name: Security Scan
on:
push:
branches: [ master, main ]
pull_request:
branches: [ master, main ]
schedule:
- cron: '0 0 * * 0' # Weekly on Sunday
permissions:
contents: read
security-events: write
jobs:
gosec:
name: Security Scan (gosec)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '1.24.x'
- name: Install and run gosec
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
gosec -no-fail -fmt json -out gosec-report.json ./... || true
- name: Upload gosec report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: gosec-report
path: gosec-report.json
retention-days: 30
- name: Display gosec results
if: always()
run: |
if [ -f gosec-report.json ]; then
echo "📊 Gosec Security Scan Results:"
cat gosec-report.json | jq -r '.Stats // empty' || echo "No stats available"
echo ""
echo "Issues found:"
cat gosec-report.json | jq -r '.Issues[]? | "\(.severity | ascii_upcase): \(.rule_id) - \(.details)"' || echo "No issues found"
fi
govulncheck:
name: Vulnerability Check (govulncheck)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '1.24.x'
- name: Run govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./... || true
+108
View File
@@ -0,0 +1,108 @@
name: Extended Tests
on:
workflow_dispatch: # Manual trigger
schedule:
- cron: '0 2 * * 0' # Weekly on Sunday at 2 AM UTC
push:
branches: [ master, main ]
paths:
- '**.go'
- 'go.mod'
- 'go.sum'
jobs:
# Run tests on older Go versions
test-older-versions:
name: Test on Go ${{ matrix.go-version }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
go-version: ['1.20', '1.19']
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ matrix.go-version }}
- name: Cache Go modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
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: Run tests
run: go test -v -race ./...
# Run benchmarks
benchmark:
name: Benchmark Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '1.24.x'
- name: Cache Go modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-1.24.x-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-1.24.x-
- name: Download dependencies
run: go mod download
- name: Run benchmarks
run: go test -bench=. -benchmem ./... -run=^$ || echo "⚠️ No benchmarks found"
# Test with race detector
race-detector:
name: Race Detector Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '1.24.x'
- name: Cache Go modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-1.24.x-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-1.24.x-
- name: Download dependencies
run: go mod download
- name: Run tests with race detector
run: go test -race -timeout=10m ./...