Skip to content

Sazwanismail patch 4#8

Merged
Sazwanend merged 12 commits into
Sazwanend:masterfrom
Sazwanismail:Sazwanismail-patch-4
Mar 16, 2026
Merged

Sazwanismail patch 4#8
Sazwanend merged 12 commits into
Sazwanend:masterfrom
Sazwanismail:Sazwanismail-patch-4

Conversation

@Sazwanismail
Copy link
Copy Markdown

To re-run or update a GitHub Actions workflow file named cmake-single-platform.yml, you have a couple of options depending on what you want to achieve:


1. Re‑run an Existing Workflow Run

If the workflow already ran (e.g., it failed) and you want to trigger it again with the same code and configuration:

Using the GitHub Web Interface

  1. Go to your repository on GitHub.
  2. Click the Actions tab.
  3. In the left sidebar, select the workflow CMake Single Platform (or the name defined in the file).
  4. You’ll see a list of workflow runs. Click on the run you want to re‑run.
  5. In the top‑right corner, click Re‑run jobs and choose:
    • Re‑run all jobs – to execute every job again.
    • Re‑run failed jobs – to only re‑execute the jobs that failed.

Using the GitHub CLI (gh)

If you have the GitHub CLI installed, you can re‑run a specific run:

gh run rerun <run-id>

Find the run ID with gh run list.

Using the GitHub API

You can also trigger a re‑run via the API, but the UI and CLI are simpler for most cases.


2. Update the Workflow File (cmake-single-platform.yml)

If you need to change the workflow logic – for example, update the CMake version, add a new step, or change the trigger events – you must edit the YAML file itself.

Steps to Update

  1. Locate the file
    The workflow file is stored in your repository under
    .github/workflows/cmake-single-platform.yml

  2. Edit the file
    You can edit it directly on GitHub:

    • Navigate to the file in your repository.
    • Click the pencil icon (Edit this file).
    • Make your changes.

    Or edit locally:

    git pull
    # edit .github/workflows/cmake-single-platform.yml with your favourite editor
    git add .github/workflows/cmake-single-platform.yml
    git commit -m "Update CMake workflow"
    git push
  3. Commit the changes
    After pushing the updated file to the default branch (or to a branch that triggers the workflow), the next time the workflow runs it will use the new version.

Important Notes

  • Triggers: The workflow runs according to the on: events defined in the file. If you change the triggers, the new behaviour takes effect after the commit.
  • Manual trigger: If the workflow has a workflow_dispatch event, you can also trigger it manually from the Actions tab after the update.
  • Validation: GitHub will validate the YAML syntax automatically. If there’s an error, the workflow may not run, and you’ll see a warning on the Actions tab.

Summary

Action How to do it
Re‑run an existing run Use the Actions tab in GitHub, the gh CLI, or the API.
Update the workflow file Edit .github/workflows/cmake-single-platform.yml and commit the changes.

