mirror of
https://github.com/kjanat/articulate-parser.git
synced 2026-01-16 11:02:10 +01:00
Compare commits
3 Commits
bd308e4dfc
...
remove-ci-
| Author | SHA1 | Date | |
|---|---|---|---|
| a1a49a75b7 | |||
| 8d606706e2 | |||
| e7de5d044a |
4
.github/workflows/autofix.yml
vendored
4
.github/workflows/autofix.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
|||||||
- name: Setup go deps
|
- name: Setup go deps
|
||||||
run: |
|
run: |
|
||||||
# Install golangci-lint
|
# Install golangci-lint
|
||||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b "$(go env GOPATH)/bin"
|
||||||
|
|
||||||
# Install go-task dependencies
|
# Install go-task dependencies
|
||||||
go install golang.org/x/tools/cmd/goimports@latest
|
go install golang.org/x/tools/cmd/goimports@latest
|
||||||
@ -34,7 +34,7 @@ jobs:
|
|||||||
run: golangci-lint run --fix
|
run: golangci-lint run --fix
|
||||||
|
|
||||||
- name: Run golangci-lint format
|
- name: Run golangci-lint format
|
||||||
run: golangci-lint format
|
run: golangci-lint fmt
|
||||||
|
|
||||||
- name: Run go mod tidy
|
- name: Run go mod tidy
|
||||||
run: go mod tidy
|
run: go mod tidy
|
||||||
|
|||||||
113
.github/workflows/ci.yml
vendored
113
.github/workflows/ci.yml
vendored
@ -38,9 +38,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go:
|
go:
|
||||||
- 1.21.x
|
|
||||||
- 1.22.x
|
|
||||||
- 1.23.x
|
|
||||||
- 1.24.x
|
- 1.24.x
|
||||||
- 1.25.x
|
- 1.25.x
|
||||||
|
|
||||||
@ -67,14 +64,18 @@ jobs:
|
|||||||
|
|
||||||
- name: Run tests with enhanced reporting
|
- name: Run tests with enhanced reporting
|
||||||
id: test
|
id: test
|
||||||
|
env:
|
||||||
|
CGO_ENABLED: 1
|
||||||
run: |
|
run: |
|
||||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
{
|
||||||
|
cat << EOF
|
||||||
## 🔧 Test Environment
|
## 🔧 Test Environment
|
||||||
- **Go Version:** ${{ matrix.go }}
|
- **Go Version:** ${{ matrix.go }}
|
||||||
- **OS:** ubuntu-latest
|
- **OS:** ubuntu-latest
|
||||||
- **Timestamp:** $(date -u)
|
- **Timestamp:** $(date -u)
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
echo "Running tests with coverage..."
|
echo "Running tests with coverage..."
|
||||||
task test:coverage 2>&1 | tee test-output.log
|
task test:coverage 2>&1 | tee test-output.log
|
||||||
@ -82,21 +83,22 @@ jobs:
|
|||||||
# Extract test results for summary
|
# Extract test results for summary
|
||||||
TEST_STATUS=$?
|
TEST_STATUS=$?
|
||||||
TOTAL_TESTS=$(grep -c "=== RUN" test-output.log || echo "0")
|
TOTAL_TESTS=$(grep -c "=== RUN" test-output.log || echo "0")
|
||||||
PASSED_TESTS=$(grep -c "--- PASS:" test-output.log || echo "0")
|
PASSED_TESTS=$(grep -c -- "--- PASS:" test-output.log || echo "0")
|
||||||
FAILED_TESTS=$(grep -c "--- FAIL:" test-output.log || echo "0")
|
FAILED_TESTS=$(grep -c -- "--- FAIL:" test-output.log || echo "0")
|
||||||
SKIPPED_TESTS=$(grep -c "--- SKIP:" test-output.log || echo "0")
|
SKIPPED_TESTS=$(grep -c -- "--- SKIP:" test-output.log || echo "0")
|
||||||
|
|
||||||
# Generate test summary
|
# Generate test summary
|
||||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
{
|
||||||
|
cat << EOF
|
||||||
## 🧪 Test Results (Go ${{ matrix.go }})
|
## 🧪 Test Results (Go ${{ matrix.go }})
|
||||||
|
|
||||||
| Metric | Value |
|
| Metric | Value |
|
||||||
| ----------- | ----------------------------------------------------------- |
|
| ----------- | ------------------------------------------------------------- |
|
||||||
| Total Tests | $TOTAL_TESTS |
|
| Total Tests | $TOTAL_TESTS |
|
||||||
| Passed | $PASSED_TESTS |
|
| Passed | $PASSED_TESTS |
|
||||||
| Failed | $FAILED_TESTS |
|
| Failed | $FAILED_TESTS |
|
||||||
| Skipped | $SKIPPED_TESTS |
|
| Skipped | $SKIPPED_TESTS |
|
||||||
| Status | $([ $TEST_STATUS -eq 0 ] && echo "PASSED" || echo "FAILED") |
|
| Status | $([ "$TEST_STATUS" -eq 0 ] && echo "PASSED" || echo "FAILED") |
|
||||||
|
|
||||||
### 📦 Package Test Results
|
### 📦 Package Test Results
|
||||||
|
|
||||||
@ -108,38 +110,39 @@ jobs:
|
|||||||
grep "^ok\|^FAIL" test-output.log | while read -r line; do
|
grep "^ok\|^FAIL" test-output.log | while read -r line; do
|
||||||
if [[ $line == ok* ]]; then
|
if [[ $line == ok* ]]; then
|
||||||
pkg=$(echo "$line" | awk '{print $2}')
|
pkg=$(echo "$line" | awk '{print $2}')
|
||||||
echo "| $pkg | ✅ PASS |" >> $GITHUB_STEP_SUMMARY
|
echo "| $pkg | ✅ PASS |"
|
||||||
elif [[ $line == FAIL* ]]; then
|
elif [[ $line == FAIL* ]]; then
|
||||||
pkg=$(echo "$line" | awk '{print $2}')
|
pkg=$(echo "$line" | awk '{print $2}')
|
||||||
echo "| $pkg | ❌ FAIL |" >> $GITHUB_STEP_SUMMARY
|
echo "| $pkg | ❌ FAIL |"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo ""
|
||||||
|
|
||||||
# Add detailed results if tests failed
|
# Add detailed results if tests failed
|
||||||
if [ $TEST_STATUS -ne 0 ]; then
|
if [ "$TEST_STATUS" -ne 0 ]; then
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat << 'EOF'
|
||||||
### ❌ Failed Tests Details
|
### ❌ Failed Tests Details
|
||||||
```
|
```
|
||||||
EOF
|
EOF
|
||||||
grep -A 10 "--- FAIL:" test-output.log | head -100 >> $GITHUB_STEP_SUMMARY
|
grep -A 10 -- "--- FAIL:" test-output.log | head -100
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat << 'EOF'
|
||||||
```
|
```
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
# Set outputs for other steps
|
# Set outputs for other steps
|
||||||
cat >> $GITHUB_OUTPUT << EOF
|
{
|
||||||
test-status=$TEST_STATUS
|
echo "test-status=$TEST_STATUS"
|
||||||
total-tests=$TOTAL_TESTS
|
echo "total-tests=$TOTAL_TESTS"
|
||||||
passed-tests=$PASSED_TESTS
|
echo "passed-tests=$PASSED_TESTS"
|
||||||
failed-tests=$FAILED_TESTS
|
echo "failed-tests=$FAILED_TESTS"
|
||||||
EOF
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# Exit with the original test status
|
# Exit with the original test status
|
||||||
exit $TEST_STATUS
|
exit "$TEST_STATUS"
|
||||||
|
|
||||||
- name: Generate coverage report
|
- name: Generate coverage report
|
||||||
if: always()
|
if: always()
|
||||||
@ -147,7 +150,8 @@ jobs:
|
|||||||
if [ -f coverage/coverage.out ]; then
|
if [ -f coverage/coverage.out ]; then
|
||||||
COVERAGE=$(go tool cover -func=coverage/coverage.out | grep total | awk '{print $3}')
|
COVERAGE=$(go tool cover -func=coverage/coverage.out | grep total | awk '{print $3}')
|
||||||
|
|
||||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
{
|
||||||
|
cat << EOF
|
||||||
## 📊 Code Coverage (Go ${{ matrix.go }})
|
## 📊 Code Coverage (Go ${{ matrix.go }})
|
||||||
|
|
||||||
**Total Coverage: $COVERAGE**
|
**Total Coverage: $COVERAGE**
|
||||||
@ -187,17 +191,18 @@ jobs:
|
|||||||
avg = packages[pkg] / counts[pkg]
|
avg = packages[pkg] / counts[pkg]
|
||||||
printf "| %s | %.1f%% |\n", pkg, avg
|
printf "| %s | %.1f%% |\n", pkg, avg
|
||||||
}
|
}
|
||||||
}' "$temp_coverage" | sort >> $GITHUB_STEP_SUMMARY
|
}' "$temp_coverage" | sort
|
||||||
|
|
||||||
rm -f "$temp_coverage"
|
rm -f "$temp_coverage"
|
||||||
|
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat << 'EOF'
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
else
|
else
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
|
||||||
## ⚠️ Coverage Report
|
## ⚠️ Coverage Report
|
||||||
No coverage file generated
|
No coverage file generated
|
||||||
|
|
||||||
@ -217,7 +222,8 @@ jobs:
|
|||||||
- name: Run linters
|
- name: Run linters
|
||||||
run: |
|
run: |
|
||||||
# Initialize summary
|
# Initialize summary
|
||||||
cat >> $GITHUB_STEP_SUMMARY << EOF
|
{
|
||||||
|
cat << EOF
|
||||||
## 🔍 Static Analysis (Go ${{ matrix.go }})
|
## 🔍 Static Analysis (Go ${{ matrix.go }})
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
@ -226,42 +232,43 @@ jobs:
|
|||||||
VET_OUTPUT=$(task lint:vet 2>&1 || echo "")
|
VET_OUTPUT=$(task lint:vet 2>&1 || echo "")
|
||||||
VET_STATUS=$?
|
VET_STATUS=$?
|
||||||
|
|
||||||
if [ $VET_STATUS -eq 0 ]; then
|
if [ "$VET_STATUS" -eq 0 ]; then
|
||||||
echo "✅ **go vet:** No issues found" >> $GITHUB_STEP_SUMMARY
|
echo "✅ **go vet:** No issues found"
|
||||||
else
|
else
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat << 'EOF'
|
||||||
❌ **go vet:** Issues found
|
❌ **go vet:** Issues found
|
||||||
|
|
||||||
```
|
```
|
||||||
EOF
|
EOF
|
||||||
echo "$VET_OUTPUT" >> $GITHUB_STEP_SUMMARY
|
echo "$VET_OUTPUT"
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
echo '```'
|
||||||
fi
|
fi
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo ""
|
||||||
|
|
||||||
# Run go fmt check
|
# Run go fmt check
|
||||||
FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "")
|
FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "")
|
||||||
FMT_STATUS=$?
|
FMT_STATUS=$?
|
||||||
|
|
||||||
if [ $FMT_STATUS -eq 0 ]; then
|
if [ "$FMT_STATUS" -eq 0 ]; then
|
||||||
echo "✅ **go fmt:** All files properly formatted" >> $GITHUB_STEP_SUMMARY
|
echo "✅ **go fmt:** All files properly formatted"
|
||||||
else
|
else
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat << 'EOF'
|
||||||
❌ **go fmt:** Files need formatting
|
❌ **go fmt:** Files need formatting
|
||||||
|
|
||||||
```
|
```
|
||||||
EOF
|
EOF
|
||||||
echo "$FMT_OUTPUT" >> $GITHUB_STEP_SUMMARY
|
echo "$FMT_OUTPUT"
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
echo '```'
|
||||||
fi
|
fi
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
# Exit with error if any linter failed
|
# Exit with error if any linter failed
|
||||||
[ $VET_STATUS -eq 0 ] && [ $FMT_STATUS -eq 0 ] || exit 1
|
[ "$VET_STATUS" -eq 0 ] && [ "$FMT_STATUS" -eq 0 ] || exit 1
|
||||||
|
|
||||||
- name: Job Summary
|
- name: Job Summary
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
|
||||||
## 📋 Job Summary (Go ${{ matrix.go }})
|
## 📋 Job Summary (Go ${{ matrix.go }})
|
||||||
|
|
||||||
| Step | Status |
|
| Step | Status |
|
||||||
@ -316,7 +323,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Test Docker image using Task
|
- name: Test Docker image using Task
|
||||||
run: |
|
run: |
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
{
|
||||||
|
cat << 'EOF'
|
||||||
## 🧪 Docker Image Tests
|
## 🧪 Docker Image Tests
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
@ -324,16 +332,17 @@ jobs:
|
|||||||
# Run Task docker test
|
# Run Task docker test
|
||||||
task docker:test
|
task docker:test
|
||||||
|
|
||||||
echo "**Testing help command:**" >> $GITHUB_STEP_SUMMARY
|
echo "**Testing help command:**"
|
||||||
echo '```terminaloutput' >> $GITHUB_STEP_SUMMARY
|
echo '```terminaloutput'
|
||||||
docker run --rm articulate-parser:latest --help >> $GITHUB_STEP_SUMMARY
|
docker run --rm articulate-parser:latest --help
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
echo '```'
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo ""
|
||||||
|
|
||||||
# Test image size
|
# Test image size
|
||||||
IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B)
|
IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B)
|
||||||
echo "**Image size:** $IMAGE_SIZE" >> $GITHUB_STEP_SUMMARY
|
echo "**Image size:** $IMAGE_SIZE"
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo ""
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
dependency-review:
|
dependency-review:
|
||||||
name: Dependency Review
|
name: Dependency Review
|
||||||
@ -357,7 +366,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
needs: [test, docker-test, dependency-review]
|
needs: [test]
|
||||||
if: |
|
if: |
|
||||||
github.event_name == 'push' && (github.ref == 'refs/heads/master' ||
|
github.event_name == 'push' && (github.ref == 'refs/heads/master' ||
|
||||||
github.ref == 'refs/heads/develop' ||
|
github.ref == 'refs/heads/develop' ||
|
||||||
@ -436,7 +445,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate Docker summary
|
- name: Generate Docker summary
|
||||||
run: |
|
run: |
|
||||||
cat >> $GITHUB_STEP_SUMMARY << 'EOF'
|
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
|
||||||
## 🐳 Docker Build Summary
|
## 🐳 Docker Build Summary
|
||||||
|
|
||||||
**Image:** `ghcr.io/${{ github.repository }}`
|
**Image:** `ghcr.io/${{ github.repository }}`
|
||||||
|
|||||||
75
.pre-commit-config.yaml
Normal file
75
.pre-commit-config.yaml
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v6.0.0
|
||||||
|
hooks:
|
||||||
|
# File quality
|
||||||
|
- id: trailing-whitespace
|
||||||
|
exclude: '^\.github/ISSUE_TEMPLATE/.*\.yml$'
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: mixed-line-ending
|
||||||
|
args: ['--fix=lf']
|
||||||
|
|
||||||
|
# File validation
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-json
|
||||||
|
- id: check-toml
|
||||||
|
|
||||||
|
# Security
|
||||||
|
- id: detect-private-key
|
||||||
|
|
||||||
|
# Git safety
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: no-commit-to-branch
|
||||||
|
args: ['--branch=master', '--branch=main']
|
||||||
|
|
||||||
|
# File structure
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: check-executables-have-shebangs
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: actionlint
|
||||||
|
name: Lint GitHub Actions workflow files
|
||||||
|
description: Runs actionlint to lint GitHub Actions workflow files
|
||||||
|
language: golang
|
||||||
|
types: ["yaml"]
|
||||||
|
files: ^\.github/workflows/
|
||||||
|
entry: actionlint
|
||||||
|
minimum_pre_commit_version: 3.0.0
|
||||||
|
- repo: https://github.com/golangci/golangci-lint
|
||||||
|
rev: v2.6.1
|
||||||
|
hooks:
|
||||||
|
- id: golangci-lint
|
||||||
|
name: golangci-lint
|
||||||
|
description: Fast linters runner for Go. Note that only modified files are linted, so linters like 'unused' that need to scan all files won't work as expected.
|
||||||
|
entry: golangci-lint run --new-from-rev HEAD --fix
|
||||||
|
types: [go]
|
||||||
|
language: golang
|
||||||
|
require_serial: true
|
||||||
|
pass_filenames: false
|
||||||
|
# - id: golangci-lint-full
|
||||||
|
# name: golangci-lint-full
|
||||||
|
# description: Fast linters runner for Go. Runs on all files in the module. Use this hook if you use pre-commit in CI.
|
||||||
|
# entry: golangci-lint run --fix
|
||||||
|
# types: [go]
|
||||||
|
# language: golang
|
||||||
|
# require_serial: true
|
||||||
|
# pass_filenames: false
|
||||||
|
- id: golangci-lint-fmt
|
||||||
|
name: golangci-lint-fmt
|
||||||
|
description: Fast linters runner for Go. Formats all files in the repo.
|
||||||
|
entry: golangci-lint fmt
|
||||||
|
types: [go]
|
||||||
|
language: golang
|
||||||
|
require_serial: true
|
||||||
|
pass_filenames: false
|
||||||
|
- id: golangci-lint-config-verify
|
||||||
|
name: golangci-lint-config-verify
|
||||||
|
description: Verifies the configuration file
|
||||||
|
entry: golangci-lint config verify
|
||||||
|
files: '\.golangci\.(?:yml|yaml|toml|json)'
|
||||||
|
language: golang
|
||||||
|
pass_filenames: false
|
||||||
371
AGENTS.md
371
AGENTS.md
@ -1,6 +1,7 @@
|
|||||||
# Agent Guidelines for articulate-parser
|
# Agent Guidelines for articulate-parser
|
||||||
|
|
||||||
## Build/Test Commands
|
## Build/Test Commands
|
||||||
|
|
||||||
- **Build**: `task build` or `go build -o bin/articulate-parser main.go`
|
- **Build**: `task build` or `go build -o bin/articulate-parser main.go`
|
||||||
- **Run tests**: `task test` or `go test -race -timeout 5m ./...`
|
- **Run tests**: `task test` or `go test -race -timeout 5m ./...`
|
||||||
- **Run single test**: `go test -v -race -run ^TestName$ ./path/to/package`
|
- **Run single test**: `go test -v -race -run ^TestName$ ./path/to/package`
|
||||||
@ -14,43 +15,413 @@
|
|||||||
## Code Style Guidelines
|
## Code Style Guidelines
|
||||||
|
|
||||||
### Imports
|
### Imports
|
||||||
|
|
||||||
- Use `goimports` with local prefix: `github.com/kjanat/articulate-parser`
|
- Use `goimports` with local prefix: `github.com/kjanat/articulate-parser`
|
||||||
- Order: stdlib, external, internal packages
|
- Order: stdlib, external, internal packages
|
||||||
- Group related imports together
|
- Group related imports together
|
||||||
|
|
||||||
### Formatting
|
### Formatting
|
||||||
|
|
||||||
- Use `gofmt -s` (simplify) and `gofumpt` with extra rules
|
- Use `gofmt -s` (simplify) and `gofumpt` with extra rules
|
||||||
- Function length: max 100 lines, 50 statements
|
- Function length: max 100 lines, 50 statements
|
||||||
- Cyclomatic complexity: max 15
|
- Cyclomatic complexity: max 15
|
||||||
- Cognitive complexity: max 20
|
- Cognitive complexity: max 20
|
||||||
|
|
||||||
### Types & Naming
|
### Types & Naming
|
||||||
|
|
||||||
- Use interface-based design (see `internal/interfaces/`)
|
- Use interface-based design (see `internal/interfaces/`)
|
||||||
- Export types/functions with clear godoc comments ending with period
|
- Export types/functions with clear godoc comments ending with period
|
||||||
- Use descriptive names: `ArticulateParser`, `MarkdownExporter`
|
- Use descriptive names: `ArticulateParser`, `MarkdownExporter`
|
||||||
- Receiver names: short (1-2 chars), consistent per type
|
- Receiver names: short (1-2 chars), consistent per type
|
||||||
|
|
||||||
### Error Handling
|
### Error Handling
|
||||||
|
|
||||||
- Always wrap errors with context: `fmt.Errorf("operation failed: %w", err)`
|
- Always wrap errors with context: `fmt.Errorf("operation failed: %w", err)`
|
||||||
- Use `%w` verb for error wrapping to preserve error chain
|
- Use `%w` verb for error wrapping to preserve error chain
|
||||||
- Check all error returns (enforced by `errcheck`)
|
- Check all error returns (enforced by `errcheck`)
|
||||||
- Document error handling rationale in defer blocks when ignoring close errors
|
- Document error handling rationale in defer blocks when ignoring close errors
|
||||||
|
|
||||||
### Comments
|
### Comments
|
||||||
|
|
||||||
- All exported types/functions require godoc comments
|
- All exported types/functions require godoc comments
|
||||||
- End sentences with periods (`godot` linter enforced)
|
- End sentences with periods (`godot` linter enforced)
|
||||||
- Mark known issues with TODO/FIXME/HACK/BUG/XXX
|
- Mark known issues with TODO/FIXME/HACK/BUG/XXX
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Use `#nosec` with justification for deliberate security exceptions (G304 for CLI file paths, G306 for export file permissions)
|
- Use `#nosec` with justification for deliberate security exceptions (G304 for CLI file paths, G306 for export file permissions)
|
||||||
- Run `gosec` and `govulncheck` for security audits
|
- Run `gosec` and `govulncheck` for security audits
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- Enable race detection: `-race` flag
|
- Enable race detection: `-race` flag
|
||||||
- Use table-driven tests where applicable
|
- Use table-driven tests where applicable
|
||||||
- Mark test helpers with `t.Helper()`
|
- Mark test helpers with `t.Helper()`
|
||||||
- Benchmarks in `*_bench_test.go`, examples in `*_example_test.go`
|
- Benchmarks in `*_bench_test.go`, examples in `*_example_test.go`
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- Minimal external dependencies (currently: go-docx, golang.org/x/net, golang.org/x/text)
|
- Minimal external dependencies (currently: go-docx, golang.org/x/net, golang.org/x/text)
|
||||||
- Run `task deps:tidy` after adding/removing dependencies
|
- Run `task deps:tidy` after adding/removing dependencies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Go 1.24 & 1.25 New Features Reference
|
||||||
|
|
||||||
|
This project uses Go 1.24+. Below is a comprehensive summary of new features and changes in Go 1.24 and 1.25 that may be relevant for development and maintenance.
|
||||||
|
|
||||||
|
### Go 1.24 Major Changes (Released February 2025)
|
||||||
|
|
||||||
|
#### Language Features
|
||||||
|
|
||||||
|
**Generic Type Aliases**
|
||||||
|
|
||||||
|
- Type aliases can now be parameterized with type parameters
|
||||||
|
- Example: `type List[T any] = []T`
|
||||||
|
- Can be disabled via `GOEXPERIMENT=noaliastypeparams` (removed in 1.25)
|
||||||
|
|
||||||
|
#### Tooling Enhancements
|
||||||
|
|
||||||
|
**Module Tool Dependencies**
|
||||||
|
|
||||||
|
- New `tool` directive in go.mod tracks executable dependencies
|
||||||
|
- Use `go get -tool <package>` to add tool dependencies
|
||||||
|
- Use `go install tool` and `go get tool` to manage them
|
||||||
|
- Eliminates need for blank imports in `tools.go` files
|
||||||
|
|
||||||
|
**Build Output Formatting**
|
||||||
|
|
||||||
|
- Both `go build` and `go test` support `-json` flag for structured JSON output
|
||||||
|
- New action types distinguish build output from test results
|
||||||
|
|
||||||
|
**Authentication**
|
||||||
|
|
||||||
|
- New `GOAUTH` environment variable provides flexible authentication for private modules
|
||||||
|
|
||||||
|
**Automatic Version Tracking**
|
||||||
|
|
||||||
|
- `go build` automatically sets main module version in binaries based on VCS tags
|
||||||
|
- Adds `+dirty` suffix for uncommitted changes
|
||||||
|
|
||||||
|
**Cgo Performance Improvements**
|
||||||
|
|
||||||
|
- New `#cgo noescape` annotation: Prevents escape analysis overhead for C function calls
|
||||||
|
- New `#cgo nocallback` annotation: Indicates C function won't call back to Go
|
||||||
|
|
||||||
|
**Toolchain Tracing**
|
||||||
|
|
||||||
|
- `GODEBUG=toolchaintrace=1` enables tracing of toolchain selection
|
||||||
|
|
||||||
|
#### Runtime & Performance
|
||||||
|
|
||||||
|
**Performance Improvements**
|
||||||
|
|
||||||
|
- **2-3% CPU overhead reduction** across benchmark suites
|
||||||
|
- New Swiss Tables-based map implementation (faster lookups)
|
||||||
|
- Disable via `GOEXPERIMENT=noswissmap`
|
||||||
|
- More efficient small object allocation
|
||||||
|
- Redesigned runtime-internal mutexes
|
||||||
|
- Disable via `GOEXPERIMENT=nospinbitmutex`
|
||||||
|
|
||||||
|
#### Compiler & Linker
|
||||||
|
|
||||||
|
**Method Receiver Restrictions**
|
||||||
|
|
||||||
|
- Methods on cgo-generated types now prevented (both directly and through aliases)
|
||||||
|
|
||||||
|
**Build IDs**
|
||||||
|
|
||||||
|
- Linkers generate GNU build IDs (ELF) and UUIDs (macOS) by default
|
||||||
|
- Disable via `-B none` flag
|
||||||
|
|
||||||
|
#### Standard Library Additions
|
||||||
|
|
||||||
|
**File System Safety - `os.Root`**
|
||||||
|
|
||||||
|
- New `os.Root` type enables directory-limited operations
|
||||||
|
- Prevents path escape and symlink breakouts
|
||||||
|
- Essential for sandboxed file operations
|
||||||
|
|
||||||
|
**Cryptography Expansion**
|
||||||
|
|
||||||
|
- `crypto/mlkem`: ML-KEM-768/1024 post-quantum key exchange (FIPS 203)
|
||||||
|
- `crypto/hkdf`: HMAC-based Extract-and-Expand KDF (RFC 5869)
|
||||||
|
- `crypto/pbkdf2`: Password-based key derivation (RFC 8018)
|
||||||
|
- `crypto/sha3`: SHA-3 and SHAKE functions (FIPS 202)
|
||||||
|
|
||||||
|
**FIPS 140-3 Support**
|
||||||
|
|
||||||
|
- New `GOFIPS140` environment variable enables FIPS mode
|
||||||
|
- New `fips140` GODEBUG setting for cryptographic module compliance
|
||||||
|
|
||||||
|
**Weak References - `weak` Package**
|
||||||
|
|
||||||
|
- New `weak` package provides low-level weak pointers
|
||||||
|
- Enables memory-efficient structures like weak maps and caches
|
||||||
|
- Useful for preventing memory leaks in cache implementations
|
||||||
|
|
||||||
|
**Testing Improvements**
|
||||||
|
|
||||||
|
- `testing.B.Loop()`: Cleaner syntax replacing manual `b.N` iteration
|
||||||
|
- Prevents compiler from optimizing away benchmarked code
|
||||||
|
- New `testing/synctest` package (experimental) for testing concurrent code with fake clocks
|
||||||
|
|
||||||
|
**Iterator Support**
|
||||||
|
|
||||||
|
- Multiple packages now offer iterator-returning variants:
|
||||||
|
- `bytes`: Iterator-based functions
|
||||||
|
- `strings`: Iterator-based functions
|
||||||
|
- `go/types`: Iterator support
|
||||||
|
|
||||||
|
#### Security Enhancements
|
||||||
|
|
||||||
|
**TLS Post-Quantum Cryptography**
|
||||||
|
|
||||||
|
- `X25519MLKEM768` hybrid key exchange enabled by default in TLS
|
||||||
|
- Provides quantum-resistant security
|
||||||
|
|
||||||
|
**Encrypted Client Hello (ECH)**
|
||||||
|
|
||||||
|
- TLS servers can enable ECH via `Config.EncryptedClientHelloKeys`
|
||||||
|
- Protects client identity during TLS handshake
|
||||||
|
|
||||||
|
**RSA Key Validation**
|
||||||
|
|
||||||
|
- Keys smaller than 1024 bits now rejected by default
|
||||||
|
- Use `GODEBUG=rsa1024min=0` to revert (testing only)
|
||||||
|
|
||||||
|
**Constant-Time Execution**
|
||||||
|
|
||||||
|
- New `crypto/subtle.WithDataIndependentTiming()` enables architecture-specific timing guarantees
|
||||||
|
- Helps prevent timing attacks
|
||||||
|
|
||||||
|
#### Deprecations & Removals
|
||||||
|
|
||||||
|
- `runtime.GOROOT()`: Deprecated; use system path instead
|
||||||
|
- `crypto/cipher` OFB/CFB modes: Deprecated (unauthenticated encryption)
|
||||||
|
- `x509sha1` GODEBUG: Removed; SHA-1 certificates no longer verified
|
||||||
|
- Experimental `X25519Kyber768Draft00`: Removed
|
||||||
|
|
||||||
|
#### Platform Changes
|
||||||
|
|
||||||
|
- **Linux**: Now requires kernel 3.2+ (enforced)
|
||||||
|
- **macOS**: Go 1.24 is final release supporting Big Sur
|
||||||
|
- **Windows/ARM 32-bit**: Marked broken
|
||||||
|
- **WebAssembly**:
|
||||||
|
- New `go:wasmexport` directive
|
||||||
|
- Reactor/library builds supported via `-buildmode=c-shared`
|
||||||
|
|
||||||
|
#### Bootstrap Requirements
|
||||||
|
|
||||||
|
- Go 1.24 requires Go 1.22.6+ for bootstrapping
|
||||||
|
- Go 1.26 will require Go 1.24+
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Go 1.25 Major Changes (Released August 2025)
|
||||||
|
|
||||||
|
#### Language Changes
|
||||||
|
|
||||||
|
- No breaking language changes
|
||||||
|
- "Core types" concept removed from specification (replaced with clearer prose)
|
||||||
|
|
||||||
|
#### Tooling Improvements
|
||||||
|
|
||||||
|
**Go Command Enhancements**
|
||||||
|
|
||||||
|
- `go build -asan`: Now defaults to leak detection at program exit
|
||||||
|
- New `go.mod ignore` directive: Specify directories for go command to ignore
|
||||||
|
- `go doc -http`: Starts documentation server and opens in browser
|
||||||
|
- `go version -m -json`: Prints JSON-encoded BuildInfo structures
|
||||||
|
- Module path resolution now supports subdirectories using `<meta>` syntax
|
||||||
|
- New `work` package pattern matches all packages in work/workspace modules
|
||||||
|
- Removed automatic toolchain line additions when updating `go` version
|
||||||
|
|
||||||
|
**Vet Analyzers**
|
||||||
|
|
||||||
|
- **"waitgroup"**: Detects misplaced `sync.WaitGroup.Add` calls
|
||||||
|
- **"hostport"**: Warns against using `fmt.Sprintf` for constructing addresses
|
||||||
|
- Recommends `net.JoinHostPort` instead
|
||||||
|
|
||||||
|
#### Runtime Enhancements
|
||||||
|
|
||||||
|
**Container-Aware GOMAXPROCS**
|
||||||
|
|
||||||
|
- Linux now respects cgroup CPU bandwidth limits
|
||||||
|
- All OSes periodically update GOMAXPROCS if CPU availability changes
|
||||||
|
- Disable via environment variables or GODEBUG settings
|
||||||
|
- Critical for containerized applications
|
||||||
|
|
||||||
|
**New Garbage Collector - "Green Tea GC"**
|
||||||
|
|
||||||
|
- Experimental `GOEXPERIMENT=greenteagc` enables new GC
|
||||||
|
- **10-40% reduction in garbage collection overhead**
|
||||||
|
- Significant for GC-sensitive applications
|
||||||
|
|
||||||
|
**Trace Flight Recorder**
|
||||||
|
|
||||||
|
- New `runtime/trace.FlightRecorder` API
|
||||||
|
- Captures execution traces in in-memory ring buffer
|
||||||
|
- Essential for debugging rare events and production issues
|
||||||
|
|
||||||
|
**Other Runtime Changes**
|
||||||
|
|
||||||
|
- Simplified unhandled panic output
|
||||||
|
- VMA names on Linux identify memory purpose (debugging aid)
|
||||||
|
- New `SetDefaultGOMAXPROCS` function resets GOMAXPROCS to defaults
|
||||||
|
|
||||||
|
#### Compiler Fixes & Improvements
|
||||||
|
|
||||||
|
**Critical Nil Pointer Bug Fix**
|
||||||
|
|
||||||
|
- Fixed Go 1.21 regression where nil pointer checks were incorrectly delayed
|
||||||
|
- ⚠️ **May cause previously passing code to now panic** (correct behavior)
|
||||||
|
- Review code for assumptions about delayed nil checks
|
||||||
|
|
||||||
|
**DWARF5 Support**
|
||||||
|
|
||||||
|
- Debug information now uses DWARF version 5
|
||||||
|
- Reduces binary size and linking time
|
||||||
|
- Better debugging experience
|
||||||
|
|
||||||
|
**Faster Slices**
|
||||||
|
|
||||||
|
- Expanded stack allocation for slice backing stores
|
||||||
|
- Improved slice performance
|
||||||
|
|
||||||
|
#### Linker
|
||||||
|
|
||||||
|
- New `-funcalign=N` option specifies function entry alignment
|
||||||
|
|
||||||
|
#### Standard Library Highlights
|
||||||
|
|
||||||
|
**New Packages**
|
||||||
|
|
||||||
|
1. **`testing/synctest`** (Promoted from Experimental)
|
||||||
|
- Concurrent code testing with virtualized time
|
||||||
|
- Control time progression in tests
|
||||||
|
- Essential for testing time-dependent concurrent code
|
||||||
|
|
||||||
|
2. **`encoding/json/v2`** (Experimental)
|
||||||
|
- **Substantially better decoding performance**
|
||||||
|
- Improved API design
|
||||||
|
- Backward compatible with v1
|
||||||
|
|
||||||
|
**Major Package Updates**
|
||||||
|
|
||||||
|
| Package | Key Changes |
|
||||||
|
|---------|------------|
|
||||||
|
| `crypto` | New `MessageSigner` interface and `SignMessage` function |
|
||||||
|
| `crypto/ecdsa` | New raw key parsing/serialization functions |
|
||||||
|
| `crypto/rsa` | **Key generation now 3x faster** |
|
||||||
|
| `crypto/sha1` | **Hashing 2x faster on amd64 with SHA-NI** |
|
||||||
|
| `crypto/tls` | New `CurveID` field; SHA-1 algorithms disallowed in TLS 1.2 |
|
||||||
|
| `net` | Windows now supports file-to-connection conversion; IPv6 multicast improvements |
|
||||||
|
| `net/http` | **New `CrossOriginProtection` middleware for CSRF defense** |
|
||||||
|
| `os` | Windows async I/O support; `Root` type expanded with 12 new methods |
|
||||||
|
| `sync` | **New `WaitGroup.Go` method for convenient goroutine creation** |
|
||||||
|
| `testing` | New `Attr`, `Output` methods; `AllocsPerRun` panics with parallel tests |
|
||||||
|
| `unique` | More eager and parallel reclamation of interned values |
|
||||||
|
|
||||||
|
#### Performance Notes
|
||||||
|
|
||||||
|
**Performance Improvements**
|
||||||
|
|
||||||
|
- ECDSA and Ed25519 signing **4x faster** in FIPS 140-3 mode
|
||||||
|
- SHA3 hashing **2x faster** on Apple M processors
|
||||||
|
- AMD64 fused multiply-add instructions in v3+ mode
|
||||||
|
- ⚠️ **Changes floating-point results** (within IEEE 754 spec)
|
||||||
|
|
||||||
|
**Performance Regressions**
|
||||||
|
|
||||||
|
- SHA-1, SHA-256, SHA-512 slower without AVX2
|
||||||
|
- Most servers post-2015 support AVX2
|
||||||
|
|
||||||
|
#### Platform Changes
|
||||||
|
|
||||||
|
- **macOS**: Requires version 12 Monterey or later
|
||||||
|
- **Windows**: 32-bit windows/arm port marked for removal in Go 1.26
|
||||||
|
- **Loong64**: Race detector now supported
|
||||||
|
- **RISC-V**:
|
||||||
|
- Plugin build mode support
|
||||||
|
- New `GORISCV64=rva23u64` environment variable value
|
||||||
|
|
||||||
|
#### Deprecations
|
||||||
|
|
||||||
|
- `go/ast` functions: `FilterPackage`, `PackageExports`, `MergePackageFiles`
|
||||||
|
- `go/parser.ParseDir` function
|
||||||
|
- Old `testing/synctest` API (when `GOEXPERIMENT=synctest` set)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Actionable Recommendations for This Project
|
||||||
|
|
||||||
|
#### Immediate Opportunities
|
||||||
|
|
||||||
|
1. **Replace `sync.WaitGroup` patterns with `WaitGroup.Go()`** (Go 1.25)
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Old pattern
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
// work
|
||||||
|
}()
|
||||||
|
|
||||||
|
// New pattern (Go 1.25)
|
||||||
|
wg.Go(func() {
|
||||||
|
// work
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use `testing.B.Loop()` in benchmarks** (Go 1.24)
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Old pattern
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
// benchmark code
|
||||||
|
}
|
||||||
|
|
||||||
|
// New pattern (Go 1.24)
|
||||||
|
for b.Loop() {
|
||||||
|
// benchmark code
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Consider `os.Root` for file operations** (Go 1.24)
|
||||||
|
- Prevents path traversal vulnerabilities
|
||||||
|
- Safer for user-provided file paths
|
||||||
|
|
||||||
|
4. **Enable Green Tea GC for testing** (Go 1.25)
|
||||||
|
- Test with `GOEXPERIMENT=greenteagc`
|
||||||
|
- May reduce GC overhead by 10-40%
|
||||||
|
|
||||||
|
5. **Leverage container-aware GOMAXPROCS** (Go 1.25)
|
||||||
|
- No changes needed; automatic in containers
|
||||||
|
- Improves resource utilization
|
||||||
|
|
||||||
|
6. **Review floating-point operations** (Go 1.25)
|
||||||
|
- AMD64 v3+ uses FMA instructions
|
||||||
|
- May change floating-point results (within spec)
|
||||||
|
|
||||||
|
7. **Watch nil pointer checks** (Go 1.25)
|
||||||
|
- Compiler bug fix may expose latent nil pointer bugs
|
||||||
|
- Review crash reports carefully
|
||||||
|
|
||||||
|
#### Future Considerations
|
||||||
|
|
||||||
|
1. **Evaluate `encoding/json/v2`** when stable
|
||||||
|
- Better performance for JSON operations
|
||||||
|
- Currently experimental in Go 1.25
|
||||||
|
|
||||||
|
2. **Adopt tool directives** in go.mod
|
||||||
|
- Cleaner dependency management for build tools
|
||||||
|
- Remove `tools.go` if present
|
||||||
|
|
||||||
|
3. **Enable FIPS mode if required**
|
||||||
|
- Use `GOFIPS140=1` for compliance
|
||||||
|
- Performance improvements in Go 1.25 (4x faster signing)
|
||||||
|
|
||||||
|
4. **Use `runtime/trace.FlightRecorder`** for production debugging
|
||||||
|
- Capture traces of rare events
|
||||||
|
- Minimal overhead when not triggered
|
||||||
|
|||||||
@ -316,13 +316,13 @@ tasks:
|
|||||||
docker:run:
|
docker:run:
|
||||||
desc: Run Docker container
|
desc: Run Docker container
|
||||||
aliases: [dr]
|
aliases: [dr]
|
||||||
deps: [docker:build]
|
deps: ['docker:build']
|
||||||
cmds:
|
cmds:
|
||||||
- docker run --rm {{.APP_NAME}}:{{.VERSION}} --help
|
- docker run --rm {{.APP_NAME}}:{{.VERSION}} --help
|
||||||
|
|
||||||
docker:test:
|
docker:test:
|
||||||
desc: Test Docker image
|
desc: Test Docker image
|
||||||
deps: [docker:build]
|
deps: ['docker:build']
|
||||||
cmds:
|
cmds:
|
||||||
- docker run --rm {{.APP_NAME}}:{{.VERSION}} --version
|
- docker run --rm {{.APP_NAME}}:{{.VERSION}} --version
|
||||||
- echo "Docker image tested successfully"
|
- echo "Docker image tested successfully"
|
||||||
@ -434,7 +434,7 @@ tasks:
|
|||||||
|
|
||||||
docs:coverage:
|
docs:coverage:
|
||||||
desc: Open coverage report in browser
|
desc: Open coverage report in browser
|
||||||
deps: [test:coverage]
|
deps: ['test:coverage']
|
||||||
cmds:
|
cmds:
|
||||||
- '{{if eq OS "darwin"}}open {{.COVERAGE_DIR}}/coverage.html{{else if eq OS "windows"}}start {{.COVERAGE_DIR}}/coverage.html{{else}}xdg-open {{.COVERAGE_DIR}}/coverage.html 2>/dev/null || echo "Please open {{.COVERAGE_DIR}}/coverage.html in your browser"{{end}}'
|
- '{{if eq OS "darwin"}}open {{.COVERAGE_DIR}}/coverage.html{{else if eq OS "windows"}}start {{.COVERAGE_DIR}}/coverage.html{{else}}xdg-open {{.COVERAGE_DIR}}/coverage.html 2>/dev/null || echo "Please open {{.COVERAGE_DIR}}/coverage.html in your browser"{{end}}'
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import (
|
|||||||
//go:embed html_styles.css
|
//go:embed html_styles.css
|
||||||
var defaultCSS string
|
var defaultCSS string
|
||||||
|
|
||||||
//go:embed html_template.html
|
//go:embed html_template.gohtml
|
||||||
var htmlTemplate string
|
var htmlTemplate string
|
||||||
|
|
||||||
// HTMLExporter implements the Exporter interface for HTML format.
|
// HTMLExporter implements the Exporter interface for HTML format.
|
||||||
|
|||||||
@ -9,4 +9,3 @@ Course description
|
|||||||
- **Navigation Mode**:
|
- **Navigation Mode**:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user