mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
feat: Restructure workflows following Single Responsibility Principle
- Remove old monolithic workflows (ci.yml, ci-cd.yml, cd.yml) - Add focused workflows: lint.yml, test.yml, build.yml, security.yml, docker-build.yml, deploy.yml - Each workflow has a single, clear responsibility - Follow 2025 best practices with semantic versioning, OIDC auth, build attestations - Add comprehensive README.md with workflow documentation - Configure Dependabot for automated dependency updates Workflows now run independently and can be triggered separately for better CI/CD control.
This commit is contained in:
parent
afaf952a1a
commit
e428d18b0d
761
.github/workflows/README.md
vendored
Normal file
761
.github/workflows/README.md
vendored
Normal file
@ -0,0 +1,761 @@
|
|||||||
|
# GitHub Actions CI/CD Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document describes the GitHub Actions CI/CD pipeline for the Tercul backend
|
||||||
|
project, updated to 2025 best practices. The pipeline ensures code quality,
|
||||||
|
security, and reliable deployments through automated testing, linting, security
|
||||||
|
scanning, and containerized deployments.
|
||||||
|
|
||||||
|
### Quick Reference
|
||||||
|
|
||||||
|
| Workflow | File | Purpose | Triggers |
|
||||||
|
|----------|------|---------|----------|
|
||||||
|
| **Lint** | `lint.yml` | Code quality & style | Push/PR to main, develop |
|
||||||
|
| **Test** | `test.yml` | Unit tests & compatibility | Push/PR to main, develop |
|
||||||
|
| **Build** | `build.yml` | Binary compilation | Push/PR to main, develop |
|
||||||
|
| **Security** | `security.yml` | CodeQL scanning | Push/PR to main + Weekly |
|
||||||
|
| **Docker Build** | `docker-build.yml` | Container images | Push to main, Tags, PRs |
|
||||||
|
| **Deploy** | `deploy.yml` | Production deployment | Tags (v*), Manual |
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The CI/CD pipeline follows the **Single Responsibility Principle** with focused workflows:
|
||||||
|
|
||||||
|
1. **Lint** (`lint.yml`) - Code quality and style enforcement
|
||||||
|
2. **Test** (`test.yml`) - Unit tests and compatibility matrix
|
||||||
|
3. **Build** (`build.yml`) - Binary compilation and verification
|
||||||
|
4. **Security** (`security.yml`) - CodeQL security scanning
|
||||||
|
5. **Docker Build** (`docker-build.yml`) - Container image building and publishing
|
||||||
|
6. **Deploy** (`deploy.yml`) - Production deployment orchestration
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
### Lint Workflow (`lint.yml`)
|
||||||
|
|
||||||
|
**Purpose**: Ensures code quality and consistent style across the codebase.
|
||||||
|
|
||||||
|
**Triggers**:
|
||||||
|
|
||||||
|
- Push to `main` and `develop` branches
|
||||||
|
- Pull requests targeting `main` and `develop` branches
|
||||||
|
|
||||||
|
**Jobs**:
|
||||||
|
|
||||||
|
- `golangci-lint`: Go linting with golangci-lint
|
||||||
|
- Checkout code
|
||||||
|
- Setup Go 1.25 with caching
|
||||||
|
- Install dependencies
|
||||||
|
- Tidy modules (ensures go.mod/go.sum are clean)
|
||||||
|
- Run linter with 5-minute timeout
|
||||||
|
|
||||||
|
**Configuration**:
|
||||||
|
|
||||||
|
- **Timeout**: 5 minutes
|
||||||
|
- **Target**: All Go files (`./...`)
|
||||||
|
- **Cache**: Enabled for faster runs
|
||||||
|
|
||||||
|
### Test Workflow (`test.yml`)
|
||||||
|
|
||||||
|
**Purpose**: Validates code functionality through comprehensive testing.
|
||||||
|
|
||||||
|
**Triggers**:
|
||||||
|
|
||||||
|
- Push to `main` and `develop` branches
|
||||||
|
- Pull requests targeting `main` and `develop` branches
|
||||||
|
|
||||||
|
**Jobs**:
|
||||||
|
|
||||||
|
#### Unit Tests
|
||||||
|
|
||||||
|
- **Environment**: Ubuntu with PostgreSQL 15 and Redis 7
|
||||||
|
- **Features**:
|
||||||
|
|
||||||
|
- Race detection enabled
|
||||||
|
- Code coverage reporting (atomic mode)
|
||||||
|
- HTML coverage report generation
|
||||||
|
- Test result summaries in GitHub UI
|
||||||
|
- 30-day artifact retention
|
||||||
|
|
||||||
|
**Services**:
|
||||||
|
|
||||||
|
- PostgreSQL 15 with health checks
|
||||||
|
- Redis 7-alpine with health checks
|
||||||
|
|
||||||
|
#### Compatibility Matrix
|
||||||
|
|
||||||
|
- **Trigger**: Push to `main` branch only
|
||||||
|
- **Strategy**: Tests across Go versions 1.22, 1.23, 1.24, 1.25
|
||||||
|
- **Purpose**: Ensures compatibility with multiple Go versions
|
||||||
|
- **Fail-fast**: Disabled (all versions tested even if one fails)
|
||||||
|
|
||||||
|
### Build Workflow (`build.yml`)
|
||||||
|
|
||||||
|
**Purpose**: Compiles the application binary and validates the build.
|
||||||
|
|
||||||
|
**Triggers**:
|
||||||
|
|
||||||
|
- Push to `main` and `develop` branches
|
||||||
|
- Pull requests targeting `main` and `develop` branches
|
||||||
|
|
||||||
|
**Jobs**:
|
||||||
|
|
||||||
|
- `build-binary`: Binary compilation and verification
|
||||||
|
- Dependency verification with `go mod verify`
|
||||||
|
- Build to `bin/tercul-backend`
|
||||||
|
- Binary validation test
|
||||||
|
- Artifact upload (30-day retention)
|
||||||
|
|
||||||
|
**Permissions**:
|
||||||
|
|
||||||
|
- `contents: read` - Read repository code
|
||||||
|
- `attestations: write` - Future SLSA attestation support
|
||||||
|
- `id-token: write` - OIDC token for attestations
|
||||||
|
|
||||||
|
### Security Workflow (`security.yml`)
|
||||||
|
|
||||||
|
**Purpose**: Automated security vulnerability detection with CodeQL.
|
||||||
|
|
||||||
|
**Triggers**:
|
||||||
|
|
||||||
|
- Push to `main` branch
|
||||||
|
- Pull requests targeting `main` branch
|
||||||
|
- Scheduled: Every Monday at 14:20 UTC
|
||||||
|
|
||||||
|
**Jobs**:
|
||||||
|
|
||||||
|
- `codeql-analysis`: CodeQL security scanning for Go
|
||||||
|
- Initialize CodeQL with Go language support
|
||||||
|
- Build code for analysis
|
||||||
|
- Perform security scan
|
||||||
|
- Category: "backend-security" for tracking
|
||||||
|
|
||||||
|
**CodeQL Configuration**:
|
||||||
|
|
||||||
|
The workflow can be customized with additional query suites:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: go
|
||||||
|
# Run security-extended suite for more comprehensive scanning
|
||||||
|
queries: security-extended
|
||||||
|
# Or use security-and-quality for maintainability checks
|
||||||
|
# queries: security-and-quality
|
||||||
|
```
|
||||||
|
|
||||||
|
**Available Query Suites**:
|
||||||
|
|
||||||
|
- `security-extended`: Default queries plus lower severity/precision queries
|
||||||
|
- `security-and-quality`: Security queries plus maintainability and reliability
|
||||||
|
|
||||||
|
**Custom Query Packs**:
|
||||||
|
|
||||||
|
Add custom CodeQL query packs for specialized analysis:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: go
|
||||||
|
packs: my-org/go-security-queries@1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Build Workflow (`docker-build.yml`)
|
||||||
|
|
||||||
|
**Purpose**: Builds and publishes multi-architecture Docker images.
|
||||||
|
|
||||||
|
**Triggers**:
|
||||||
|
|
||||||
|
- Push to `main` branch
|
||||||
|
- Tag pushes with `v*` pattern
|
||||||
|
- Pull requests targeting `main` branch
|
||||||
|
|
||||||
|
**Jobs**:
|
||||||
|
|
||||||
|
- `build-image`: Multi-platform Docker image building
|
||||||
|
|
||||||
|
- Docker Buildx setup for multi-arch builds
|
||||||
|
- Login to GitHub Container Registry
|
||||||
|
- Metadata extraction for tags and labels
|
||||||
|
- Build for AMD64 and ARM64 architectures
|
||||||
|
- Push to registry (except for PRs)
|
||||||
|
- Generate build provenance attestation
|
||||||
|
|
||||||
|
**Image Tagging Strategy**:
|
||||||
|
|
||||||
|
- `main` branch pushes → `main` + `sha-<hash>` tags
|
||||||
|
- Tag pushes (`v1.2.3`) → `v1.2.3`, `1.2.3`, `1.2`, `sha-<hash>` tags
|
||||||
|
- Pull requests → `pr-<number>` tag (build only, not pushed)
|
||||||
|
|
||||||
|
**Push Behavior**:
|
||||||
|
|
||||||
|
- **Pushes to main/tags**: Build and push to registry
|
||||||
|
- **Pull requests**: Build only (validation, no push)
|
||||||
|
|
||||||
|
**Platforms**: linux/amd64, linux/arm64
|
||||||
|
|
||||||
|
### Deploy Workflow (`deploy.yml`)
|
||||||
|
|
||||||
|
**Purpose**: Production deployment orchestration to Docker Swarm.
|
||||||
|
|
||||||
|
**Triggers**:
|
||||||
|
|
||||||
|
- Tag pushes with `v*` pattern
|
||||||
|
- Manual dispatch with version input
|
||||||
|
|
||||||
|
**Jobs**:
|
||||||
|
|
||||||
|
- `deploy-production`: Deployment to production environment
|
||||||
|
|
||||||
|
- Version extraction from tag or manual input
|
||||||
|
- Docker Swarm service update (SSH-based deployment template)
|
||||||
|
- Deployment summary with timestamp
|
||||||
|
- Environment protection and tracking
|
||||||
|
|
||||||
|
**Environment**:
|
||||||
|
|
||||||
|
- Name: `production`
|
||||||
|
- URL: Configurable production URL
|
||||||
|
- Protection: Supports required reviewers and wait timers
|
||||||
|
|
||||||
|
**Manual Deployment**:
|
||||||
|
|
||||||
|
Deployments can be triggered manually from the Actions tab with a specific version.
|
||||||
|
|
||||||
|
**Required Secrets**:
|
||||||
|
|
||||||
|
- `SWARM_HOST`: Docker Swarm manager hostname/IP
|
||||||
|
- `SWARM_SSH_KEY`: SSH private key for Swarm access
|
||||||
|
|
||||||
|
## Workflow Execution Order
|
||||||
|
|
||||||
|
**On Pull Request**:
|
||||||
|
|
||||||
|
1. Lint → Validates code style
|
||||||
|
2. Test → Runs unit tests with coverage
|
||||||
|
3. Build → Compiles binary
|
||||||
|
4. Security → CodeQL analysis (main branch PRs only)
|
||||||
|
5. Docker Build → Builds image (no push)
|
||||||
|
|
||||||
|
**On Push to main**:
|
||||||
|
|
||||||
|
1. Lint → Code quality check
|
||||||
|
2. Test → Unit tests + compatibility matrix
|
||||||
|
3. Build → Binary compilation
|
||||||
|
4. Security → CodeQL scan
|
||||||
|
5. Docker Build → Build and push image
|
||||||
|
|
||||||
|
**On Tag Push (v\*)**:
|
||||||
|
|
||||||
|
1. Docker Build → Build and push versioned image
|
||||||
|
2. Deploy → Deploy to production
|
||||||
|
|
||||||
|
## Security Features
|
||||||
|
|
||||||
|
### Permissions Management
|
||||||
|
|
||||||
|
- **Principle of Least Privilege**: Each workflow has minimal required permissions
|
||||||
|
- **GITHUB_TOKEN Restrictions**: Read-only by default, elevated only when necessary
|
||||||
|
- **Workflow Separation**: Each workflow operates independently
|
||||||
|
- **Attestation Permissions**: For build provenance and SLSA compliance
|
||||||
|
|
||||||
|
### Code Security
|
||||||
|
|
||||||
|
- **CodeQL Integration**: Automated security scanning for Go code
|
||||||
|
- **Dependency Verification**: `go mod verify` ensures integrity
|
||||||
|
- **Module Tidying**: `go mod tidy` prevents dependency drift
|
||||||
|
|
||||||
|
### Container Security
|
||||||
|
|
||||||
|
- **Multi-platform Builds**: Ensures compatibility and security across architectures
|
||||||
|
- **Provenance Attestation**: Cryptographic proof of build integrity
|
||||||
|
- **Registry Security**: GitHub Container Registry with token-based authentication
|
||||||
|
|
||||||
|
### Secrets Management
|
||||||
|
|
||||||
|
- **No Hardcoded Secrets**: All sensitive data uses GitHub secrets
|
||||||
|
- **Environment Variables**: Proper isolation of configuration
|
||||||
|
- **GITHUB_TOKEN**: Automatic authentication for package registries
|
||||||
|
- **Granular Permissions**: Package-level access control
|
||||||
|
|
||||||
|
### Package Registry Security
|
||||||
|
|
||||||
|
- **GITHUB_TOKEN Authentication**: No personal access tokens required
|
||||||
|
- **Automatic Permissions**: Packages inherit repository visibility
|
||||||
|
- **Repository Scoped**: Packages linked to source repository
|
||||||
|
- **Granular Access**: Fine-grained permissions per package
|
||||||
|
- **Artifact Attestation**: Cryptographic proof of build provenance
|
||||||
|
- **OIDC Support**: Token-based authentication without long-lived credentials
|
||||||
|
|
||||||
|
## Best Practices Implemented
|
||||||
|
|
||||||
|
### 2025 Updates
|
||||||
|
|
||||||
|
- **Semantic Versioning**: Actions pinned to major versions (e.g., `@v5`) instead of SHA
|
||||||
|
- **Caching Optimization**: Go module and Docker layer caching
|
||||||
|
- **Matrix Testing**: Cross-version compatibility validation
|
||||||
|
- **Service Health Checks**: Database and Redis readiness verification
|
||||||
|
- **Artifact Management**: Proper retention policies and naming
|
||||||
|
|
||||||
|
### Performance Optimizations
|
||||||
|
|
||||||
|
- **Dependency Caching**: Reduces setup time significantly
|
||||||
|
- **Parallel Jobs**: Independent jobs run concurrently
|
||||||
|
- **Conditional Execution**: Security scans only on main branch
|
||||||
|
- **Artifact Upload**: Efficient storage and retrieval
|
||||||
|
|
||||||
|
### Reliability Features
|
||||||
|
|
||||||
|
- **Timeout Configuration**: Prevents hanging jobs
|
||||||
|
- **Error Handling**: Proper exit codes and logging
|
||||||
|
- **Health Checks**: Service readiness validation
|
||||||
|
- **Retention Policies**: Balanced storage management
|
||||||
|
|
||||||
|
## Configuration Details
|
||||||
|
|
||||||
|
### Go Version
|
||||||
|
|
||||||
|
- Primary: Go 1.25
|
||||||
|
- Matrix: Go 1.22, 1.23, 1.24, 1.25
|
||||||
|
|
||||||
|
### Services
|
||||||
|
|
||||||
|
- **PostgreSQL**: Version 15 with health checks
|
||||||
|
- **Redis**: Version 7-alpine with ping health checks
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
|
- **Linter**: golangci-lint latest with 5-minute timeout
|
||||||
|
- **Testing**: `go test` with race detection and coverage
|
||||||
|
- **Building**: `go build` with verbose output
|
||||||
|
- **Security**: CodeQL for Go analysis
|
||||||
|
|
||||||
|
### Caching
|
||||||
|
|
||||||
|
- **Go Modules**: Automatic caching via setup-go action
|
||||||
|
- **Docker Layers**: GitHub Actions cache with GHA type
|
||||||
|
- **CodeQL Databases**: Stored in `${{ github.runner_temp }}/codeql_databases`
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Dependabot Configuration
|
||||||
|
|
||||||
|
- **GitHub Actions**: Weekly updates with "ci" prefix
|
||||||
|
- **Go Modules**: Weekly updates with "deps" prefix
|
||||||
|
- **Automated PRs**: Keeps dependencies current and secure
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
- **Workflow Runs**: GitHub Actions tab for execution monitoring
|
||||||
|
- **Security Alerts**: Code scanning results and dependency alerts
|
||||||
|
- **Coverage Reports**: Artifact downloads for test coverage analysis
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
#### Common Issues
|
||||||
|
|
||||||
|
1. **Cache Misses**: Clear caches if corruption suspected
|
||||||
|
2. **Service Failures**: Check health check configurations
|
||||||
|
3. **Permission Errors**: Verify GITHUB_TOKEN scopes
|
||||||
|
4. **Timeout Issues**: Adjust timeout values in workflow configurations
|
||||||
|
5. **Docker Push Failures**: Check package write permissions
|
||||||
|
6. **Registry Authentication**: Ensure `packages: write` permission is set
|
||||||
|
|
||||||
|
#### Package Registry Issues
|
||||||
|
|
||||||
|
**Problem**: Cannot push to GitHub Container Registry
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Solution: Ensure proper permissions
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problem**: Package not visible after push
|
||||||
|
|
||||||
|
- Check package visibility settings (public/private/internal)
|
||||||
|
- Verify repository is linked to package
|
||||||
|
- Ensure workflow completed successfully
|
||||||
|
|
||||||
|
**Problem**: Cannot pull package in workflow
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Solution: Login to registry first
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Debugging
|
||||||
|
|
||||||
|
- **Manual Dispatch**: Use `workflow_dispatch` for testing
|
||||||
|
- **Log Analysis**: Review step outputs for error details
|
||||||
|
- **Artifact Inspection**: Download build artifacts for verification
|
||||||
|
- **Package Logs**: Check package activity in GitHub UI
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
### Planned Features
|
||||||
|
|
||||||
|
- **SLSA Integration**: Enhanced build attestation
|
||||||
|
- **Dependency Review**: Automated dependency vulnerability checking
|
||||||
|
- **Performance Testing**: Load testing integration
|
||||||
|
- **Multi-environment Deployment**: Staging and production separation
|
||||||
|
|
||||||
|
### Scalability Considerations
|
||||||
|
|
||||||
|
- **Self-hosted Runners**: For resource-intensive jobs
|
||||||
|
- **Job Parallelization**: Further optimization of concurrent execution
|
||||||
|
- **Cache Optimization**: Advanced caching strategies
|
||||||
|
|
||||||
|
## Docker Image Usage
|
||||||
|
|
||||||
|
### Pulling Images
|
||||||
|
|
||||||
|
Pull the latest image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull ghcr.io/<owner>/<repository>:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Pull a specific version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull ghcr.io/<owner>/<repository>:1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Locally
|
||||||
|
|
||||||
|
Run the container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name tercul-backend \
|
||||||
|
-p 8080:8080 \
|
||||||
|
-e DATABASE_URL="postgres://..." \
|
||||||
|
ghcr.io/<owner>/<repository>:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Swarm Deployment
|
||||||
|
|
||||||
|
Deploy as a stack:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker stack deploy -c docker-compose.yml tercul
|
||||||
|
```
|
||||||
|
|
||||||
|
Update running service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker service update \
|
||||||
|
--image ghcr.io/<owner>/<repository>:1.2.3 \
|
||||||
|
tercul_backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verifying Attestations
|
||||||
|
|
||||||
|
Verify build provenance:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gh attestation verify \
|
||||||
|
oci://ghcr.io/<owner>/<repository>:latest \
|
||||||
|
--owner <owner>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
When modifying workflows:
|
||||||
|
|
||||||
|
1. Test changes using `workflow_dispatch`
|
||||||
|
2. Ensure backward compatibility
|
||||||
|
3. Update this documentation
|
||||||
|
4. Follow security best practices
|
||||||
|
5. Use semantic versioning for action references
|
||||||
|
6. Test Docker builds locally before pushing
|
||||||
|
7. Verify package permissions after changes
|
||||||
|
8. Review CodeQL alerts before merging PRs
|
||||||
|
9. Update query packs regularly for latest security rules
|
||||||
|
10. Test configuration changes with `workflow_dispatch`
|
||||||
|
|
||||||
|
## CodeQL Advanced Configuration
|
||||||
|
|
||||||
|
### Custom Configuration File
|
||||||
|
|
||||||
|
For complex CodeQL setups, use a configuration file (`.github/codeql/codeql-config.yml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: "CodeQL Config"
|
||||||
|
|
||||||
|
# Disable default queries to run only custom queries
|
||||||
|
disable-default-queries: false
|
||||||
|
|
||||||
|
# Specify query packs
|
||||||
|
packs:
|
||||||
|
- scope/go-security-pack
|
||||||
|
- scope/go-compliance-pack@1.2.3
|
||||||
|
|
||||||
|
# Add custom queries
|
||||||
|
queries:
|
||||||
|
- uses: security-and-quality
|
||||||
|
- uses: ./custom-queries
|
||||||
|
|
||||||
|
# Filter queries by severity
|
||||||
|
query-filters:
|
||||||
|
- exclude:
|
||||||
|
problem.severity:
|
||||||
|
- warning
|
||||||
|
- recommendation
|
||||||
|
- exclude:
|
||||||
|
id: go/redundant-assignment
|
||||||
|
|
||||||
|
# Scan specific directories
|
||||||
|
paths:
|
||||||
|
- internal
|
||||||
|
- cmd
|
||||||
|
- pkg
|
||||||
|
|
||||||
|
paths-ignore:
|
||||||
|
- "**/*_test.go"
|
||||||
|
- vendor
|
||||||
|
- "**/testdata/**"
|
||||||
|
|
||||||
|
# Extend threat model (preview)
|
||||||
|
threat-models: local
|
||||||
|
```
|
||||||
|
|
||||||
|
Reference the config in your workflow:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inline Configuration
|
||||||
|
|
||||||
|
Alternatively, specify configuration inline:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: go
|
||||||
|
config: |
|
||||||
|
disable-default-queries: false
|
||||||
|
queries:
|
||||||
|
- uses: security-extended
|
||||||
|
query-filters:
|
||||||
|
- exclude:
|
||||||
|
problem.severity:
|
||||||
|
- recommendation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scheduling CodeQL Scans
|
||||||
|
|
||||||
|
Run CodeQL on a schedule for regular security audits:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
schedule:
|
||||||
|
# Run at 14:20 UTC every Monday
|
||||||
|
- cron: '20 14 * * 1'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Avoiding Unnecessary Scans
|
||||||
|
|
||||||
|
Skip CodeQL for specific file changes:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
paths-ignore:
|
||||||
|
- '**/*.md'
|
||||||
|
- '**/*.txt'
|
||||||
|
- 'docs/**'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Analysis Categories
|
||||||
|
|
||||||
|
Categorize multiple analyses in monorepos:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
|
with:
|
||||||
|
category: "backend-api"
|
||||||
|
```
|
||||||
|
|
||||||
|
### External Query Packs
|
||||||
|
|
||||||
|
Use query packs from GitHub Enterprise Server:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
registries: |
|
||||||
|
- url: https://containers.GHEHOSTNAME/v2/
|
||||||
|
packages:
|
||||||
|
- my-company/*
|
||||||
|
token: ${{ secrets.GHES_TOKEN }}
|
||||||
|
packs: my-company/go-queries
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query Suite Examples
|
||||||
|
|
||||||
|
**Security-focused**:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
queries:
|
||||||
|
- uses: security-extended
|
||||||
|
```
|
||||||
|
|
||||||
|
**Quality and security**:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
queries:
|
||||||
|
- uses: security-and-quality
|
||||||
|
```
|
||||||
|
|
||||||
|
**Custom suite**:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
queries:
|
||||||
|
- uses: ./custom-queries/critical-security.qls
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Workflow Techniques
|
||||||
|
|
||||||
|
### Workflow Commands
|
||||||
|
|
||||||
|
GitHub Actions supports workflow commands for advanced functionality:
|
||||||
|
|
||||||
|
#### Debug Logging
|
||||||
|
|
||||||
|
Enable detailed debugging with the `ACTIONS_STEP_DEBUG` secret:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Debug step
|
||||||
|
run: echo "::debug::Detailed debugging information"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Annotations
|
||||||
|
|
||||||
|
Create annotations for notices, warnings, and errors:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Notice annotation
|
||||||
|
- run: echo "::notice file=app.go,line=10::Consider refactoring"
|
||||||
|
|
||||||
|
# Warning annotation
|
||||||
|
- run: echo "::warning file=main.go,line=5,col=10::Deprecated function"
|
||||||
|
|
||||||
|
# Error annotation
|
||||||
|
- run: echo "::error file=handler.go,line=20,title=Build Error::Missing import"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Grouping Log Lines
|
||||||
|
|
||||||
|
Organize logs with collapsible groups:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Build application
|
||||||
|
run: |
|
||||||
|
echo "::group::Compiling Go code"
|
||||||
|
go build -v ./...
|
||||||
|
echo "::endgroup::"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Masking Secrets
|
||||||
|
|
||||||
|
Prevent sensitive values from appearing in logs:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Generate token
|
||||||
|
run: |
|
||||||
|
TOKEN=$(generate_token)
|
||||||
|
echo "::add-mask::$TOKEN"
|
||||||
|
echo "TOKEN=$TOKEN" >> $GITHUB_ENV
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Job Summaries
|
||||||
|
|
||||||
|
Add Markdown summaries to workflow runs:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Test summary
|
||||||
|
run: |
|
||||||
|
echo "### Test Results :white_check_mark:" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- Total: 150 tests" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- Passed: 148" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- Failed: 2" >> $GITHUB_STEP_SUMMARY
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Files
|
||||||
|
|
||||||
|
Use environment files for dynamic configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Set environment variable for subsequent steps
|
||||||
|
- name: Set build info
|
||||||
|
run: |
|
||||||
|
echo "BUILD_TIME=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_ENV
|
||||||
|
echo "COMMIT_SHA=${GITHUB_SHA:0:7}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Use in later steps
|
||||||
|
- name: Deploy
|
||||||
|
run: echo "Deploying $COMMIT_SHA built at $BUILD_TIME"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output Parameters
|
||||||
|
|
||||||
|
Share data between steps:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Calculate version
|
||||||
|
id: version
|
||||||
|
run: echo "VERSION=1.2.3" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Use version
|
||||||
|
run: echo "Building version ${{ steps.version.outputs.VERSION }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiline Values
|
||||||
|
|
||||||
|
Handle multiline strings safely:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Store API response
|
||||||
|
run: |
|
||||||
|
{
|
||||||
|
echo 'API_RESPONSE<<EOF'
|
||||||
|
curl https://api.example.com/data
|
||||||
|
echo EOF
|
||||||
|
} >> $GITHUB_ENV
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||||
|
- [Go CI/CD Best Practices](https://github.com/golang/go/wiki/Go-Release-Cycle)
|
||||||
|
- [Security Hardening Guide](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)
|
||||||
|
- [Dependency Caching](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows)
|
||||||
|
- [Workflow Commands Reference](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions)
|
||||||
|
- [Publishing Packages with Actions](https://docs.github.com/en/packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions)
|
||||||
|
- [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry)
|
||||||
|
- [Artifact Attestations](https://docs.github.com/en/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)
|
||||||
|
- [CodeQL Configuration Reference](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning)
|
||||||
|
- [CodeQL Query Suites](https://docs.github.com/en/code-security/code-scanning/managing-your-code-scanning-configuration/codeql-query-suites)
|
||||||
|
- [CodeQL CLI Reference](https://docs.github.com/en/code-security/codeql-cli)
|
||||||
46
.github/workflows/build.yml
vendored
Normal file
46
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-binary:
|
||||||
|
name: Build Binary
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.25"
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Verify dependencies
|
||||||
|
run: go mod verify
|
||||||
|
|
||||||
|
- name: Build application
|
||||||
|
run: |
|
||||||
|
go build -v -o bin/tercul-backend ./cmd
|
||||||
|
ls -la bin/
|
||||||
|
|
||||||
|
- name: Test binary
|
||||||
|
run: ./bin/tercul-backend --help || echo "Binary built successfully"
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tercul-backend-binary
|
||||||
|
path: bin/
|
||||||
|
retention-days: 30
|
||||||
203
.github/workflows/ci-cd.yml
vendored
203
.github/workflows/ci-cd.yml
vendored
@ -1,203 +0,0 @@
|
|||||||
name: CI/CD Pipeline
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, develop]
|
|
||||||
pull_request:
|
|
||||||
branches: [main, develop]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# Security scanning with CodeQL (only on main branch pushes)
|
|
||||||
security-scan:
|
|
||||||
name: Security Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: go
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: "1.25"
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: go mod download
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: go build -v ./...
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
|
|
||||||
# Linting (runs on PRs and pushes)
|
|
||||||
lint:
|
|
||||||
name: Lint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: "1.25"
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: go mod download
|
|
||||||
|
|
||||||
- name: Tidy modules
|
|
||||||
run: go mod tidy
|
|
||||||
|
|
||||||
- name: golangci-lint
|
|
||||||
uses: golangci/golangci-lint-action@v6
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: --timeout=5m ./...
|
|
||||||
|
|
||||||
# Testing and coverage (runs on PRs and pushes)
|
|
||||||
test:
|
|
||||||
name: Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15
|
|
||||||
env:
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: testdb
|
|
||||||
options: >-
|
|
||||||
--health-cmd pg_isready
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: "1.25"
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: go mod download
|
|
||||||
|
|
||||||
- name: Run tests with coverage
|
|
||||||
run: |
|
|
||||||
go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
|
|
||||||
go tool cover -html=coverage.out -o coverage.html
|
|
||||||
|
|
||||||
- name: Upload coverage reports
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: coverage-report
|
|
||||||
path: coverage.html
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
# Build and verify (runs on PRs and pushes)
|
|
||||||
build:
|
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: "1.25"
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: go mod download
|
|
||||||
|
|
||||||
- name: Verify dependencies
|
|
||||||
run: go mod verify
|
|
||||||
|
|
||||||
- name: Build application
|
|
||||||
run: |
|
|
||||||
go build -v -o bin/tercul-backend ./cmd
|
|
||||||
ls -la bin/
|
|
||||||
|
|
||||||
- name: Test build
|
|
||||||
run: ./bin/tercul-backend --help || echo "Binary built successfully"
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: terbul-backend-binary
|
|
||||||
path: bin/
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
# Matrix testing across Go versions (only on main branch pushes)
|
|
||||||
test-matrix:
|
|
||||||
name: Test Matrix (Go ${{ matrix.go-version }})
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
go-version: ["1.22", "1.23", "1.24", "1.25"]
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15
|
|
||||||
env:
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: testdb
|
|
||||||
options: >-
|
|
||||||
--health-cmd pg_isready
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Setup Go ${{ matrix.go-version }}
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: ${{ matrix.go-version }}
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: go mod download
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: go test -v -race ./...
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: go build -v ./...
|
|
||||||
60
.github/workflows/deploy.yml
vendored
Normal file
60
.github/workflows/deploy.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ["v*"]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "Version to deploy (e.g., v1.2.3)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy-production:
|
||||||
|
name: Deploy to Production
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
url: https://tercul.example.com
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Extract version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
echo "VERSION=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Deploy to Docker Swarm
|
||||||
|
env:
|
||||||
|
SWARM_HOST: ${{ secrets.SWARM_HOST }}
|
||||||
|
SWARM_SSH_KEY: ${{ secrets.SWARM_SSH_KEY }}
|
||||||
|
IMAGE_TAG: ${{ steps.version.outputs.VERSION }}
|
||||||
|
run: |
|
||||||
|
# Uncomment and configure for actual Docker Swarm deployment
|
||||||
|
# echo "$SWARM_SSH_KEY" > swarm_key
|
||||||
|
# chmod 600 swarm_key
|
||||||
|
# ssh -i swarm_key -o StrictHostKeyChecking=no \
|
||||||
|
# deploy@$SWARM_HOST \
|
||||||
|
# "docker service update \
|
||||||
|
# --image ghcr.io/${{ github.repository }}:${IMAGE_TAG} \
|
||||||
|
# tercul-backend"
|
||||||
|
# rm swarm_key
|
||||||
|
|
||||||
|
echo "Deploying version ${{ steps.version.outputs.VERSION }} to production"
|
||||||
|
echo "Image: ghcr.io/${{ github.repository }}:${IMAGE_TAG}"
|
||||||
|
|
||||||
|
- name: Deployment summary
|
||||||
|
run: |
|
||||||
|
echo "### Deployment Complete :rocket:" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Version**: ${{ steps.version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Image**: ghcr.io/${{ github.repository }}:${{ steps.version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Environment**: Production" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Deployed at**: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
|
||||||
@ -1,13 +1,15 @@
|
|||||||
name: Go CD
|
name: Docker Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
tags: ["v*"]
|
tags: ["v*"]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push:
|
build-image:
|
||||||
name: Build and Push Docker Image
|
name: Build Docker Image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@ -36,6 +38,7 @@ jobs:
|
|||||||
images: ghcr.io/${{ github.repository }}
|
images: ghcr.io/${{ github.repository }}
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
type=ref,event=tag
|
type=ref,event=tag
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
@ -46,7 +49,7 @@ jobs:
|
|||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
@ -54,32 +57,9 @@ jobs:
|
|||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|
||||||
- name: Generate artifact attestation
|
- name: Generate artifact attestation
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
uses: actions/attest-build-provenance@v3
|
uses: actions/attest-build-provenance@v3
|
||||||
with:
|
with:
|
||||||
subject-name: ghcr.io/${{ github.repository}}
|
subject-name: ghcr.io/${{ github.repository}}
|
||||||
subject-digest: ${{ steps.push.outputs.digest }}
|
subject-digest: ${{ steps.push.outputs.digest }}
|
||||||
push-to-registry: true
|
push-to-registry: true
|
||||||
|
|
||||||
deploy:
|
|
||||||
name: Deploy to Production
|
|
||||||
needs: build-and-push
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Extract tag name
|
|
||||||
id: tag
|
|
||||||
run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# This step is a placeholder for deployment logic
|
|
||||||
# Replace with your actual deployment mechanism (SSH, kubectl, etc.)
|
|
||||||
- name: Deploy to production
|
|
||||||
run: |
|
|
||||||
echo "Deploying version ${{ steps.tag.outputs.TAG }} to production"
|
|
||||||
# Add your deployment commands here
|
|
||||||
env:
|
|
||||||
TAG: ${{ steps.tag.outputs.TAG }}
|
|
||||||
# Add other environment variables needed for deployment
|
|
||||||
@ -1,17 +1,15 @@
|
|||||||
name: CI
|
name: Lint
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main, develop]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main, develop]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-and-test:
|
golangci-lint:
|
||||||
|
name: Go Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
security-events: write # For code scanning
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
@ -28,17 +26,8 @@ jobs:
|
|||||||
- name: Tidy modules
|
- name: Tidy modules
|
||||||
run: go mod tidy
|
run: go mod tidy
|
||||||
|
|
||||||
- name: Lint
|
- name: Run golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v6
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: --timeout=5m ./...
|
args: --timeout=5m ./...
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: go test -v -race -coverprofile=coverage.out ./...
|
|
||||||
|
|
||||||
- name: Upload coverage
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: coverage
|
|
||||||
path: coverage.out
|
|
||||||
47
.github/workflows/security.yml
vendored
Normal file
47
.github/workflows/security.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: Security
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
schedule:
|
||||||
|
# Run CodeQL scan every Monday at 14:20 UTC
|
||||||
|
- cron: "20 14 * * 1"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codeql-analysis:
|
||||||
|
name: CodeQL Security Scan
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: go
|
||||||
|
# Optionally use security-extended for more comprehensive scanning
|
||||||
|
# queries: security-extended
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.25"
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Build for analysis
|
||||||
|
run: go build -v ./...
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
|
with:
|
||||||
|
category: "backend-security"
|
||||||
114
.github/workflows/test.yml
vendored
Normal file
114
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
name: Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-tests:
|
||||||
|
name: Unit Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:15
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: testdb
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.25"
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Run tests with coverage
|
||||||
|
run: |
|
||||||
|
go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
|
||||||
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
|
||||||
|
- name: Generate test summary
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
echo "### Test Results :test_tube:" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Coverage**: See artifact for detailed report" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Race Detection**: Enabled" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Go Version**: 1.25" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
- name: Upload coverage reports
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report
|
||||||
|
path: |
|
||||||
|
coverage.out
|
||||||
|
coverage.html
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
compatibility-matrix:
|
||||||
|
name: Go ${{ matrix.go-version }} Compatibility
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
go-version: ["1.22", "1.23", "1.24", "1.25"]
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:15
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: testdb
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Go ${{ matrix.go-version }}
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: go test -v -race ./...
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: go build -v ./...
|
||||||
Loading…
Reference in New Issue
Block a user