chore: update CI/CD workflows and configuration
- Enhanced .golangci.yml with additional linters and settings for improved code quality checks. - Updated CI workflow to include multiple branches for pull requests and improved caching strategies. - Added new workflows for documentation checks, dependency reviews, and security scans. - Refined coverage analysis workflow to provide detailed reports and comments on pull requests. - Removed outdated test workflow and consolidated testing strategies into extended tests. - Improved release workflow with better version handling and artifact management.
This commit is contained in:
@@ -0,0 +1,109 @@
|
|||||||
|
# GitHub Actions Workflows
|
||||||
|
|
||||||
|
This directory contains all CI/CD workflows for the ONVIF Go library.
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
### 🔄 CI (`ci.yml`)
|
||||||
|
Main continuous integration workflow that runs on every push and pull request.
|
||||||
|
|
||||||
|
**Jobs:**
|
||||||
|
- **validate** - Quick validation (formatting, vet, lint)
|
||||||
|
- **test** - Run tests with coverage on Go 1.23
|
||||||
|
- **test-matrix** - Test on multiple Go versions (1.21, 1.22, 1.23) and platforms (Linux, macOS, Windows)
|
||||||
|
- **build** - Build verification for all packages and examples
|
||||||
|
- **sonarcloud** - Code quality analysis (runs on master/main only)
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- Push to `master`, `main`, `develop`
|
||||||
|
- Pull requests to `master`, `main`, `develop`
|
||||||
|
|
||||||
|
### 🧪 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
|
||||||
|
|
||||||
|
### 📊 Coverage Analysis (`coverage.yml`)
|
||||||
|
Post-CI coverage analysis and reporting.
|
||||||
|
|
||||||
|
**Jobs:**
|
||||||
|
- **coverage-analysis** - Detailed coverage analysis with package breakdown
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- After successful CI workflow on `master`/`main`
|
||||||
|
|
||||||
|
### 🚀 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
|
||||||
|
|
||||||
|
### 🔍 Lint (`lint.yml`)
|
||||||
|
Dedicated linting workflow.
|
||||||
|
|
||||||
|
**Triggers:**
|
||||||
|
- Push to `master`, `main`, `develop`
|
||||||
|
- Pull requests
|
||||||
|
|
||||||
|
### 🔒 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
|
||||||
|
|
||||||
|
## Workflow Status
|
||||||
|
|
||||||
|
All workflows use:
|
||||||
|
- ✅ Latest action versions
|
||||||
|
- ✅ Go 1.23 as primary version
|
||||||
|
- ✅ Caching for faster builds
|
||||||
|
- ✅ Matrix builds for multiple platforms
|
||||||
|
- ✅ Artifact uploads for coverage and releases
|
||||||
|
|
||||||
|
## Required Secrets
|
||||||
|
|
||||||
|
- `CODECOV_TOKEN` - For coverage reporting (optional)
|
||||||
|
- `SONAR_TOKEN` - For SonarCloud analysis (optional)
|
||||||
|
- `DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN` - For Docker Hub (optional)
|
||||||
|
|
||||||
|
## Concurrency
|
||||||
|
|
||||||
|
Workflows use concurrency groups to cancel in-progress runs when new commits are pushed, saving CI resources.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last Updated: December 2, 2025*
|
||||||
|
|
||||||
+69
-58
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [ master, main, develop ]
|
branches: [ master, main, develop ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ master, main, develop ]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -16,19 +16,10 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Status check - always runs
|
|
||||||
status-check:
|
|
||||||
name: Workflow Status
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Workflow started
|
|
||||||
run: echo "✅ CI workflow is running"
|
|
||||||
|
|
||||||
# Quick validation - fail fast on obvious issues
|
# Quick validation - fail fast on obvious issues
|
||||||
validate:
|
validate:
|
||||||
name: Quick Validation
|
name: Quick Validation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: status-check
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -42,7 +33,9 @@ jobs:
|
|||||||
- name: Cache Go modules
|
- name: Cache Go modules
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
@@ -53,18 +46,22 @@ jobs:
|
|||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: |
|
run: |
|
||||||
if [ "$(gofmt -s -l . | grep -v vendor | wc -l)" -gt 0 ]; then
|
if [ "$(gofmt -s -l . | grep -v vendor | wc -l)" -gt 0 ]; then
|
||||||
echo "Code formatting issues found:"
|
echo "❌ Code formatting issues found:"
|
||||||
gofmt -s -d . | grep -v vendor
|
gofmt -s -d . | grep -v vendor
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
echo "✅ Code formatting is correct"
|
||||||
|
|
||||||
- name: Lint
|
- name: Run go vet
|
||||||
uses: golangci/golangci-lint-action@v4
|
run: go vet ./...
|
||||||
|
|
||||||
|
- name: Lint with golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v6
|
||||||
with:
|
with:
|
||||||
version: v1.64
|
version: latest
|
||||||
skip-cache: true
|
args: --timeout=5m
|
||||||
|
|
||||||
# Test on primary Go version
|
# Test on primary Go version with coverage
|
||||||
test:
|
test:
|
||||||
name: Test (Go 1.23)
|
name: Test (Go 1.23)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -82,7 +79,9 @@ jobs:
|
|||||||
- name: Cache Go modules
|
- name: Cache Go modules
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-1.23-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-1.23-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-1.23-
|
${{ runner.os }}-go-1.23-
|
||||||
@@ -103,7 +102,7 @@ jobs:
|
|||||||
files: ./coverage.out
|
files: ./coverage.out
|
||||||
flags: unittests
|
flags: unittests
|
||||||
name: codecov-umbrella
|
name: codecov-umbrella
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: false
|
||||||
|
|
||||||
- name: Archive coverage
|
- name: Archive coverage
|
||||||
if: always()
|
if: always()
|
||||||
@@ -115,17 +114,18 @@ jobs:
|
|||||||
coverage.html
|
coverage.html
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
# Test on multiple Go versions (after primary test passes)
|
# Test on multiple Go versions and platforms
|
||||||
test-matrix:
|
test-matrix:
|
||||||
name: Test (Go ${{ matrix.go-version }})
|
name: Test (Go ${{ matrix.go-version }} on ${{ matrix.os }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: test
|
needs: validate
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true # Stop on first failure
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
go-version: ['1.21', '1.22']
|
go-version: ['1.21', '1.22', '1.23']
|
||||||
exclude:
|
exclude:
|
||||||
|
# Skip older Go versions on macOS and Windows to save CI time
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
go-version: '1.21'
|
go-version: '1.21'
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
@@ -156,40 +156,11 @@ jobs:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test -v -race ./...
|
run: go test -v -race ./...
|
||||||
|
|
||||||
# Code quality - only run if tests pass
|
|
||||||
sonarcloud:
|
|
||||||
name: Code Quality (SonarCloud)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: test
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && secrets.SONAR_TOKEN != ''
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Download coverage from test job
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: coverage-report
|
|
||||||
|
|
||||||
- name: SonarCloud Scan
|
|
||||||
uses: SonarSource/sonarcloud-github-action@v2
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
||||||
with:
|
|
||||||
args: >
|
|
||||||
-Dsonar.projectKey=0x524a_onvif-go
|
|
||||||
-Dsonar.organization=0x524a
|
|
||||||
-Dsonar.go.coverage.reportPaths=coverage.out
|
|
||||||
|
|
||||||
# Build verification
|
# Build verification
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build Verification
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: test
|
needs: validate
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -203,7 +174,9 @@ jobs:
|
|||||||
- name: Cache Go modules
|
- name: Cache Go modules
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-1.23-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-1.23-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-1.23-
|
${{ runner.os }}-go-1.23-
|
||||||
@@ -217,6 +190,44 @@ jobs:
|
|||||||
- name: Build examples
|
- name: Build examples
|
||||||
run: |
|
run: |
|
||||||
for dir in examples/*/; do
|
for dir in examples/*/; do
|
||||||
echo "Building $dir"
|
if [ -f "$dir/main.go" ] || [ -f "$dir/*.go" ]; then
|
||||||
(cd "$dir" && go build -v .)
|
echo "Building $dir"
|
||||||
|
(cd "$dir" && go build -v .) || echo "⚠️ Failed to build $dir"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
- name: Build CLI tools
|
||||||
|
run: |
|
||||||
|
go build -v ./cmd/onvif-cli
|
||||||
|
go build -v ./cmd/onvif-quick
|
||||||
|
go build -v ./cmd/onvif-server
|
||||||
|
go build -v ./cmd/onvif-diagnostics
|
||||||
|
|
||||||
|
# Code quality - only run if tests pass
|
||||||
|
sonarcloud:
|
||||||
|
name: Code Quality (SonarCloud)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: test
|
||||||
|
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') && secrets.SONAR_TOKEN != ''
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Download coverage from test job
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report
|
||||||
|
|
||||||
|
- name: SonarCloud Scan
|
||||||
|
uses: SonarSource/sonarcloud-github-action@master
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
with:
|
||||||
|
args: >
|
||||||
|
-Dsonar.projectKey=0x524a_onvif-go
|
||||||
|
-Dsonar.organization=0x524a
|
||||||
|
-Dsonar.go.coverage.reportPaths=coverage.out
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Additional Coverage Reports
|
name: Coverage Analysis
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
workflow_run:
|
||||||
@@ -15,28 +15,55 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Set up Go
|
||||||
uses: actions/download-artifact@fb7b1ae3fa6edf41bfe27490ab69d8657bea0656 # v4.1.7
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.23'
|
||||||
|
|
||||||
|
- name: Download coverage artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: coverage-report
|
name: coverage-report
|
||||||
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Check coverage percentage
|
- name: Check coverage percentage
|
||||||
run: |
|
run: |
|
||||||
if [ -f coverage.out ]; then
|
if [ -f coverage.out ]; then
|
||||||
|
echo "📊 Coverage Report:"
|
||||||
|
go tool cover -func=coverage.out | tail -1
|
||||||
|
|
||||||
coverage=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//')
|
coverage=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//')
|
||||||
echo "Coverage: $coverage%"
|
echo "Total Coverage: ${coverage}%"
|
||||||
# Set threshold to 40%
|
|
||||||
if (( $(echo "$coverage < 40" | bc -l) )); then
|
# Set threshold to 50%
|
||||||
echo "⚠️ Coverage below 40% threshold: $coverage%"
|
threshold=50
|
||||||
|
if (( $(echo "$coverage < $threshold" | bc -l) )); then
|
||||||
|
echo "⚠️ Coverage below ${threshold}% threshold: ${coverage}%"
|
||||||
|
echo "::warning::Coverage is below ${threshold}% threshold"
|
||||||
else
|
else
|
||||||
echo "✅ Coverage above threshold: $coverage%"
|
echo "✅ Coverage above ${threshold}% threshold: ${coverage}%"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Generate detailed coverage by package
|
||||||
|
echo ""
|
||||||
|
echo "📦 Coverage by Package:"
|
||||||
|
go tool cover -func=coverage.out | grep -E "^github.com" | sort -k3 -nr | head -20
|
||||||
|
else
|
||||||
|
echo "❌ Coverage file not found"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload coverage badge
|
- name: Comment PR with coverage
|
||||||
continue-on-error: true
|
if: github.event.workflow_run.event == 'pull_request'
|
||||||
run: |
|
uses: marocchino/sticky-pull-request-comment@v2
|
||||||
# Optional: Update badges or notifications
|
with:
|
||||||
echo "Coverage analysis complete"
|
recreate: true
|
||||||
|
message: |
|
||||||
|
## 📊 Coverage Report
|
||||||
|
|
||||||
|
Total Coverage: **${{ steps.coverage.outputs.percentage }}%**
|
||||||
|
|
||||||
|
[View detailed coverage report](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }})
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
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@v4
|
||||||
|
|
||||||
|
- name: Dependency Review
|
||||||
|
uses: actions/dependency-review-action@v4
|
||||||
|
with:
|
||||||
|
fail-on-severity: moderate
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
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@v4
|
||||||
|
|
||||||
|
- name: Check for broken links
|
||||||
|
uses: peter-evans/link-checker@v1
|
||||||
|
with:
|
||||||
|
args: -v -r -d docs/
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Validate markdown
|
||||||
|
uses: DavidAnson/markdownlint-cli2-action@v16
|
||||||
|
with:
|
||||||
|
globs: 'docs/**/*.md'
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master, main, develop ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master, main, develop ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
golangci-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@v6
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: --timeout=5m --out-format=github-actions
|
||||||
|
|
||||||
@@ -3,8 +3,12 @@ name: Release
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*.*.*'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Release version (e.g., v1.2.3)'
|
||||||
|
required: true
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -39,20 +43,26 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@a4a2eec1d0ddf3f5835416e10cb208206f91ce91 # v5.0.0
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.23'
|
||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
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 "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
echo "Version: ${VERSION}"
|
||||||
|
|
||||||
- name: Build binaries
|
- name: Build binaries
|
||||||
env:
|
env:
|
||||||
@@ -62,7 +72,8 @@ jobs:
|
|||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ steps.version.outputs.VERSION }}
|
VERSION=${{ steps.version.outputs.VERSION }}
|
||||||
LDFLAGS="-s -w -X main.Version=${VERSION} -X main.Commit=${{ steps.version.outputs.SHORT_SHA }}"
|
SHORT_SHA=${{ steps.version.outputs.SHORT_SHA }}
|
||||||
|
LDFLAGS="-s -w -X main.Version=${VERSION} -X main.Commit=${SHORT_SHA}"
|
||||||
|
|
||||||
# Set file extension for Windows
|
# Set file extension for Windows
|
||||||
EXT=""
|
EXT=""
|
||||||
@@ -73,16 +84,16 @@ jobs:
|
|||||||
# Build all CLI tools
|
# Build all CLI tools
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
|
|
||||||
echo "Building onvif-cli..."
|
echo "🔨 Building onvif-cli..."
|
||||||
go build -ldflags="${LDFLAGS}" -o "dist/onvif-cli-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-cli
|
go build -ldflags="${LDFLAGS}" -o "dist/onvif-cli-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-cli
|
||||||
|
|
||||||
echo "Building onvif-quick..."
|
echo "🔨 Building onvif-quick..."
|
||||||
go build -ldflags="${LDFLAGS}" -o "dist/onvif-quick-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-quick
|
go build -ldflags="${LDFLAGS}" -o "dist/onvif-quick-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-quick
|
||||||
|
|
||||||
echo "Building onvif-server..."
|
echo "🔨 Building onvif-server..."
|
||||||
go build -ldflags="${LDFLAGS}" -o "dist/onvif-server-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-server
|
go build -ldflags="${LDFLAGS}" -o "dist/onvif-server-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-server
|
||||||
|
|
||||||
echo "Building onvif-diagnostics..."
|
echo "🔨 Building onvif-diagnostics..."
|
||||||
go build -ldflags="${LDFLAGS}" -o "dist/onvif-diagnostics-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-diagnostics
|
go build -ldflags="${LDFLAGS}" -o "dist/onvif-diagnostics-${{ matrix.goos }}-${{ matrix.goarch }}${EXT}" ./cmd/onvif-diagnostics
|
||||||
|
|
||||||
- name: Create archive
|
- name: Create archive
|
||||||
@@ -107,7 +118,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy documentation
|
# Copy documentation
|
||||||
cp README.md LICENSE staging/
|
cp README.md LICENSE staging/ 2>/dev/null || true
|
||||||
|
|
||||||
# Create archive from staging directory
|
# Create archive from staging directory
|
||||||
if [ "${{ matrix.goos }}" = "windows" ]; then
|
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||||
@@ -120,6 +131,8 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "✅ Created ${ARCHIVE_NAME}.tar.gz"
|
||||||
|
|
||||||
- name: Generate checksums
|
- name: Generate checksums
|
||||||
run: |
|
run: |
|
||||||
cd releases
|
cd releases
|
||||||
@@ -134,7 +147,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: release-${{ matrix.goos }}-${{ matrix.goarch }}
|
name: release-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
path: releases/*
|
path: releases/*
|
||||||
retention-days: 5
|
retention-days: 7
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Create GitHub Release
|
name: Create GitHub Release
|
||||||
@@ -142,12 +155,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@fb7b1ae3fa6edf41bfe27490ab69d8657bea0656 # v4.1.7
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: all-releases
|
path: all-releases
|
||||||
pattern: release-*
|
pattern: release-*
|
||||||
@@ -157,14 +170,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd all-releases
|
cd all-releases
|
||||||
# Combine all checksum files
|
# Combine all checksum files
|
||||||
cat checksums-*.txt > checksums.txt
|
cat checksums-*.txt > checksums.txt 2>/dev/null || true
|
||||||
# Remove individual checksum files
|
# Remove individual checksum files
|
||||||
rm checksums-*.txt
|
rm -f checksums-*.txt
|
||||||
|
|
||||||
- name: Get version and changelog
|
- name: Get version and changelog
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
VERSION=${GITHUB_REF#refs/tags/}
|
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 "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Generate changelog from commits since last tag
|
# Generate changelog from commits since last tag
|
||||||
@@ -174,21 +191,22 @@ jobs:
|
|||||||
git log --pretty=format:"- %s (%h)" ${PREV_TAG}..HEAD >> $GITHUB_OUTPUT
|
git log --pretty=format:"- %s (%h)" ${PREV_TAG}..HEAD >> $GITHUB_OUTPUT
|
||||||
echo "" >> $GITHUB_OUTPUT
|
echo "" >> $GITHUB_OUTPUT
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "CHANGELOG=Initial release" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
uses: softprops/action-gh-release@d4c6436acb972979c89d42d294e19ddc00bdef6e # v2.0.1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: all-releases/*
|
files: all-releases/*
|
||||||
draft: true
|
draft: false
|
||||||
prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') || contains(github.ref, '-alpha') }}
|
prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') || contains(github.ref, '-alpha') }}
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
fail_on_unmatched_files: true
|
|
||||||
make_latest: true
|
make_latest: true
|
||||||
body: |
|
body: |
|
||||||
## Release ${{ steps.version.outputs.VERSION }}
|
## Release ${{ steps.version.outputs.VERSION }}
|
||||||
|
|
||||||
### Installation
|
### 📦 Installation
|
||||||
|
|
||||||
Download the appropriate binary for your platform below.
|
Download the appropriate binary for your platform below.
|
||||||
|
|
||||||
@@ -211,11 +229,11 @@ jobs:
|
|||||||
go get github.com/${{ github.repository }}@${{ steps.version.outputs.VERSION }}
|
go get github.com/${{ github.repository }}@${{ steps.version.outputs.VERSION }}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Checksums
|
### 🔐 Checksums
|
||||||
|
|
||||||
SHA256 checksums are available in `checksums.txt`
|
SHA256 checksums are available in `checksums.txt`
|
||||||
|
|
||||||
### Changes
|
### 📝 Changes
|
||||||
|
|
||||||
${{ steps.version.outputs.CHANGELOG }}
|
${{ steps.version.outputs.CHANGELOG }}
|
||||||
env:
|
env:
|
||||||
@@ -228,23 +246,16 @@ jobs:
|
|||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@2db740d56eb54d769da97c489bb369cf5d3dda6ec # v3.0.0
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa601d98bc5fc6 # v3.0.0
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@8c334bdf38b3b7d57f1a2ab4dcb89e44d874e2a2 # v3.0.0
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@8c334bdf38b3b7d57f1a2ab4dcb89e44d874e2a2 # v3.0.0
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -252,10 +263,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
id: version
|
id: version
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
run: |
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/v}
|
||||||
|
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@5176660ba9f93254eda4d16d1a0beb4e32bd5a8e # v5.0.0
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
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@v4
|
||||||
|
|
||||||
|
- name: Run Gosec Security Scanner
|
||||||
|
uses: securego/gosec@master
|
||||||
|
with:
|
||||||
|
args: '-no-fail -fmt json -out gosec-report.json ./...'
|
||||||
|
|
||||||
|
- name: Upload SARIF file
|
||||||
|
uses: github/codeql-action/upload-sarif@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
sarif_file: gosec-report.json
|
||||||
|
|
||||||
|
govulncheck:
|
||||||
|
name: Vulnerability Check (govulncheck)
|
||||||
|
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 govulncheck
|
||||||
|
run: |
|
||||||
|
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
|
govulncheck ./...
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
name: Simple Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
simple:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Echo test
|
|
||||||
run: echo "Hello from GitHub Actions"
|
|
||||||
@@ -1,34 +1,42 @@
|
|||||||
name: Extra Tests
|
name: Extended Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch: # Manual trigger only
|
workflow_dispatch: # Manual trigger
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 2 * * *' # Daily at 2 AM UTC
|
- cron: '0 2 * * 0' # Weekly on Sunday at 2 AM UTC
|
||||||
|
push:
|
||||||
|
branches: [ master, main ]
|
||||||
|
paths:
|
||||||
|
- '**.go'
|
||||||
|
- 'go.mod'
|
||||||
|
- 'go.sum'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Run tests on other Go versions as manual/scheduled job
|
# Run tests on older Go versions
|
||||||
test-older-versions:
|
test-older-versions:
|
||||||
name: Test on Go ${{ matrix.go-version }}
|
name: Test on Go ${{ matrix.go-version }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
go-version: ['1.20', '1.19']
|
go-version: ['1.20', '1.19']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@a4a2eec1d0ddf3f5835416e10cb208206f91ce91 # v5.0.0
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
|
|
||||||
- name: Cache Go modules
|
- name: Cache Go modules
|
||||||
uses: actions/cache@e5f3f4dc664b57a06a2055cfc9b80cf9f20aba75 # v4.0.1
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-${{ matrix.go-version }}-
|
${{ runner.os }}-go-${{ matrix.go-version }}-
|
||||||
@@ -38,3 +46,63 @@ jobs:
|
|||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test -v -race ./...
|
run: go test -v -race ./...
|
||||||
|
|
||||||
|
# Run benchmarks
|
||||||
|
benchmark:
|
||||||
|
name: Benchmark Tests
|
||||||
|
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: Cache Go modules
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-1.23-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-1.23-
|
||||||
|
|
||||||
|
- 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@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.23'
|
||||||
|
|
||||||
|
- name: Cache Go modules
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-1.23-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-1.23-
|
||||||
|
|
||||||
|
- name: Download dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Run tests with race detector
|
||||||
|
run: go test -race -timeout=10m ./...
|
||||||
|
|||||||
+123
-2
@@ -1,13 +1,134 @@
|
|||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
tests: true
|
||||||
|
skip-dirs:
|
||||||
|
- vendor
|
||||||
|
- testdata
|
||||||
|
skip-files:
|
||||||
|
- ".*\\.pb\\.go$"
|
||||||
|
- ".*\\.gen\\.go$"
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- errcheck
|
- errcheck
|
||||||
- govet
|
- govet
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- unused
|
- unused
|
||||||
|
- gosimple
|
||||||
|
- ineffassign
|
||||||
|
- typecheck
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- misspell
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- gocritic
|
||||||
|
- gosec
|
||||||
|
- exportloopref
|
||||||
|
- goconst
|
||||||
|
- gocyclo
|
||||||
|
- dupl
|
||||||
|
- funlen
|
||||||
|
- gocognit
|
||||||
|
- lll
|
||||||
|
- nakedret
|
||||||
|
- prealloc
|
||||||
|
- stylecheck
|
||||||
|
- whitespace
|
||||||
|
- wrapcheck
|
||||||
|
- errname
|
||||||
|
- errorlint
|
||||||
|
- exhaustive
|
||||||
|
- godot
|
||||||
|
- goerr113
|
||||||
|
- gomnd
|
||||||
|
- goprintffuncname
|
||||||
|
- nlreturn
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- rowserrcheck
|
||||||
|
- sqlclosecheck
|
||||||
|
- thelper
|
||||||
|
- tparallel
|
||||||
|
- wastedassign
|
||||||
|
|
||||||
run:
|
linters-settings:
|
||||||
timeout: 5m
|
errcheck:
|
||||||
|
check-type-assertions: true
|
||||||
|
check-blank: true
|
||||||
|
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
enable-all: true
|
||||||
|
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 15
|
||||||
|
|
||||||
|
funlen:
|
||||||
|
lines: 100
|
||||||
|
statements: 50
|
||||||
|
|
||||||
|
lll:
|
||||||
|
line-length: 120
|
||||||
|
|
||||||
|
gocritic:
|
||||||
|
enabled-tags:
|
||||||
|
- diagnostic
|
||||||
|
- experimental
|
||||||
|
- opinionated
|
||||||
|
- performance
|
||||||
|
- style
|
||||||
|
disabled-checks:
|
||||||
|
- dupImport
|
||||||
|
- ifElseChain
|
||||||
|
- octalLiteral
|
||||||
|
- whyNoLint
|
||||||
|
- wrapperFunc
|
||||||
|
|
||||||
|
gosec:
|
||||||
|
severity: medium
|
||||||
|
confidence: medium
|
||||||
|
|
||||||
|
godot:
|
||||||
|
scope: declarations
|
||||||
|
exclude:
|
||||||
|
- "^TODO:"
|
||||||
|
- "^FIXME:"
|
||||||
|
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/0x524a/onvif-go
|
||||||
|
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
# Exclude some linters from test files
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
- gosec
|
||||||
|
- funlen
|
||||||
|
- gocyclo
|
||||||
|
- gocognit
|
||||||
|
|
||||||
|
# Exclude known false positives
|
||||||
|
- text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|.*Write|.*Read|.*Printf?|.*Fprintf?) is not checked"
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
|
||||||
|
# Allow long lines in test files
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- lll
|
||||||
|
|
||||||
|
max-issues-per-linter: 50
|
||||||
|
max-same-issues: 10
|
||||||
|
exclude-use-default: false
|
||||||
|
|
||||||
output:
|
output:
|
||||||
formats:
|
formats:
|
||||||
- colored-line-number
|
- colored-line-number
|
||||||
|
print-issued-lines: true
|
||||||
|
print-linter-name: true
|
||||||
|
uniq-by-line: false
|
||||||
|
|||||||
+190
@@ -0,0 +1,190 @@
|
|||||||
|
# CI/CD Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The ONVIF Go library uses GitHub Actions for continuous integration and deployment. All workflows are located in `.github/workflows/`.
|
||||||
|
|
||||||
|
## Workflow Summary
|
||||||
|
|
||||||
|
| Workflow | Purpose | Triggers | Status |
|
||||||
|
|----------|---------|----------|--------|
|
||||||
|
| **CI** | Main CI pipeline | Push/PR to main branches | ✅ Active |
|
||||||
|
| **Test** | Extended testing | Manual/Weekly/Code changes | ✅ Active |
|
||||||
|
| **Coverage** | Coverage analysis | After CI success | ✅ Active |
|
||||||
|
| **Release** | Create releases | Tags/Manual | ✅ Active |
|
||||||
|
| **Lint** | Code linting | Push/PR | ✅ Active |
|
||||||
|
| **Security** | Security scanning | Push/PR/Weekly | ✅ Active |
|
||||||
|
| **Docs** | Documentation checks | Docs changes | ✅ Active |
|
||||||
|
| **Dependency Review** | Dependency security | PRs | ✅ Active |
|
||||||
|
|
||||||
|
## Main CI Workflow
|
||||||
|
|
||||||
|
The **CI** workflow (`ci.yml`) is the primary workflow that runs on every push and pull request.
|
||||||
|
|
||||||
|
### Jobs
|
||||||
|
|
||||||
|
1. **validate** - Quick validation (5-10 minutes)
|
||||||
|
- Code formatting check
|
||||||
|
- `go vet`
|
||||||
|
- Linting with golangci-lint
|
||||||
|
|
||||||
|
2. **test** - Primary testing (10-15 minutes)
|
||||||
|
- Runs on Go 1.23
|
||||||
|
- Race detector enabled
|
||||||
|
- Coverage report generation
|
||||||
|
- Uploads to Codecov
|
||||||
|
|
||||||
|
3. **test-matrix** - Multi-platform testing (20-30 minutes)
|
||||||
|
- Tests on Go 1.21, 1.22, 1.23
|
||||||
|
- Tests on Linux, macOS, Windows
|
||||||
|
- Parallel execution
|
||||||
|
|
||||||
|
4. **build** - Build verification (5-10 minutes)
|
||||||
|
- Builds all packages
|
||||||
|
- Builds all examples
|
||||||
|
- Builds all CLI tools
|
||||||
|
|
||||||
|
5. **sonarcloud** - Code quality (10-15 minutes)
|
||||||
|
- Only on master/main
|
||||||
|
- Requires SONAR_TOKEN secret
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- **Total CI time**: ~40-60 minutes (parallel jobs)
|
||||||
|
- **Fast feedback**: Validation job fails fast on formatting/lint issues
|
||||||
|
- **Caching**: Go modules and build cache for faster runs
|
||||||
|
|
||||||
|
## Release Workflow
|
||||||
|
|
||||||
|
The **Release** workflow (`release.yml`) creates GitHub releases with binaries for all platforms.
|
||||||
|
|
||||||
|
### Supported Platforms
|
||||||
|
|
||||||
|
- **Linux**: amd64, arm64, arm (v7)
|
||||||
|
- **Windows**: amd64, arm64
|
||||||
|
- **macOS**: amd64, arm64
|
||||||
|
|
||||||
|
### Release Process
|
||||||
|
|
||||||
|
1. **Tag creation**: Push a tag like `v1.2.3`
|
||||||
|
2. **Build**: Automatically builds for all platforms
|
||||||
|
3. **Archive**: Creates `.tar.gz` (Linux/macOS) and `.zip` (Windows)
|
||||||
|
4. **Checksums**: Generates SHA256 checksums
|
||||||
|
5. **Release**: Creates GitHub release with all artifacts
|
||||||
|
6. **Docker**: Builds and pushes multi-arch Docker image to GHCR
|
||||||
|
|
||||||
|
### Manual Release
|
||||||
|
|
||||||
|
You can also trigger a release manually:
|
||||||
|
1. Go to Actions → Release workflow
|
||||||
|
2. Click "Run workflow"
|
||||||
|
3. Enter version (e.g., `v1.2.3`)
|
||||||
|
|
||||||
|
## Security Workflow
|
||||||
|
|
||||||
|
The **Security** workflow (`security.yml`) scans for vulnerabilities.
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
|
- **gosec**: Security scanner for Go code
|
||||||
|
- **govulncheck**: Vulnerability checker for dependencies
|
||||||
|
|
||||||
|
### Schedule
|
||||||
|
|
||||||
|
Runs weekly on Sundays to catch new vulnerabilities.
|
||||||
|
|
||||||
|
## Coverage
|
||||||
|
|
||||||
|
Coverage is tracked and reported to Codecov. The coverage workflow provides detailed analysis:
|
||||||
|
|
||||||
|
- Total coverage percentage
|
||||||
|
- Coverage by package
|
||||||
|
- Coverage trends over time
|
||||||
|
|
||||||
|
### Coverage Threshold
|
||||||
|
|
||||||
|
Minimum coverage threshold: **50%**
|
||||||
|
|
||||||
|
## Required Secrets
|
||||||
|
|
||||||
|
### Optional Secrets
|
||||||
|
|
||||||
|
- `CODECOV_TOKEN` - For Codecov integration
|
||||||
|
- `SONAR_TOKEN` - For SonarCloud integration
|
||||||
|
- `DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN` - For Docker Hub
|
||||||
|
|
||||||
|
## Workflow Status Badges
|
||||||
|
|
||||||
|
Add these badges to your README:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Always run CI locally first**: `make check test`
|
||||||
|
2. **Keep workflows fast**: Use caching and parallel jobs
|
||||||
|
3. **Fail fast**: Validation job catches issues early
|
||||||
|
4. **Test before release**: All tests must pass before tagging
|
||||||
|
5. **Review security scans**: Check security workflow results
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### CI Fails on Formatting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fix formatting
|
||||||
|
make fmt
|
||||||
|
|
||||||
|
# Or manually
|
||||||
|
gofmt -w .
|
||||||
|
```
|
||||||
|
|
||||||
|
### CI Fails on Linting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run linter locally
|
||||||
|
make lint
|
||||||
|
|
||||||
|
# Or manually
|
||||||
|
golangci-lint run ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests Fail Locally but Pass in CI
|
||||||
|
|
||||||
|
- Check Go version: CI uses Go 1.23
|
||||||
|
- Check race detector: CI runs with `-race`
|
||||||
|
- Check environment differences
|
||||||
|
|
||||||
|
### Release Fails
|
||||||
|
|
||||||
|
- Ensure tag format: `v1.2.3` (not `1.2.3`)
|
||||||
|
- Check permissions: Need `contents: write`
|
||||||
|
- Verify all tests pass before tagging
|
||||||
|
|
||||||
|
## Workflow Files
|
||||||
|
|
||||||
|
All workflow files are in `.github/workflows/`:
|
||||||
|
|
||||||
|
- `ci.yml` - Main CI pipeline
|
||||||
|
- `test.yml` - Extended tests
|
||||||
|
- `coverage.yml` - Coverage analysis
|
||||||
|
- `release.yml` - Release automation
|
||||||
|
- `lint.yml` - Linting
|
||||||
|
- `security.yml` - Security scanning
|
||||||
|
- `docs.yml` - Documentation checks
|
||||||
|
- `dependency-review.yml` - Dependency review
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||||
|
- [Workflow README](../.github/workflows/README.md)
|
||||||
|
- [Makefile](../Makefile) - Local development commands
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last Updated: December 2, 2025*
|
||||||
|
|
||||||
Reference in New Issue
Block a user