If you have a more specific scenario (e.g., you want to re‑run a workflow on a different branch or with different inputs), feel free to provide more details!

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
[![SLSA Publish](https://github.com/Sazwanismail/bitcoin/actions/workflows/generator-generic-ossf-slsa3-publish.yml/badge.svg?branch=master)](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
[![SLSA Publish](https://github.com/Sazwanismail/bitcoin/actions/workflows/generator-generic-ossf-slsa3-publish.yml/badge.svg?branch=master&event=workflow_dispatch)](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**: ![](https://img.shields.io/badge/SLSA-passing-brightgreen)
- **Failing**: ![](https://img.shields.io/badge/SLSA-failing-red)
- **In Progress**: ![](https://img.shields.io/badge/SLSA-pending-yellow)

### 5. Recommended Placement:
Add both badges together for better visibility:
```markdown
## Build Status

[![CI](https://github.com/Sazwanismail/bitcoin/actions/workflows/ci.yml/badge.svg?branch=master&event=workflow_dispatch)](https://github.com/Sazwanismail/bitcoin/actions/workflows/ci.yml)
[![SLSA Level 3](https://github.com/Sazwanismail/bitcoin/actions/workflows/generator-generic-ossf-slsa3-publish.yml/badge.svg?branch=master)](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!
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!
# Updated CMake Single Platform GitHub Actions Workflow

This repository provides an up-to-date GitHub Actions workflow for building CMake projects on a single platform (Linux, macOS, or Windows). It includes:

- CMake configuration and build
- Caching for dependencies (vcpkg, ccache)
- Multiple build types (Debug, Release)
- Running tests with CTest
- Uploading build artifacts
- Code formatting and linting (optional)

## 📄 Workflow File: `.github/workflows/cmake-single-platform.yml`

```yaml
name: CMake Single Platform Build

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:  # Allow manual trigger

env:
  BUILD_TYPE: Release
  # Customize CMake build type if needed

jobs:
  build:
    # Choose the runner: ubuntu-latest, windows-latest, or macos-latest
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    # ===== SETUP DEPENDENCIES =====
    - name: Install Linux dependencies (if any)
      if: runner.os == 'Linux'
      run: |
        sudo apt-get update
        sudo apt-get install -y ninja-build ccache
        # Add other packages as needed

    - name: Install macOS dependencies
      if: runner.os == 'macOS'
      run: |
        brew install ninja ccache
        # Add other packages

    - name: Install Windows dependencies (using Chocolatey)
      if: runner.os == 'Windows'
      run: |
        choco install ninja ccache
        # Or use vcpkg (see below)

    # ===== CACHE MANAGEMENT =====
    - name: Cache ccache
      uses: actions/cache@v4
      with:
        path: ~/.ccache
        key: ${{ runner.os }}-ccache-${{ github.sha }}
        restore-keys: ${{ runner.os }}-ccache-

    - name: Cache vcpkg (if used)
      if: false  # Enable if you use vcpkg
      uses: actions/cache@v4
      with:
        path: |
          ~/.cache/vcpkg
          build/vcpkg_installed
        key: ${{ runner.os }}-vcpkg-${{ hashFiles('**/vcpkg.json') }}
        restore-keys: ${{ runner.os }}-vcpkg-

    # ===== CONFIGURE & BUILD =====
    - name: Configure CMake
      run: |
        cmake -B build -S . \
          -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
          -G Ninja \
          -DCMAKE_C_COMPILER_LAUNCHER=ccache \
          -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
      env:
        CC: clang   # Override compiler if needed (gcc, clang, cl)
        CXX: clang++

    - name: Build
      run: cmake --build build --config ${{ env.BUILD_TYPE }} --parallel

    # ===== TEST =====
    - name: Test
      working-directory: build
      run: ctest -C ${{ env.BUILD_TYPE }} --output-on-failure --parallel

    # ===== CODE QUALITY (optional) =====
    - name: Run clang-format lint
      if: false  # Enable if you want formatting checks
      uses: jidicula/clang-format-action@v4.11.0
      with:
        clang-format-version: '16'
        check-path: 'src'

    # ===== ARTIFACTS =====
    - name: Upload build artifacts
      uses: actions/upload-artifact@v4
      with:
        name: ${{ runner.os }}-${{ env.BUILD_TYPE }}-binaries
        path: |
          build/bin
          build/lib
          build/*.exe
          build/*.dll
          build/*.so
          build/*.dylib
        if-no-files-found: ignore
```

## 🔧 Customization Tips

1. **Runner OS**: Change `runs-on` to `windows-latest` or `macos-latest` as needed.
2. **Dependencies**: Adjust package installation steps for your specific libraries.
3. **vcpkg**: If your project uses vcpkg, enable the vcpkg cache step and install vcpkg in a setup step.
4. **Compiler**: Override `CC` and `CXX` environment variables to use different compilers (e.g., `gcc`, `clang`, `msvc`).
5. **Build Types**: You can matrix over `BUILD_TYPE` to build both Debug and Release, or add a strategy matrix.
6. **Artifacts**: Customize the artifact paths to match your output locations.

## 📦 Example with vcpkg and Matrix

If you need multiple build types or configurations, extend with a matrix:

```yaml
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        build_type: [Debug, Release]
    env:
      BUILD_TYPE: ${{ matrix.build_type }}
    steps:
      # ... steps (use matrix.os and matrix.build_type)
```

## ✅ Best Practices Included

- **Caching** with ccache and vcpkg speeds up rebuilds.
- **Ninja** generator for faster builds.
- **Parallel** builds and tests.
- **Artifact** upload for easy access to binaries.
- **Manual trigger** (`workflow_dispatch`) for ad-hoc runs.

## 🔗 References

- [GitHub Actions Documentation](https://docs.github.com/actions)
- [CMake Documentation](https://cmake.org/cmake/help/latest/)
- [vcpkg with GitHub Actions](https://vcpkg.io/en/getting-started.html)

---

**Maintainer:** Your Team  
**License:** MIT
# Updated Advanced CMake Single/Multi-Platform Workflow

This workflow provides a robust CI pipeline for CMake projects, supporting multiple operating systems and build configurations. It includes caching, testing, code coverage, static analysis, and artifact upload.

## 📄 `.github/workflows/cmake-advanced.yml`

```yaml
name: CMake Advanced CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:        # Allow manual trigger

env:
  # Global build type; can be overridden per matrix
  BUILD_TYPE: Release

jobs:
  build:
    name: ${{ matrix.os }} / ${{ matrix.build_type }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false      # Continue other jobs if one fails
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        build_type: [Debug, Release]
        # Optionally exclude some combinations
        # exclude:
        #   - os: windows-latest
        #     build_type: Debug

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    # ===== DEPENDENCY INSTALLATION =====
    - name: Install Linux dependencies
      if: runner.os == 'Linux'
      run: |
        sudo apt-get update
        sudo apt-get install -y \
          ninja-build \
          ccache \
          lcov \
          clang-tidy \
          curl \
          zip
        # Add project-specific packages here

    - name: Install macOS dependencies
      if: runner.os == 'macOS'
      run: |
        brew install \
          ninja \
          ccache \
          llvm      # provides clang-tidy, lcov
        # Ensure llvm binaries are in PATH
        echo "$(brew --prefix llvm)/bin" >> $GITHUB_PATH

    - name: Install Windows dependencies
      if: runner.os == 'Windows'
      run: |
        choco install ninja ccache
        # vcpkg is usually installed on GitHub runners; if needed, bootstrap:
        # git clone https://github.com/Microsoft/vcpkg.git
        # .\vcpkg\bootstrap-vcpkg.bat
        # echo "${{ github.workspace }}/vcpkg" >> $GITHUB_PATH

    # ===== CACHE SETUP =====
    - name: Cache ccache
      uses: actions/cache@v4
      with:
        path: ~/.ccache
        key: ${{ runner.os }}-ccache-${{ matrix.build_type }}-${{ github.sha }}
        restore-keys: |
          ${{ runner.os }}-ccache-${{ matrix.build_type }}-
          ${{ runner.os }}-ccache-

    - name: Cache vcpkg (if used)
      if: false   # Enable if you use vcpkg.json manifest mode
      uses: actions/cache@v4
      with:
        path: |
          ~/.cache/vcpkg
          ${{ github.workspace }}/build/vcpkg_installed
        key: ${{ runner.os }}-vcpkg-${{ hashFiles('**/vcpkg.json') }}
        restore-keys: ${{ runner.os }}-vcpkg-

    # ===== CONFIGURE CMAKE =====
    - name: Configure CMake
      shell: bash
      run: |
        cmake -B build -S . \
          -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
          -G Ninja \
          -DCMAKE_C_COMPILER_LAUNCHER=ccache \
          -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
          -DCMAKE_EXPORT_COMPILE_COMMANDS=ON   # for clang-tidy

    # ===== BUILD =====
    - name: Build
      run: cmake --build build --config ${{ matrix.build_type }} --parallel

    # ===== RUN TESTS =====
    - name: Test
      working-directory: build
      run: ctest -C ${{ matrix.build_type }} --output-on-failure --parallel

    # ===== STATIC ANALYSIS (clang-tidy) =====
    - name: Run clang-tidy
      if: runner.os == 'Linux' && matrix.build_type == 'Debug'   # Run once to avoid duplication
      working-directory: build
      run: |
        # Adjust source directory and checks as needed
        run-clang-tidy -p . -extra-arg=-Wno-unknown-warning-option -quiet

    # ===== CODE COVERAGE (Linux only) =====
    - name: Generate coverage report
      if: runner.os == 'Linux' && matrix.build_type == 'Debug' && github.event_name == 'push'
      run: |
        # Ensure you have built with coverage flags: -fprofile-arcs -ftest-coverage
        lcov --directory . --capture --output-file coverage.info
        lcov --remove coverage.info '/usr/*' --output-file coverage.info
        lcov --list coverage.info
      working-directory: build

    - name: Upload coverage to Codecov
      if: runner.os == 'Linux' && matrix.build_type == 'Debug' && github.event_name == 'push'
      uses: codecov/codecov-action@v4
      with:
        files: build/coverage.info
        flags: unittests
        name: codecov-umbrella
        fail_ci_if_error: false
        token: ${{ secrets.CODECOV_TOKEN }}

    # ===== UPLOAD ARTIFACTS =====
    - name: Prepare artifacts
      shell: bash
      run: |
        mkdir -p artifacts
        # Copy binaries, libraries, etc.
        if [ -d build/bin ]; then cp -r build/bin artifacts/; fi
        if [ -d build/lib ]; then cp -r build/lib artifacts/; fi
        # Include compile_commands.json for debugging
        cp build/compile_commands.json artifacts/ || true

    - name: Upload build artifacts
      uses: actions/upload-artifact@v4
      with:
        name: ${{ runner.os }}-${{ matrix.build_type }}-artifacts
        path: artifacts/
```

## 🚀 Key Features

- **Matrix Build**: Builds on Ubuntu, Windows, and macOS with both Debug and Release configurations.
- **Caching**: Uses `ccache` to speed up rebuilds; vcpkg cache ready.
- **Dependencies**: Installs `ninja`, `ccache`, and platform-specific tools.
- **Static Analysis**: Runs `clang-tidy` (on Linux/Debug once).
- **Code Coverage**: Generates and uploads coverage reports to Codecov (Linux/Debug only).
- **Artifacts**: Uploads binaries, libraries, and `compile_commands.json`.

## 🔧 Customization

- **Add more packages**: Modify the dependency installation steps.
- **Adjust coverage**: Ensure your CMake project enables coverage flags when `CMAKE_BUILD_TYPE` is Debug.
- **vcpkg**: Uncomment the cache step and add a vcpkg installation step if needed.
- **Compiler**: Override `CC`/`CXX` in the configure step to use specific compilers.
- **Artifacts**: Modify the `Prepare artifacts` step to capture your desired output.

## ✅ Best Practices

- **fail-fast: false** allows all matrix jobs to run even if one fails.
- **Conditional steps** avoid redundant work (e.g., coverage only once).
- **Caching keys** use both OS and build type to avoid mixing caches.
- **Parallel** builds and tests reduce CI time.

## 📚 References

- [GitHub Actions Documentation](https://docs.github.com/actions)
- [CMake Documentation](https://cmake.org/documentation)
- [Codecov Action](https://github.com/codecov/codecov-action)
- [clang-tidy Integration](https://clang.llvm.org/extra/clang-tidy/)

---

**Maintainer:** Your Team  
**License:** MIT
# Building a SLSA3‑Compliant Development Workflow: A Practical Guide

You’ve asked to “Create development” – and that’s exactly what we’ll do. Below is a **step‑by‑step blueprint** for setting up a development environment and process that meets SLSA Level 3 requirements while remaining practical for everyday coding. This guide builds on everything we’ve discussed and gives you a concrete path forward.

## 🎯 Goal
Establish a development pipeline where every artifact (commits, builds, releases) carries verifiable proof of its origin and integrity, satisfying SLSA Build Level 3 and setting the foundation for higher levels.

---

## 📦 Phase 1: Repository Foundation

### 1.1 Enable Signed Commits
- **What**: Require that every commit is signed with a GPG, SSH, or S/MIME key.
- **How**:
  - Generate a signing key (GPG: `gpg --full-generate-key`).
  - Add the public key to your GitHub/GitLab account.
  - Configure Git locally:  
    ```bash
    git config --global user.signingkey <key-id>
    git config --global commit.gpgsign true
    ```
- **Why**: Establishes a chain of custody from developer to code, which is part of the source integrity expected by SLSA.

### 1.2 Branch Protection Rules
- **Require signed commits** on all protected branches (main, release/*).
- **Require pull request reviews** before merging.
- **Optionally require** that all status checks pass (including any SLSA verification steps you add later).

### 1.3 Dependency Locking
- Use lock files (`go.sum`, `package-lock.json`, `Cargo.lock`, etc.) to pin dependency versions.
- Commit these lock files to the repository.

---

## 🛠️ Phase 2: Local Developer Environment

### 2.1 Containerized Development Environment
- Provide a `Dockerfile` or Dev Container configuration that mirrors your CI build environment.
- Example `.devcontainer/devcontainer.json`:
  ```json
  {
    "name": "MyApp Dev",
    "build": { "dockerfile": "Dockerfile" },
    "features": {
      "ghcr.io/devcontainers/features/common-utils:2": {}
    }
  }
  ```
- This ensures builds are reproducible and eliminates “works on my machine” discrepancies.

### 2.2 Pre‑commit Hooks for Security
- Use [pre-commit](https://pre-commit.com/) to run:
  - **Dependency hash verification** (e.g., check `go.sum` against a known good state).
  - **Linting and static analysis**.
  - **Secret scanning** (e.g., `detect-secrets` or `truffleHog`).
- Example `.pre-commit-config.yaml`:
  ```yaml
  repos:
    - repo: local
      hooks:
        - id: verify-deps
          name: Verify dependencies
          entry: scripts/verify-deps.sh
          language: script
          files: '.*\.(mod|sum|lock)$'
    - repo: https://github.com/pre-commit/pre-commit-hooks
      rev: v4.4.0
      hooks:
        - id: detect-aws-credentials
        - id: detect-private-key
  ```

### 2.3 Local Build with Provenance (Optional but Recommended)
- For testing, you can generate lightweight attestations using [in-toto](https://in-toto.io/).
- Example wrapper script `local-build.sh`:
  ```bash
  #!/bin/bash
  in-toto-run --step-name local-build --products myapp --key mykey -- ./build.sh
  ```
- This creates a link file that you can keep locally for debugging.

---

## 🔁 Phase 3: Continuous Integration (CI) Pipeline

### 3.1 Reusable Build Workflow
Create a reusable workflow (`.github/workflows/build.yml`) that encapsulates your build steps and outputs artifact hashes.

```yaml
name: Reusable Build

on:
  workflow_call:
    outputs:
      base64-subjects:
        description: "Base64-encoded subjects (artifacts with digests)"
        value: ${{ jobs.build.outputs.base64-subjects }}

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      base64-subjects: ${{ steps.hashes.outputs.base64_subjects }}
    steps:
      - uses: actions/checkout@v4
      - run: make build
      - run: mkdir -p artifacts && cp bin/* artifacts/
      - id: hashes
        run: |
          cd artifacts
          subjects="[]"
          for file in *; do
            hash=$(sha256sum "$file" | cut -d' ' -f1)
            subjects=$(jq -c --arg name "$file" --arg hash "sha256:$hash" \
                      '. += [{"name": $name, "digest": $hash}]' <<< "$subjects")
          done
          echo "base64_subjects=$(echo -n "$subjects" | base64 -w0)" >> $GITHUB_OUTPUT
      - uses: actions/upload-artifact@v4
        with:
          name: build-artifacts-${{ github.run_id }}
          path: artifacts/
```

### 3.2 Main CI Workflow (PRs and Merges)
Create a main workflow (`.github/workflows/ci.yml`) that calls the reusable build and then verifies dependencies.

```yaml
name: CI

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read
  id-token: write   # Needed if you verify provenance of dependencies

jobs:
  build:
    uses: ./.github/workflows/build.yml

  verify-deps:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Download dependency provenance
        run: |
          # Example: verify a third-party binary used in build
          curl -LO https://example.com/dependency.bin
          curl -LO https://example.com/dependency.intoto.jsonl
          slsa-verifier verify-artifact \
            --provenance-path dependency.intoto.jsonl \
            --source-uri github.com/trusted-owner/dependency \
            --builder-id trusted-builder-id \
            dependency.bin
```

### 3.3 Release Workflow with SLSA3 Provenance
Create a separate workflow (`.github/workflows/release.yml`) triggered on tags or release publication.

```yaml
name: Release

on:
  release:
    types: [published]

permissions:
  id-token: write
  attestations: write
  contents: write
  actions: read

jobs:
  build:
    uses: ./.github/workflows/build.yml

  provenance:
    needs: build
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
    with:
      base64-subjects: ${{ needs.build.outputs.base64-subjects }}
      upload-artifacts-name: build-artifacts-${{ github.run_id }}
      upload-assets: true

  verify-and-publish:
    needs: provenance
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build-artifacts-${{ github.run_id }}
          path: artifacts/

      - name: Verify provenance
        run: |
          gh attestation verify artifacts/myapp \
            --owner ${{ github.repository_owner }} \
            --signer-repo slsa-framework/slsa-github-generator

      - name: Upload to release
        run: |
          gh release upload ${{ github.event.release.tag_name }} artifacts/* provenance.json
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

---

## 🔐 Phase 4: Verification Gate Before Deployment

### 4.1 Deployment Job
In the release workflow (or a separate deployment workflow), add a final verification step:

```yaml
deploy:
  needs: verify-and-publish
  runs-on: ubuntu-latest
  environment: production
  steps:
    - name: Verify attestation again (defense in depth)
      run: |
        gh attestation verify artifacts/myapp \
          --owner ${{ github.repository_owner }}
    - name: Deploy
      run: ./deploy.sh artifacts/
```

### 4.2 Enforce Verification in Production Environment
- Configure GitHub Environments with **required reviewers**.
- Optionally, use a deployment protection rule that calls an external verification service (e.g., via a custom GitHub Action).

---

## 📘 Phase 5: Developer Onboarding & Documentation

Create a `CONTRIBUTING.md` or `DEVELOPMENT.md` that covers:
- How to set up the local environment (Docker, pre‑commit, signing keys).
- How to run a local build that mimics CI.
- How to interpret verification failures.
- Where to find provenance files and how to manually verify them.

Example section:

```markdown
## Verifying Artifacts Locally

After a CI build, you can download the provenance file from the workflow run and verify it:

```bash
gh attestation verify myapp --owner myorg
```

Or using the `slsa-verifier` tool:

```bash
slsa-verifier verify-artifact \
  --provenance-path provenance.json \
  --source-uri github.com/myorg/myapp \
  myapp
```
```

---

## 🧪 Phase 6: Testing the Pipeline

1. **Test a pull request**: Push a change, ensure the CI workflow runs, and that dependency verification passes.
2. **Create a pre‑release**: Tag a commit, push the tag, and trigger the release workflow. Download the artifacts and verify them manually.
3. **Simulate a tampering attempt**: Modify an artifact locally and try to verify it – the verification should fail.
4. **Rotate keys**: If using GPG for commit signing, practice rotating a developer key and updating the repository settings.

---

## 📈 Ongoing Maintenance

- Keep the SLSA generator version up to date (check for releases at [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator/releases)).
- Periodically review dependency verification rules.
- Update developer documentation as tooling evolves.

---

## 🎉 You’re Now SLSA3‑Ready

By following this guide, your development workflow will:
- Produce **non‑forgeable provenance** for every release.
- Ensure **source integrity** through signed commits.
- Provide **reproducible builds** via containerized environments.
- Build a **culture of security** where every developer understands and participates in supply chain protection.

This is a living process – adapt it to your team’s size, tech stack, and release cadence. And remember, the SLSA community is constantly improving tooling and practices; stay engaged to keep your pipeline cutting‑edge.

Would you like help with any specific part, such as setting up the containerized environment or writing the reusable workflow? I’m here to assist!
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, 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 introduces a new documentation file, 'Development', which serves as a comprehensive guide for integrating SLSA Level 3 (SLSA3) principles into the software development workflow. It provides actionable steps and best practices for developers to enhance supply chain security, covering aspects from dependency verification and reproducible builds to secure CI/CD integration, thereby fostering a culture of security from coding to deployment.

Highlights

  • New Documentation Added: A new file named 'Development' was added, containing a comprehensive guide on integrating SLSA3 principles into the development workflow.
  • SLSA3 Integration Guidance: The guide details how to integrate SLSA Level 3 (SLSA3) principles, covering dependency management, local build reproducibility, commit signing, and early security scanning.
  • CI/CD and Attestations: It outlines the use of in-toto attestations for development artifacts and best practices for CI/CD integration to shift left with SLSA checks.
  • Practical Examples and Resources: The document includes a practical example of a developer's daily routine with SLSA3 integrated and lists relevant resources for further implementation.
Changelog
  • Development
    • Added a new guide detailing SLSA3 integration into the development workflow.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/cmake-single-platform.yml
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a new documentation file, Development, which provides a guide on integrating SLSA3 principles. My review focuses on an issue at the end of the file where conversational text appears to have been included erroneously. I have provided a suggestion to remove this content to improve the document's clarity.

Comment thread Development
To help you **update and rename "CodeQL Advanced" to "License Agreement (CLA)"**, I need to know exactly what you're working with. However, I can give you a **general approach** based on common scenarios. If you can provide more details (file type, location, purpose), I can tailor the answer precisely.

---

### **Possible Scenarios & Solutions**

#### **Scenario 1: You have a GitHub Actions workflow file named `codeql-advanced.yml`**
You want to rename it to `cla.yml` and update its content to handle CLA signing records (like the data for Muhamad Sazwan bin Ismail).

**Steps:**
1. **Rename the file**  
   In your repository, navigate to `.github/workflows/` and rename `codeql-advanced.yml` to `cla.yml` (or `license-agreement.yml`).

2. **Update the workflow name** (inside the file)  
   Change the `name:` field from something like `CodeQL Advanced` to `License Agreement (CLA)`.

3. **Replace the steps**  
   Remove all CodeQL-related steps and add steps that interact with your database (SQL/NoSQL) to record CLA signatures.  
   Example placeholder workflow:

```yaml
name: License Agreement (CLA)

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  check-cla:
    runs-on: ubuntu-latest
    steps:
      - name: Check CLA signature
        run: |
          # Example: Query your database to see if contributor signed CLA
          echo "Checking CLA for ${{ github.event.pull_request.user.login }}"
          # You'd use a script here that checks against your DB
```

#### **Scenario 2: You have a database table or collection named `codeql_advanced`**
You want to rename it to `cla_records` and update its schema/structure to store CLA data (like the examples for Muhamad Sazwan).

**SQL Example:**
```sql
-- Rename table
ALTER TABLE codeql_advanced RENAME TO cla_records;

-- Update columns if needed
ALTER TABLE cla_records ADD COLUMN signed_at TIMESTAMP;
-- etc.
```

**NoSQL (MongoDB) Example:**
```javascript
// Rename collection
db.codeql_advanced.renameCollection("cla_records");

// Update documents to new structure (if needed)
db.cla_records.updateMany({}, { $rename: { "oldField": "newField" } });
```

#### **Scenario 3: You have a code file or class named `CodeQLAdvanced`**
You want to rename it to `LicenseAgreementCLA` and update its logic.

**Example in Python:**
```python
# Rename class
class LicenseAgreementCLA:
    def __init__(self, contributor_name):
        self.contributor = contributor_name
        # ... other CLA-related logic
```

---

### **Please clarify:**
- What type of item are you renaming? (file, table, class, etc.)
- Where is it located? (GitHub repo, local project, database)
- What should the new version do? (record CLA signatures, manage agreements, etc.)

Once I know these, I can give you the exact commands or code modifications.
Update and rename CodeQL Advanced to  License Agreement (CLA).
@Sazwanend Sazwanend merged commit 0ab516f into Sazwanend:master Mar 16, 2026
1 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants