CONTRIBUTING.md#5
Conversation
Here's a `cmake-single-platform.yml` GitHub Actions workflow that builds and tests a CMake project on Linux:
```yaml
name: CMake Build and Test
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake
- name: Create build directory
run: cmake -E make_directory build
- name: Configure CMake
working-directory: build
run: cmake .. -DCMAKE_BUILD_TYPE=Release
- name: Build project
working-directory: build
run: cmake --build . --config Release --parallel $(nproc)
- name: Run tests
working-directory: build
run: ctest -C Release --output-on-failure
```
### Key Features:
1. **Triggers**:
- Runs on push/PR to main/master branches
2. **Environment**:
- Uses latest Ubuntu runner
3. **Steps**:
- Installs essential build tools and CMake
- Creates a separate build directory
- Configures CMake in Release mode
- Builds with parallel compilation (uses all available cores)
- Runs tests with detailed failure output
4. **Optimizations**:
- Parallel builds using `$(nproc)` to detect available CPU cores
- Separate build directory keeps source tree clean
- Output-on-failure for test debugging
### Customization Options:
1. **Add Dependencies**:
```yaml
- name: Install custom dependencies
run: sudo apt-get install -y libboost-dev libopencv-dev
```
2. **CMake Configuration Flags**:
```yaml
run: cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON
```
3. **Cross-Platform** (modify `runs-on`):
```yaml
# For Windows
runs-on: windows-latest
# For macOS
runs-on: macos-latest
```
4. **Caching Dependencies** (add before build step):
```yaml
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.cache
key: ${{ runner.os }}-deps-${{ hashFiles('**/CMakeLists.txt') }}
```
5. **Artifact Upload** (add after build):
```yaml
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-output
path: build/
```
To use this workflow:
1. Create `.github/workflows/cmake-single-platform.yml` in your repo
2. Commit and push to trigger the workflow
3. Monitor executions in GitHub Actions tab
The workflow will automatically:
- Build Release configuration
- Run all registered CTest targets
- Fail fast on compilation errors or test failures
- Provide detailed build logs for debugging
Based on the CI badge you've shared, here's how to create a similar status badge for your updated SLSA Level 3 publish workflow: ### 1. Create the SLSA Publish Workflow Badge Add this markdown to your README.md: ```markdown [](https://github.com/Sazwanismail/bitcoin/actions/workflows/generator-generic-ossf-slsa3-publish.yml) ``` ### 2. Key Parameters Explained: | Parameter | Value | Purpose | |--------------------|-------------------------------------------------|------------------------------------------| | Workflow filename | `generator-generic-ossf-slsa3-publish.yml` | Matches your updated workflow file | | Branch | `branch=master` | Shows status for master branch | | Event | (Automatic - no need to specify) | Uses default release published trigger | ### 3. For Workflow Dispatch Trigger: If you want to add manual trigger status (like your CI badge), modify to: ```markdown [](https://github.com/Sazwanismail/bitcoin/actions/workflows/generator-generic-ossf-slsa3-publish.yml) ``` Note the added `&event=workflow_dispatch` parameter ### 4. Badge Appearance Options: - **Passing**:  - **Failing**:  - **In Progress**:  ### 5. Recommended Placement: Add both badges together for better visibility: ```markdown ## Build Status [](https://github.com/Sazwanismail/bitcoin/actions/workflows/ci.yml) [](https://github.com/Sazwanismail/bitcoin/actions/workflows/generator-generic-ossf-slsa3-publish.yml) ``` This creates a professional status overview showing both regular CI builds and SLSA-compliant release publishing in your README. The badges will automatically update to show real-time workflow status.
I'll update the `cmake-single-platform.yml` workflow with significant improvements for security, performance, and compliance. Here's the enhanced version:
```yaml
name: CMake Build (SLSA L3 Provenance) - Single Platform
on:
push:
branches: [main, release/*]
tags: [v*]
pull_request:
release:
types: [published]
workflow_dispatch:
inputs:
build-type:
description: 'Build type'
required: true
default: 'Release'
type: choice
options: [Debug, Release, RelWithDebInfo]
permissions:
id-token: write # Required for OIDC provenance signing
contents: read # Minimal permissions for code access
actions: read # Required for reusable workflows
jobs:
setup:
runs-on: ubuntu-latest
outputs:
build-type: ${{ steps.inputs.outputs.build-type }}
run-id: ${{ github.run_id }}
steps:
- name: Capture build type
id: inputs
run: |
build_type="${{ github.event.inputs.build-type || 'Release' }}"
echo "build-type=$build_type" >> $GITHUB_OUTPUT
- name: Generate unique run ID
id: run-id
run: echo "run-id=${{ github.run_id }}" >> $GITHUB_OUTPUT
cmake-build:
needs: setup
runs-on: ubuntu-latest
outputs:
base64-subjects: ${{ steps.hashes.outputs.base64_subjects }}
artifacts-name: artifacts-${{ needs.setup.outputs.run-id }}
build-type: ${{ needs.setup.outputs.build-type }}
steps:
- name: Checkout code (full history)
uses: actions/checkout@v4
with:
fetch-depth: 0 # Essential for SLSA provenance
- name: Cache build dependencies
uses: actions/cache@v3
with:
path: |
~/.cache/ccache
build
key: ${{ runner.os }}-cmake-${{ hashFiles('**/CMakeLists.txt') }}-${{ needs.setup.outputs.run-id }}
restore-keys: |
${{ runner.os }}-cmake-
- name: Setup build environment
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ccache ninja-build
- name: Configure CMake
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=${{ needs.setup.outputs.build-type }} \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build project
run: cmake --build build --parallel 4
- name: Test project
run: ctest --test-dir build --output-on-failure
- name: Package artifacts
run: |
mkdir -p artifacts
# Copy binaries, libraries, and other distributables
find build -type f \( -executable -o -name "*.so*" -o -name "*.a" \) \
-exec cp -t artifacts/ {} +
# Create versioned archive
version=${{ github.event.release.tag_name || 'nightly' }}
tar czf artifacts-$version.tar.gz -C artifacts .
mv artifacts-$version.tar.gz artifacts/
- name: Generate artifact hashes
id: hashes
run: |
cd artifacts
subjects="[]"
for file in *; do
# Use SHA512 for stronger security
hash=$(sha512sum "$file" | awk '{print $1}')
subjects=$(jq -c \
--arg name "$file" \
--arg hash "sha512:$hash" \
'. += [{"name": $file, "digest": $hash}]' \
<<< "$subjects")
done
echo "base64_subjects=$(echo -n "$subjects" | base64 -w0)" >> $GITHUB_OUTPUT
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: artifacts-${{ needs.setup.outputs.run-id }}
path: artifacts/
retention-days: 3
provenance:
needs: [setup, cmake-build]
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
permissions:
id-token: write
contents: write
actions: read
with:
base64-subjects: ${{ needs.cmake-build.outputs.base64-subjects }}
upload-artifacts-name: ${{ needs.cmake-build.outputs.artifacts-name }}
upload-assets: ${{ github.event_name == 'release' && github.event.action == 'published' }}
build-type: ${{ needs.cmake-build.outputs.build-type }}
secrets: inherit
security-scan:
needs: [cmake-build]
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: ${{ needs.cmake-build.outputs.artifacts-name }}
- name: Run vulnerability scan
uses: shiftleft/scan-action@v2
with:
output: reports/
scan-type: all
- name: Upload security report
uses: actions/upload-artifact@v4
with:
name: security-report-${{ needs.setup.outputs.run-id }}
path: reports/
deploy:
needs: [provenance, security-scan]
if: github.event_name == 'release' && github.event.action == 'published'
runs-on: ubuntu-latest
environment: production
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: ${{ needs.cmake-build.outputs.artifacts-name }}
- name: Verify provenance
run: |
# Install SLSA verifier
curl -sSL https://github.com/slsa-framework/slsa-verifier/releases/download/v3.0.0/slsa-verifier-linux-amd64 -o slsa-verifier
chmod +x slsa-verifier
./slsa-verifier verify-artifact \
--provenance-path provenance.json \
--source-uri github.com/${{ github.repository }} \
--builder-id https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 \
artifacts/*.tar.gz
- name: Deploy to production
run: |
# Add your deployment commands here
echo "Deploying verified artifacts..."
```
### Key Improvements:
1. **Workflow Structure**:
- Added `setup` job for input handling and run ID generation
- Separated build, provenance, security scanning, and deployment
- Matrix-ready for future multi-platform expansion
2. **Enhanced Security**:
- SHA512 hashing instead of SHA256
- Full provenance verification before deployment
- Security scanning with ShiftLeft
- Explicit permission scoping
- SLSA generator updated to v2.1.0
3. **Build Improvements**:
- Added CCache for build acceleration
- Ninja build system for faster compilation
- Parallel builds (`--parallel 4`)
- Automated testing with CTest
- Build type parameterization (Debug/Release)
4. **Artifact Management**:
- Versioned tarballs for releases
- Better artifact collection with pattern matching
- Shortened artifact retention (3 days)
- Automated cleanup of old artifacts
5. **New Features**:
- Security scanning job
- Deployment environment with verification gate
- Workflow dispatch with build options
- Release tag detection
- Branch protection patterns (`release/*`)
6. **Compliance Enhancements**:
- Explicit builder ID in verifier
- Non-repudiable provenance
- Full build environment capture
- Source integrity verification
### Usage Notes:
1. **Customize Build**:
- Modify `Package artifacts` step to match your project structure
- Adjust CMake flags in `Configure CMake` step
- Update artifact patterns in `find` command
2. **Deployment**:
- Add your actual deployment commands in the `Deploy to production` step
- Configure environment protection rules in GitHub settings
3. **Security**:
- Review security scan results
- Consider adding additional scanners (Trivy, OWASP ZAP)
- Enable branch protection rules
4. **Verification**:
- The SLSA verifier step ensures provenance matches artifacts
- Verification occurs in deployment job before release
This updated workflow provides a comprehensive CI/CD pipeline with strong security guarantees, faster builds, and better artifact management while maintaining SLSA Level 3 compliance.
Based on your request to update a `ci.yml` (typically `.gitlab-ci.yml` or similar CI/CD configuration file), here's a structured approach incorporating 2025 best practices from industry sources. Key updates focus on **security**, **efficiency**, **reusability**, and **scalability**:
### 🔧 1. **Adopt Dynamic Child Pipelines for Environment Management**
- **Problem**: Managing numerous environments (e.g., `env1`, `env2`) bloats the YAML file .
- **Solution**: Use a `parallel:matrix` to generate deployment jobs dynamically:
```yaml
deploy:
stage: deploy
script: ./deploy.sh $ENV_NAME
parallel:
matrix:
- ENV_NAME: [dev, staging, prod] # Add/remove environments here
```
- **Benefits**: Reduces code duplication; adds environments without modifying pipeline structure .
### 🔐 2. **Implement Kaniko for Secure Docker Builds**
- Replace `docker build` with **Kaniko** to eliminate privileged container risks:
```yaml
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.9.0
entrypoint: [""]
script:
- /kaniko/executor --context $CI_PROJECT_DIR --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
```
- **Why**: Avoids security flaws in Docker-in-Docker (DinD) and uses layer caching for faster builds .
### ♻️ 3. **Centralize CI Templates for Cross-Project Consistency**
- Store reusable templates in a dedicated repo (e.g., `ci-templates/`):
```yaml
include:
- project: 'my-org/ci-templates'
ref: main
file: '/templates/kaniko-build.yml'
```
- **Advantages**: Ensures standardized pipelines; updates propagate globally .
### ⚡ 4. **Optimize Trigger Rules to Reduce Resource Waste**
- Run pipelines selectively using `rules`:
```yaml
deploy_prod:
stage: deploy
script: ./deploy.sh prod
rules:
- if: $CI_COMMIT_BRANCH == "main"
changes:
- "src/prod-config/*" # Only trigger if prod config changes
```
- **Efficiency**: Cuts unnecessary job runs by 40–60% .
### 🛡️ 5. **Integrate Security Scanning & Secrets Management**
- Add built-in security scans and use **Vault** for secrets:
```yaml
security_scan:
stage: test
image: shiftleft/scan
script:
- scan --src $CI_PROJECT_DIR --type php
secrets:
VAULT_TOKEN: $VAULT_CI_TOKEN # Inject secrets securely
```
- **Compliance**: Automated SAST/DAST scans; secrets never exposed in logs .
---
### 🚀 **Advanced Optimization Techniques**
- **YAML Anchors & `!reference`**: Reuse configurations without duplication :
```yaml
.base_script: &base_script
before_script:
- apt-get update
job1:
<<: *base_script
script: ./test.sh
```
- **Protected Tags/Branches**: Prevent accidental deployments to `main` .
- **Windows Runner Fixes**: Use explicit tags (e.g., `saas-windows-medium-amd64`) to avoid Linux/Windows conflicts .
---
### 💎 **Sample Snippet for a Modern `.gitlab-ci.yml`**
```yaml
stages:
- build
- test
- deploy
include:
- project: 'my-org/ci-templates'
file: '/security-scan.yml'
build:
extends: .kaniko_template # From centralized template
variables:
CONTEXT: $CI_PROJECT_DIR
deploy:
stage: deploy
parallel:
matrix:
- ENV: [dev, staging, prod]
script: ./deploy.sh $ENV
rules:
- if: $CI_COMMIT_TAG != null # Deploy only on tagged releases
```
### Key Trends for 2025 :
- **AI-Driven Pipelines**: Auto-fix failed jobs using ML.
- **GitOps Integration**: Tools like **Argo CD** for Kubernetes deployments.
- **Cost Control**: Parallel jobs + caching to reduce cloud spending.
For further implementation details:
- GitLab CI Editor/Lint: Validate syntax in real-time .
- Dynamic Environments: Use `environment:url` with review apps.
Let me know if you need help adapting this to a specific tool (e.g., GitHub Actions) or legacy systems! 😊
# CodeQL Advanced Implementation
## 🚀 Complete Advanced CodeQL Setup
### 1. Advanced CodeQL Configuration Structure
```
.github/
├── workflows/
│ ├── codeql-advanced.yml
│ ├── codeql-security-gates.yml
│ └── codeql-custom-analysis.yml
├── codeql/
│ ├── config/
│ │ ├── codeql-config.yml
│ │ ├── query-suites.qls
│ │ └── performance-config.yml
│ ├── custom-queries/
│ │ ├── qlpack.yml
│ │ ├── Security/
│ │ ├── Performance/
│ │ └── Architecture/
│ └── scripts/
│ ├── aggregate-results.py
│ └── security-gates.py
```
### 2. Main Advanced CodeQL Workflow
```yaml
# .github/workflows/codeql-advanced.yml
name: "Advanced CodeQL Analysis"
on:
push:
branches: [ main, develop, release/* ]
paths:
- 'src/**'
- 'lib/**'
- '**.java'
- '**.js'
- '**.ts'
- '**.py'
- '**.go'
- '**.cpp'
paths-ignore:
- '**/*.md'
- '**/*.txt'
- '**/test/**'
- '**/spec/**'
pull_request:
branches: [ main, develop ]
schedule:
- cron: '0 2 * * 1' # Weekly on Monday at 2 AM UTC
workflow_dispatch:
inputs:
analysis-depth:
description: 'Analysis depth level'
required: true
default: 'deep'
type: choice
options:
- quick
- standard
- deep
include-experimental:
description: 'Include experimental queries'
required: false
type: boolean
default: false
env:
CODEQL_ACTION_VERBOSITY: info
CODEQL_POWERFUL_ANALYSIS: true
CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN: false
jobs:
initialize:
name: Initialize Analysis
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
database-locations: ${{ steps.set-matrix.outputs.database-locations }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up analysis matrix
id: set-matrix
run: |
MATRIX_JSON=$(python .github/codeql/scripts/detect-languages.py)
echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
echo "database-locations=$(echo $MATRIX_JSON | jq -r '.include[].database_location' | tr '\n' ',' | sed 's/,$//')" >> $GITHUB_OUTPUT
analyze-multi-language:
name: Analyze (${{ matrix.language }})
needs: initialize
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.initialize.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: ${{ matrix.queries }}
config-file: ./.github/codeql/config/codeql-config.yml
config: ${{ matrix.config }}
tools: latest
database: ${{ matrix.database_location }}
- name: Build ${{ matrix.language }} code
if: matrix.build-command
run: ${{ matrix.build-command }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
output: sarif-results/${{ matrix.language }}
upload-database: true
skip-queries: ${{ github.event_name == 'schedule' && 'security' || '' }}
threads: ${{ matrix.threads }}
ram: ${{ matrix.ram }}
env:
CODEQL_RAM: ${{ matrix.ram }}
CODEQL_THREADS: ${{ matrix.threads }}
custom-query-analysis:
name: Custom Query Analysis
needs: analyze-multi-language
runs-on: ubuntu-latest
if: always()
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download CodeQL databases
run: |
mkdir -p databases
echo "${{ needs.initialize.outputs.database-locations }}" | tr ',' '\n' | xargs -I {} cp -r {} databases/
- name: Run Custom Queries
uses: github/codeql-action/analyze@v3
with:
queries: ./.github/codeql/custom-queries/
packs: ./.github/codeql/custom-queries/
output: sarif-results/custom
category: "custom"
security-metrics:
name: Generate Security Metrics
needs: [analyze-multi-language, custom-query-analysis]
runs-on: ubuntu-latest
if: always()
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Generate Security Report
run: |
python .github/codeql/scripts/aggregate-results.py
- name: Upload Security Metrics
uses: actions/upload-artifact@v4
with:
name: security-metrics
path: |
security-report.html
codeql-metrics.json
retention-days: 30
- name: Update Security Dashboard
run: |
echo "## CodeQL Security Analysis Complete" >> $GITHUB_STEP_SUMMARY
echo "✅ Multi-language analysis completed" >> $GITHUB_STEP_SUMMARY
echo "📊 Custom queries executed" >> $GITHUB_STEP_SUMMARY
echo "📈 Security metrics generated" >> $GITHUB_STEP_SUMMARY
```
### 3. Language Detection Script
```python
# .github/codeql/scripts/detect-languages.py
#!/usr/bin/env python3
import json
import os
from pathlib import Path
def detect_languages():
"""Detect programming languages in the repository"""
language_files = {
'java': ['**/*.java', '**/pom.xml', '**/build.gradle', '**/build.gradle.kts'],
'javascript': ['**/*.js', '**/*.ts', '**/package.json', '**/yarn.lock'],
'python': ['**/*.py', '**/requirements.txt', '**/Pipfile', '**/pyproject.toml'],
'go': ['**/*.go', '**/go.mod'],
'cpp': ['**/*.cpp', '**/*.hpp', '**/*.c', '**/*.h', '**/CMakeLists.txt'],
}
detected_languages = []
for lang, patterns in language_files.items():
for pattern in patterns:
if list(Path('.').glob(pattern)):
detected_languages.append(lang)
break
# Default to javascript if no languages detected
if not detected_languages:
detected_languages = ['javascript']
return detected_languages
def generate_matrix(languages):
"""Generate workflow matrix configuration"""
matrix_config = {
'include': []
}
language_configs = {
'java': {
'runner': 'ubuntu-latest',
'queries': 'security-and-quality,security-extended',
'build-command': './gradlew build -x test || mvn compile -DskipTests',
'threads': 4,
'ram': 8192,
'config': '{"packs": ["codeql/java-queries"]}'
},
'javascript': {
'runner': 'ubuntu-latest',
'queries': 'security-and-quality,security-extended',
'build-command': '',
'threads': 2,
'ram': 4096,
'config': '{"packs": ["codeql/javascript-queries"]}'
},
'python': {
'runner': 'ubuntu-latest',
'queries': 'security-and-quality,security-extended',
'build-command': '',
'threads': 2,
'ram': 4096,
'config': '{"packs": ["codeql/python-queries"]}'
},
'go': {
'runner': 'ubuntu-latest',
'queries': 'security-and-quality',
'build-command': 'go build ./...',
'threads': 2,
'ram': 4096,
'config': '{"packs": ["codeql/go-queries"]}'
},
'cpp': {
'runner': 'ubuntu-latest',
'queries': 'security-and-quality',
'build-command': 'mkdir -p build && cd build && cmake .. && make -j4',
'threads': 4,
'ram': 8192,
'config': '{"packs": ["codeql/cpp-queries"]}'
}
}
for lang in languages:
if lang in language_configs:
config = language_configs[lang]
matrix_config['include'].append({
'language': lang,
'runner': config['runner'],
'queries': config['queries'],
'build-command': config['build-command'],
'threads': config['threads'],
'ram': config['ram'],
'config': config['config'],
'database_location': f'.codeql/databases/{lang}'
})
return matrix_config
if __name__ == "__main__":
languages = detect_languages()
matrix = generate_matrix(languages)
print(json.dumps(matrix))
```
### 4. Advanced CodeQL Configuration
```yaml
# .github/codeql/config/codeql-config.yml
name: "Advanced CodeQL Configuration"
query-filters:
- exclude:
id:
- "java/example/too-many-loops"
- "js/debugger-statement"
- "python/trivial-conditional"
- include:
tags:
- "security"
- "external/cwe/cwe-798"
- "external/cwe/cwe-259"
- "external/cwe/cwe-89"
- "external/cwe/cwe-79"
- include:
precision:
- "high"
- "medium"
paths:
- "src/"
- "lib/"
- "app/"
- "main/"
paths-ignore:
- "**/test/**"
- "**/spec/**"
- "**/node_modules/**"
- "**/vendor/**"
- "**/build/**"
- "**/dist/**"
- "**/.cache/**"
languages:
java:
build-command:
- "./gradlew build -x test"
- "mvn compile -DskipTests"
source-roots:
- "src/main/java"
- "src/main/kotlin"
javascript:
build-command: "npm run build --if-present"
source-roots:
- "src"
- "lib"
python:
build-command: "python -m py_compile **/*.py"
source-roots:
- "src"
- "app"
go:
build-command: "go build ./..."
source-roots:
- "."
cpp:
build-command: "mkdir -p build && cd build && cmake .. && make -j4"
source-roots:
- "src"
- "include"
queries:
- uses: ./.github/codeql/config/query-suites.qls
- uses: ./.github/codeql/custom-queries/qlpack.yml
packs:
- "codeql/java-queries"
- "codeql/javascript-queries"
- "codeql/python-queries"
- "codeql/go-queries"
- "codeql/cpp-queries"
- "./.github/codeql/custom-queries"
database:
location: "./.codeql/databases"
cleanup: true
retention-days: 30
analysis:
mode: "${{ env.ANALYSIS_MODE || 'deep' }}"
timeout: 300
memory: 8192
threads: 0 # 0 means automatic
output:
format: sarif-latest
include-column-numbers: true
include-severity: true
include-help-links: true
```
### 5. Custom Query Pack Configuration
```yaml
# .github/codeql/custom-queries/qlpack.yml
name: custom-security-queries
version: 1.0.0
libraryPathDependencies:
- codeql/java-all
- codeql/javascript-all
- codeql/python-all
- codeql/go-all
- codeql/cpp-all
extractor: |
none
dependencies:
codeql/java-all: "*"
codeql/javascript-all: "*"
codeql/python-all: "*"
codeql/go-all: "*"
codeql/cpp-all: "*"
```
### 6. Advanced Security Queries
```ql
// .github/codeql/custom-queries/Security/SQLInjectionAdvanced.ql
/**
* @name Advanced SQL Injection Detection
* @description Detects complex SQL injection patterns with taint tracking
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/advanced-sql-injection
* @tags security
* external/cwe/cwe-89
* external/cwe/cwe-564
*/
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
class SqlInjectionConfiguration extends TaintTracking::Configuration {
SqlInjectionConfiguration() {
this = "SqlInjectionConfiguration"
}
override predicate isSource(DataFlow::Node source) {
// HTTP request parameters
exists(Method m |
m.hasName("getParameter") or
m.hasName("getHeader") or
m.hasName("getQueryString") or
m.hasName("getCookies") or
m.hasName("getAttribute")
|
source.asExpr() = m.getACall()
) or
// File input
exists(Method m |
m.hasName("readLine") or
m.hasName("read") and
m.getDeclaringType().hasQualifiedName("java.io", "Reader")
|
source.asExpr() = m.getACall()
)
}
override predicate isSink(DataFlow::Node sink) {
// Database operations
exists(Method m |
m.hasName("executeQuery") or
m.hasName("executeUpdate") or
m.hasName("execute") or
m.hasName("prepareStatement") or
m.hasName("createStatement")
|
sink.asExpr() = m.getACall() or
sink.asExpr() = m.getArgument(0)
) or
// ORM operations
exists(Method m |
m.hasName("createNativeQuery") or
m.hasName("createQuery") and
m.getDeclaringType().getASupertype*().hasQualifiedName("javax.persistence", "EntityManager")
|
sink.asExpr() = m.getACall()
)
}
override predicate isSanitizer(DataFlow::Node sanitizer) {
// Parameterized queries
exists(Method m |
m.hasName("setString") or
m.hasName("setInt") or
m.hasName("setDate") and
m.getDeclaringType().getASupertype*().hasQualifiedName("java.sql", "PreparedStatement")
|
sanitizer.asExpr() = m.getACall()
) or
// Input validation
exists(Method m |
m.hasName("matches") or
m.hasName("isAlphanumeric") or
m.hasName("escapeSql")
|
sanitizer.asExpr() = m.getACall()
) or
// Encoding/escaping
exists(Method m |
m.hasName("encode") or
m.hasName("escape") and
m.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringEscapeUtils")
|
sanitizer.asExpr() = m.getACall()
)
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
// String concatenation and manipulation
exists(BinaryExpr bin |
bin.getOperator() = BinaryExpr.ADD and
(bin.getLeftOperand() = node1.asExpr() and bin.getRightOperand() = node2.asExpr() or
bin.getRightOperand() = node1.asExpr() and bin.getLeftOperand() = node2.asExpr())
) or
// String builder operations
exists(MethodAccess ma |
ma.getMethod().hasName("append") and
ma.getMethod().getDeclaringType().getASupertype*().hasQualifiedName("java.lang", "AbstractStringBuilder") and
node1.asExpr() = ma.getQualifier() and
node2.asExpr() = ma
)
}
}
from SqlInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"Potential SQL injection vulnerability: user input flows to database operation without proper sanitization"
```
### 7. Performance Analysis Queries
```ql
// .github/codeql/custom-queries/Performance/MemoryLeakDetection.ql
/**
* @name Memory Leak Detection
* @description Identifies potential memory leaks in Java applications
* @kind problem
* @problem.severity warning
* @precision medium
* @id java/memory-leak-detection
* @tags performance
* maintainability
*/
import java
class ResourceAllocation extends Method {
ResourceAllocation() {
this.getName().matches("create%") or
this.getName().matches("new%") or
this.getName().matches("open%") or
this.getName().matches("allocate%") or
this.getName().matches("init%")
}
}
class ResourceRelease extends Method {
ResourceRelease() {
this.getName().matches("close%") or
this.getName().matches("destroy%") or
this.getName().matches("release%") or
this.getName().matches("free%") or
this.getName().matches("cleanup%") or
this.getName().matches("dispose%")
}
}
class PotentialMemoryLeak extends ResourceAllocation {
PotentialMemoryLeak() {
not exists(ResourceRelease release |
release.getDeclaringType() = this.getDeclaringType() and
release.getName().toLowerCase() = this.getName().replace("create", "close").toLowerCase() or
release.getName().toLowerCase() = this.getName().replace("new", "delete").toLowerCase() or
release.getName().toLowerCase() = this.getName().replace("open", "close").toLowerCase() or
release.getName().toLowerCase() = this.getName().replace("allocate", "free").toLowerCase()
)
}
}
from PotentialMemoryLeak allocation
select allocation,
"Potential memory leak: resource allocation method '" + allocation.getName() +
"' without corresponding release method"
```
### 8. Security Quality Gates Workflow
```yaml
# .github/workflows/codeql-security-gates.yml
name: "CodeQL Security Gates"
on:
pull_request:
branches: [ main, develop ]
jobs:
security-gates:
name: Security Quality Gates
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
output: sarif-results
category: "security-gates"
upload-database: false
- name: Check Security Thresholds
id: security-check
run: |
python .github/codeql/scripts/security-gates.py
- name: Fail on Critical Security Issues
if: steps.security-check.outputs.critical_issues > 0
run: |
echo "❌ CRITICAL: ${{ steps.security-check.outputs.critical_issues }} critical security issues found"
echo "Blocking merge due to security policy violations"
exit 1
- name: Warn on High Security Issues
if: steps.security-check.outputs.high_issues > 5
run: |
echo "⚠️ WARNING: ${{ steps.security-check.outputs.high_issues }} high severity issues found"
echo "Consider addressing these issues before merge"
- name: Generate Security Report
if: always()
run: |
echo "## CodeQL Security Quality Gates" >> $GITHUB_STEP_SUMMARY
echo "### Results Summary" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Critical Issues: ${{ steps.security-check.outputs.critical_issues }}" >> $GITHUB_STEP_SUMMARY
echo "- ⚠️ High Issues: ${{ steps.security-check.outputs.high_issues }}" >> $GITHUB_STEP_SUMMARY
echo "- 📝 Medium Issues: ${{ steps.security-check.outputs.medium_issues }}" >> $GITHUB_STEP_SUMMARY
if [ ${{ steps.security-check.outputs.critical_issues }} -eq 0 ]; then
echo "### ✅ Security Gates PASSED" >> $GITHUB_STEP_SUMMARY
else
echo "### ❌ Security Gates FAILED" >> $GITHUB_STEP_SUMMARY
fi
```
### 9. Security Gates Script
```python
# .github/codeql/scripts/security-gates.py
#!/usr/bin/env python3
import json
import os
import sys
from pathlib import Path
def load_sarif_results():
"""Load and parse SARIF results from CodeQL analysis"""
results = []
sarif_dir = Path("sarif-results")
if not sarif_dir.exists():
return results
for sarif_file in sarif_dir.glob("**/*.sarif"):
with open(sarif_file, 'r') as f:
data = json.load(f)
for run in data.get('runs', []):
results.extend(run.get('results', []))
return results
def analyze_severity_distribution(results):
"""Analyze severity distribution of security issues"""
severity_count = {
'critical': 0,
'high': 0,
'medium': 0,
'low': 0
}
for result in results:
# Map CodeQL levels to our severity levels
level = result.get('level', 'warning')
if level == 'error':
severity_count['critical'] += 1
elif level == 'warning':
severity_count['high'] += 1
elif level == 'note':
severity_count['medium'] += 1
else:
severity_count['low'] += 1
return severity_count
def check_security_gates(severity_count):
"""Check if security gates are passed"""
gates_passed = True
# Critical issues always fail the gates
if severity_count['critical'] > 0:
gates_passed = False
# More than 10 high issues fails the gates
if severity_count['high'] > 10:
gates_passed = False
return gates_passed
def main():
results = load_sarif_results()
severity_count = analyze_severity_distribution(results)
gates_passed = check_security_gates(severity_count)
# Set output variables for GitHub Actions
print(f"::set-output name=critical_issues::{severity_count['critical']}")
print(f"::set-output name=high_issues::{severity_count['high']}")
print(f"::set-output name=medium_issues::{severity_count['medium']}")
print(f"::set-output name=low_issues::{severity_count['low']}")
print(f"::set-output name=gates_passed::{str(gates_passed).lower()}")
# Print summary
print("Security Analysis Summary:")
print(f" Critical Issues: {severity_count['critical']}")
print(f" High Issues: {severity_count['high']}")
print(f" Medium Issues: {severity_count['medium']}")
print(f" Low Issues: {severity_count['low']}")
print(f" Security Gates: {'PASSED' if gates_passed else 'FAILED'}")
return 0 if gates_passed else 1
if __name__ == "__main__":
sys.exit(main())
```
### 10. Performance Configuration
```yaml
# .github/codeql/config/performance-config.yml
optimization:
max-paths: 1000
timeout: 300
memory: 8192
threads: 4
analysis:
mode: deep
precision: balanced
caching:
enabled: true
location: ./.codeql/cache
cleanup-age: 30d
max-size: 10GB
logging:
level: INFO
queries: true
performance: true
timing: true
monitoring:
enable-metrics: true
metrics-interval: 60
memory-usage: true
```
### 11. Query Suites Configuration
```ql
// .github/codeql/config/query-suites.qls
- description: "Security and Quality Suite"
- queries: .
from: security-and-quality
- queries: .
from: security-extended
- include:
tags:
- security
- external/cwe/cwe-89
- external/cwe/cwe-79
- external/cwe/cwe-78
- external/cwe/cwe-798
- external/cwe/cwe-259
- exclude:
precision: very-low
- exclude:
kind: example
- description: "Custom Security Queries"
- queries: .
from: custom-security-queries.qls
```
## 🚀 Deployment Instructions
### 1. Initialize the Structure
```bash
# Create directory structure
mkdir -p .github/{workflows,codeql/{config,custom-queries/{Security,Performance,Architecture},scripts}}
# Create all the files as shown above
```
### 2. Set Up Dependencies
```bash
# Install CodeQL CLI (if needed)
wget https://github.com/github/codeql-cli-binaries/releases/latest/download/codeql-linux64.zip
unzip codeql-linux64.zip
sudo mv codeql /usr/local/bin/
# Create custom query pack
cd .github/codeql/custom-queries
codeql pack init custom-security-queries
```
### 3. Commit and Push
```bash
git add .
git commit -m "feat: Add advanced CodeQL configuration"
git push origin main
```
## 🔧 Key Features
### ✅ Advanced Analysis Capabilities
- **Multi-language Support**: Java, JavaScript, Python, Go, C++
- **Custom Query Development**: Advanced security and performance queries
- **Performance Optimization**: Configurable resources and caching
- **Security Quality Gates**: Automated security thresholds
- **Comprehensive Reporting**: Detailed security metrics and dashboards
### ✅ Enterprise-Grade Security
- **Advanced Taint Tracking**: Complex data flow analysis
- **Memory Leak Detection**: Performance and resource management
- **SQL Injection Prevention**: Comprehensive injection detection
- **Security Thresholds**: Configurable quality gates
### ✅ Performance Optimization
- **Parallel Execution**: Multi-language concurrent analysis
- **Resource Management**: Configurable memory and CPU usage
- **Caching Strategy**: Reduced analysis times for subsequent runs
- **Incremental Analysis**: Smart change detection
This advanced CodeQL setup provides enterprise-grade code security analysis with custom rules, performance optimization, and comprehensive security gates!
Create CodeQL Advanced
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the project's security analysis capabilities by introducing a comprehensive "CodeQL Advanced Implementation Guide." This guide provides in-depth instructions and practical examples for leveraging CodeQL's advanced features, such as highly customized scanning configurations, the development of bespoke security and performance queries, and seamless integration into CI/CD workflows with automated quality gates. The addition of this resource aims to empower developers to implement robust, enterprise-grade code security analysis, thereby improving the overall security posture and developer experience. Highlights
Changelog
Ignored Files
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request appears to have a significant discrepancy: the title and description suggest changes to a CONTRIBUTING.md file, but the actual change is the addition of a new file named CodeQL Advanced containing a guide on CodeQL. Please clarify the intent of this PR.
Regarding the new file, I have several points of feedback:
- The filename
CodeQL Advancedis unconventional due to the space and lack of extension. It would be better to rename it, for example, tocodeql_advanced.md. - The provided examples contain some issues:
- An incorrect version for a GitHub Action is used (
@v4instead of the stable@v3). - A Python script for aggregating SARIF reports has a bug that will cause it to fail.
- A code block has a likely typo in its language identifier (
yqlinstead ofyaml).
- An incorrect version for a GitHub Action is used (
I've added specific comments with suggestions for these issues.
I am having trouble creating individual review comments. Click here to see my feedback.
CodeQL Advanced (1)
The filename CodeQL Advanced is unconventional. It contains a space and lacks a file extension. This can cause problems with various tools and makes it difficult to identify the file type. If this is a Markdown file, please consider renaming it to something like codeql_advanced.md to follow common conventions.
CodeQL Advanced (56)
The github/codeql-action/init action is being used with version @v4. The latest stable version of this action is v3. Using @v4 might point to a non-existent or unstable version, which could break the workflow. Please use @v3 for stability.
uses: github/codeql-action/init@v3
CodeQL Advanced (683-686)
There appears to be a bug in how multiple SARIF files are aggregated. load_sarif_results(sarif_file) returns a dictionary, but all_results.extend() will extend the list with the dictionary's keys, not its contents. The subsequent call to analyze_severity_distribution(all_results) will then fail because it expects a dictionary with a runs key, not a list of strings.
To fix this, you should aggregate the runs from each SARIF file. Here's a possible correction:
aggregated_runs = []
for sarif_file in results_dir.glob("*.sarif"):
sarif_data = load_sarif_results(sarif_file)
aggregated_runs.extend(sarif_data.get('runs', []))
all_results = {"runs": aggregated_runs}
severity = analyze_severity_distribution(all_results)CodeQL Advanced (295)
The language identifier yql is used for this code block. This appears to be a typo for yaml or yml. While some renderers might handle this, using the standard yaml identifier will ensure correct syntax highlighting across most platforms.
```yaml
I'll provide a comprehensive and well-documented version of the `first-responder-v2-prs-collect.yml` workflow. This version includes detailed comments, additional steps for robustness, and follows best practices for GitHub Actions.
```yaml
# .github/workflows/first-responder-v2-prs-collect.yml
# Collects pull requests for first responder v2 and sends notifications to Slack.
# Runs every 15 minutes during working hours (Mon-Fri, 9am-5pm UTC).
# Also allows manual trigger via workflow_dispatch.
name: First Responder v2 PRs Collect
on:
schedule:
# Cron syntax: minute hour day-of-month month day-of-week
# Every 15 minutes between 9:00 and 16:45 UTC (last run at 16:45)
# Only on weekdays (1-5 = Monday-Friday)
- cron: "*/15 9-16 * * 1-5"
workflow_dispatch:
# Allow manual triggering with optional inputs (if needed)
inputs:
debug:
description: 'Enable debug logging'
required: false
default: false
type: boolean
# Set permissions for the GITHUB_TOKEN
permissions:
contents: read
pull-requests: read
issues: read
jobs:
collect-prs:
name: Collect PRs and notify Slack
runs-on: ubuntu-latest
# Add timeout to prevent runaway jobs
timeout-minutes: 10
steps:
# Step 1: Check out the repository code
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1 # Shallow clone for speed
# Step 2: Set up Node.js environment
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm' # Cache npm dependencies for faster installs
# Step 3: Install dependencies from package-lock.json
- name: Install dependencies
run: npm ci
# npm ci is faster and uses exact versions from package-lock.json
# Step 4: Run PR collection script with environment variables
- name: Run PR collection script
env:
# GitHub token automatically provided by GitHub Actions
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Slack bot token required to post messages
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
# Slack channel IDs for announcements and join channel
SLACK_ANNOUNCEMENT_CHANNEL_ID: ${{ secrets.SLACK_ANNOUNCEMENT_CHANNEL_ID }}
SLACK_JOIN_CHANNEL_ID: ${{ secrets.SLACK_JOIN_CHANNEL_ID }}
# Optional debug flag if manual trigger with debug
DEBUG: ${{ github.event.inputs.debug && 'true' || '' }}
run: node src/scripts/first-responder-v2/prs-collect.js
# Step 5: (Optional) Notify on failure
- name: Notify Slack on failure
if: failure()
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_ANNOUNCEMENT_CHANNEL_ID: ${{ secrets.SLACK_ANNOUNCEMENT_CHANNEL_ID }}
run: |
curl -X POST -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-type: application/json" \
--data "{
\"channel\": \"$SLACK_ANNOUNCEMENT_CHANNEL_ID\",
\"text\": \":x: First Responder v2 PR collection failed at $(date -u +'%Y-%m-%d %H:%M:%S UTC')\"
}" \
https://slack.com/api/chat.postMessage
```
**Key Features of this Updated YAML:**
- **Detailed comments** explaining each section.
- **Permissions block** to restrict token scope for security.
- **Timeout** to prevent long-running jobs.
- **Caching** for npm dependencies to speed up runs.
- **Manual trigger** with optional `debug` input.
- **Failure notification** step to alert Slack if the script fails.
- **Environment variables** clearly listed.
Make sure you have the required secrets set in your repository:
- `SLACK_BOT_TOKEN`
- `SLACK_ANNOUNCEMENT_CHANNEL_ID`
- `SLACK_JOIN_CHANNEL_ID`
If you need further adjustments or have a different file in mind, let me know!
Tentu, saya akan memberikan lebih banyak detail dan konteks terkait workflow `first-responder-v2-prs-collect.yml` serta komponen-komponennya. Berikut adalah penjelasan mendalam, tips penggunaan, dan kode tambahan untuk memaksimalkan workflow ini.
## 1. Penjelasan Mendalam tentang Cron Schedule
Workflow ini menggunakan cron expression `*/15 9-16 * * 1-5`. Mari kita uraikan:
- `*/15` → Setiap 15 menit (menit 0,15,30,45).
- `9-16` → Jam 9 pagi hingga 4 sore UTC (jam 16). Karena cron menjalankan pada menit ke-0,15,30,45 di jam tersebut, maka run terakhir dimulai pukul 16:45 UTC (setara pukul 23:45 WIB jika UTC+7).
- `*` → Setiap hari dalam bulan.
- `*` → Setiap bulan.
- `1-5` → Senin sampai Jumat (1=Senin, 5=Jumat).
### Mengubah ke Zona Waktu Lokal
Jika Anda ingin menjalankan workflow sesuai jam kerja di Indonesia (misal 09:00–17:00 WIB), Anda bisa menyesuaikan cron dengan mempertimbangkan offset UTC. Contoh untuk WIB (UTC+7):
```yaml
# 09:00–17:00 WIB = 02:00–10:00 UTC
on:
schedule:
- cron: "*/15 2-9 * * 1-5" # Setiap 15 menit jam 2–9 UTC
```
Perhatikan bahwa jam 10:00 UTC = 17:00 WIB, tapi menit terakhir di jam 9 adalah 09:45 UTC = 16:45 WIB. Jika ingin sampai jam 17:00 WIB (10:00 UTC), Anda perlu menjadwalkan di jam 10 juga, tapi hanya di menit 0 agar tidak berjalan setelah jam 17:00 WIB. Anda bisa menggunakan multiple cron lines:
```yaml
on:
schedule:
- cron: "*/15 2-9 * * 1-5" # 09:00–16:45 WIB
- cron: "0 10 * * 1-5" # 17:00 WIB tepat
```
## 2. Variabel Lingkungan dan Secret yang Diperlukan
Workflow ini menggunakan tiga Slack channel ID:
- `SLACK_ANNOUNCEMENT_CHANNEL_ID`: Channel untuk pengumuman penting, misalnya ringkasan PR yang dikumpulkan.
- `SLACK_JOIN_CHANNEL_ID`: Channel khusus untuk mengundang anggota baru atau notifikasi onboarding.
- `SLACK_BOT_TOKEN`: Token bot Slack dengan hak akses `chat:write` dan `channels:join` (jika perlu mengundang bot ke channel).
**Cara mendapatkan Slack Bot Token dan Channel ID:**
1. Buat aplikasi Slack di [api.slack.com/apps](https://api.slack.com/apps).
2. Tambahkan scope `chat:write` dan `channels:join` (atau `groups:write` untuk private channel).
3. Install aplikasi ke workspace Anda.
4. Salin Bot User OAuth Token (mulai dengan `xoxb-`).
5. Untuk mendapatkan Channel ID, buka channel di Slack, klik nama channel di bagian atas, dan sali ID dari URL (biasanya diawali `C` atau `G`).
Tambahkan semua nilai tersebut sebagai **repository secrets** di GitHub (Settings > Secrets and variables > Actions).
## 3. Script `prs-collect.js` – Contoh Sederhana
Workflow ini menjalankan script Node.js. Berikut adalah contoh minimal script yang mungkin digunakan (anda dapat menyesuaikan dengan logika Anda sendiri):
```javascript
// src/scripts/first-responder-v2/prs-collect.js
const { Octokit } = require('@octokit/rest');
const { WebClient } = require('@slack/web-api');
// Inisialisasi klien
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);
async function collectPRs() {
try {
// Contoh: ambil PR terbuka di repo tertentu
const { data: pullRequests } = await octokit.pulls.list({
owner: 'sazwan96',
repo: 'sazwanismail', // ganti dengan repo Anda
state: 'open'
});
console.log(`Ditemukan ${pullRequests.length} PR terbuka.`);
// Kirim notifikasi ke Slack
if (pullRequests.length > 0) {
const message = {
channel: process.env.SLACK_ANNOUNCEMENT_CHANNEL_ID,
text: `Ada ${pullRequests.length} PR baru yang perlu direview!`,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*Daftar PR Terbuka:*`
}
},
...pullRequests.map(pr => ({
type: 'section',
text: {
type: 'mrkdwn',
text: `<${pr.html_url}|#${pr.number}: ${pr.title}> oleh @${pr.user.login}`
}
}))
]
};
await slack.chat.postMessage(message);
} else {
// Opsional: kirim pesan bahwa tidak ada PR
await slack.chat.postMessage({
channel: process.env.SLACK_ANNOUNCEMENT_CHANNEL_ID,
text: 'Tidak ada PR terbuka saat ini.'
});
}
// Kirim pesan ke join channel (misal untuk onboarding)
await slack.chat.postMessage({
channel: process.env.SLACK_JOIN_CHANNEL_ID,
text: 'Workflow PR collection berjalan dengan sukses.'
});
} catch (error) {
console.error('Error:', error);
// Opsional: kirim notifikasi error ke Slack
await slack.chat.postMessage({
channel: process.env.SLACK_ANNOUNCEMENT_CHANNEL_ID,
text: `Terjadi error: ${error.message}`
});
process.exit(1);
}
}
collectPRs();
```
Pastikan Anda menginstal dependencies yang diperlukan:
```bash
npm install @octokit/rest @slack/web-api
```
## 4. Menambahkan Logging dan Monitoring
Untuk memudahkan debugging, Anda dapat menambahkan step yang meng-upload log sebagai artifact jika terjadi error:
```yaml
- name: Upload logs on failure
if: failure()
uses: actions/upload-artifact@v3
with:
name: error-logs
path: /home/runner/.npm/_logs/
retention-days: 5
```
## 5. Menambahkan Step untuk Menjalankan Test Sebelum Collect
Jika Anda ingin memastikan script berfungsi sebelum menjalankan koleksi PR, Anda bisa menambahkan step test:
```yaml
- name: Run tests
run: npm test
```
## 6. Menjadwalkan dengan Input Manual yang Lebih Fleksibel
Anda dapat memperluas `workflow_dispatch` dengan input untuk memilih repositori target atau mode debug:
```yaml
on:
workflow_dispatch:
inputs:
repo:
description: 'Repository to scan (format: owner/repo)'
required: false
default: 'sazwan96/sazwanismail'
debug:
description: 'Enable debug logging'
required: false
default: false
type: boolean
```
Kemudian di script, baca input tersebut:
```javascript
const repoFullName = process.env.INPUT_REPO || 'sazwan96/sazwanismail';
const [owner, repo] = repoFullName.split('/');
```
## 7. Keamanan: Menggunakan GitHub App Token
Jika Anda membutuhkan akses yang lebih aman atau spesifik, pertimbangkan untuk menggunakan GitHub App token daripada `GITHUB_TOKEN`. Anda bisa menggunakan action `tibdex/github-app-token` untuk menghasilkan token dengan izin terbatas.
## 8. Alternatif: Menggunakan Action `schedule` dengan If Condition
Jika Anda ingin mengontrol eksekusi berdasarkan kondisi tertentu (misal hanya jika ada perubahan file tertentu), Anda bisa menambahkan conditional step:
```yaml
- name: Check if script changed
id: changed
uses: tj-actions/changed-files@v35
with:
files: |
src/scripts/first-responder-v2/prs-collect.js
.github/workflows/first-responder-v2-prs-collect.yml
- name: Run PR collection only if relevant files changed
if: steps.changed.outputs.any_changed == 'true'
run: node src/scripts/first-responder-v2/prs-collect.js
```
## 9. Integrasi dengan Database atau API Eksternal
Jika Anda perlu menyimpan hasil koleksi PR ke database atau memanggil API eksternal, tambahkan step tersebut di dalam script atau sebagai step terpisah.
## 10. Notifikasi ke Multiple Channel
Anda bisa mengirim notifikasi ke lebih dari dua channel dengan menambahkan variabel lingkungan tambahan:
```yaml
env:
SLACK_CHANNEL_1: ${{ secrets.SLACK_CHANNEL_1 }}
SLACK_CHANNEL_2: ${{ secrets.SLACK_CHANNEL_2 }}
```
Lalu di script, Anda bisa memposting ke semua channel yang didefinisikan.
---
Dengan semua tambahan ini, workflow Anda menjadi lebih powerful, fleksibel, dan mudah dipelihara. Jika ada bagian spesifik yang ingin didalami atau ditambahkan, beri tahu saya!
Create Development
Contributing to [Project Name]
Thank you for considering contributing to [Project Name]! This document outlines the process and guidelines for contributing.
Table of Contents
Code of Conduct
This project adheres to the Bitcoin Code of Conduct. By participating, you are expected to uphold this code.
Getting Started
Development Process
masterbranch. Pull requests (PRs) should be made againstmaster.Coding Standards
clang-formatwith the provided.clang-formatconfiguration.make lint(or equivalent) to check for style violations.Testing
make check.Submitting Changes
master.git commit -sto add a Signed-off-by line.master.Developer Certificate of Origin (DCO)
We require that all contributors sign the Developer Certificate of Origin. By signing off your commits (
git commit -s), you attest that you have the right to submit the code.Communication
#bitcoin-core-devon Libera.Chat or the Bitcoin Core Matrix channel.License
By contributing, you agree that your contributions will be licensed under the same license as the project (e.g., MIT). See LICENSE for details.
Thank you for contributing to [Project Name] and helping advance Bitcoin development!
