sherlock-project/sherlock

4 workflows · maturity 17% · 2 patterns · GitHub ↗

Security 0/100

Practices

✓ Matrix○ Permissions○ Security scan○ AI review○ Cache○ Concurrency○ Reusable workflows

Detected patterns

Security dimensions

permissions
0
security scan
0
supply chain
0
secret handling
0
harden runner
0

Workflows (4)

exclusions .github/workflows/exclusions.yml
Triggers
schedule, workflow_dispatch
Runs on
ubuntu-latest
Jobs
update-exclusions
Actions
abatilo/actions-poetry
Commands
  • poetry install --no-interaction --with dev
  • $(poetry env activate) pytest -q --tb no -m validate_targets_fp -n 20 | tee fp_test_results.txt deactivate
  • grep -oP '(?<=test_false_pos\[)[^\]]+(?=\].*result was Claimed)' fp_test_results.txt \ | sort -u > false_positive_exclusions.txt grep -oP '(?<=test_false_pos\[)[^\]]+(?=\].*result was WAF)' fp_test_results.txt \ | sort -u > waf_hits.txt
  • git fetch origin exclusions || true if git show origin/exclusions:false_positive_exclusions.txt >/dev/null 2>&1; then # If the exclusions branch and file exist, compare if git diff --quiet origin/exclusions -- false_positive_exclusions.txt; then echo "exclusions_changed=false" >> "$GITHUB_OUTPUT" else echo "exclusions_changed=true" >> "$GITHUB_OUTPUT" fi else # If the exclusions branch or file do not exist, treat as changed echo "exclusions_changed=true" >> "$GITHUB_OUTPUT" fi
  • FP_COUNT=$(wc -l < false_positive_exclusions.txt | xargs) WAF_COUNT=$(wc -l < waf_hits.txt | xargs) echo ">>> Found $FP_COUNT false positives and $WAF_COUNT WAF hits." echo ">>> False positive exclusions:" && cat false_positive_exclusions.txt echo ">>> WAF hits:" && cat waf_hits.txt
  • git config user.name "Paul Pfeister (automation)" git config user.email "code@pfeister.dev" mv false_positive_exclusions.txt false_positive_exclusions.txt.tmp git add -f false_positive_exclusions.txt.tmp # -f required to override .gitignore git stash push -m "stash false positive exclusion list" -- false_positive_exclusions.txt.tmp git fetch origin exclusions || true # Allows creation of branch if deleted git checkout -B exclusions origin/exclusions || (git checkout --orphan exclusions && git rm -rf .) git stash pop || true mv false_positive_exclusions.txt.tmp false_positive_exclusions.txt git rm -f false_positive_exclusions.txt.tmp || true git add false_positive_exclusions.txt git commit -m "auto: update exclusions list" || echo "No changes to commit" git push origin exclusions
View raw YAML
name: Exclusions Updater

on:
  schedule:
    #- cron: '0 5 * * 0'  # Runs at 05:00 every Sunday
    - cron: '0 5 * * *' # Runs at 05:00 every day
  workflow_dispatch:

jobs:
  update-exclusions:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.13'

      - name: Install Poetry
        uses: abatilo/actions-poetry@v4
        with:
          poetry-version: 'latest'

      - name: Install dependencies
        run: |
          poetry install --no-interaction --with dev

      - name: Run false positive tests
        run: |
          $(poetry env activate)
          pytest -q --tb no -m validate_targets_fp -n 20 | tee fp_test_results.txt
          deactivate

      - name: Parse false positive detections by desired categories
        run: |
          grep -oP '(?<=test_false_pos\[)[^\]]+(?=\].*result was Claimed)' fp_test_results.txt \
            | sort -u > false_positive_exclusions.txt
          grep -oP '(?<=test_false_pos\[)[^\]]+(?=\].*result was WAF)' fp_test_results.txt \
            | sort -u > waf_hits.txt

      - name: Detect if exclusions list changed
        id: detect_changes
        run: |
          git fetch origin exclusions || true

          if git show origin/exclusions:false_positive_exclusions.txt >/dev/null 2>&1; then
            # If the exclusions branch and file exist, compare
            if git diff --quiet origin/exclusions -- false_positive_exclusions.txt; then
              echo "exclusions_changed=false" >> "$GITHUB_OUTPUT"
            else
              echo "exclusions_changed=true" >> "$GITHUB_OUTPUT"
            fi
          else
            # If the exclusions branch or file do not exist, treat as changed
            echo "exclusions_changed=true" >> "$GITHUB_OUTPUT"
          fi

      - name: Quantify and display results
        run: |
          FP_COUNT=$(wc -l < false_positive_exclusions.txt | xargs)
          WAF_COUNT=$(wc -l < waf_hits.txt | xargs)
          echo ">>> Found $FP_COUNT false positives and $WAF_COUNT WAF hits."
          echo ">>> False positive exclusions:" && cat false_positive_exclusions.txt
          echo ">>> WAF hits:" && cat waf_hits.txt

      - name: Commit and push exclusions list
        if: steps.detect_changes.outputs.exclusions_changed == 'true'
        run: |
          git config user.name "Paul Pfeister (automation)"
          git config user.email "code@pfeister.dev"

          mv false_positive_exclusions.txt false_positive_exclusions.txt.tmp

          git add -f false_positive_exclusions.txt.tmp # -f required to override .gitignore
          git stash push -m "stash false positive exclusion list" -- false_positive_exclusions.txt.tmp

          git fetch origin exclusions || true # Allows creation of branch if deleted
          git checkout -B exclusions origin/exclusions || (git checkout --orphan exclusions && git rm -rf .)

          git stash pop || true

          mv false_positive_exclusions.txt.tmp false_positive_exclusions.txt

          git rm -f false_positive_exclusions.txt.tmp || true
          git add false_positive_exclusions.txt
          git commit -m "auto: update exclusions list" || echo "No changes to commit"
          git push origin exclusions
regression matrix .github/workflows/regression.yml
Triggers
pull_request, push
Runs on
ubuntu-latest, ${{ matrix.os }}, ubuntu-latest
Jobs
tox-lint, tox-matrix, docker-build-test
Matrix
os, python-version→ 3.10, 3.11, 3.12, 3.13, 3.14, 3.14t, macos-latest, ubuntu-latest, windows-latest
Actions
docker/setup-buildx-action
Commands
  • python -m pip install --upgrade pip pip install tox
  • tox -e lint
  • python -m pip install --upgrade pip pip install tox pip install tox-gh-actions
  • tox
  • VERSION=$(grep -m1 'version = ' pyproject.toml | cut -d'"' -f2) echo "version=$VERSION" >> $GITHUB_OUTPUT
  • docker build \ --build-arg VERSION_TAG=${{ steps.get-version.outputs.version }} \ -t sherlock-test:latest .
  • docker run --rm sherlock-test:latest --version
View raw YAML
name: Regression Testing

on:
  pull_request:
    branches:
      - master
      - release/**
    paths:
      - '.github/workflows/regression.yml'
      - '**/*.json'
      - '**/*.py'
      - '**/*.ini'
      - '**/*.toml'
      - 'Dockerfile'
  push:
    branches:
      - master
      - release/**
    paths:
      - '.github/workflows/regression.yml'
      - '**/*.json'
      - '**/*.py'
      - '**/*.ini'
      - '**/*.toml'
      - 'Dockerfile'

jobs:
  tox-lint:
    runs-on: ubuntu-latest
    # Linting is run through tox to ensure that the same linter
    # is used by local runners
    steps:
      - uses: actions/checkout@v6
      - name: Set up linting environment
        uses: actions/setup-python@v6
        with:
          python-version: '3.x'
      - name: Install tox and related dependencies
        run: |
          python -m pip install --upgrade pip
          pip install tox
      - name: Run tox linting environment
        run: tox -e lint
  tox-matrix:
    runs-on: ${{ matrix.os }}
    strategy:
      # We want to know what specific versions it fails on
      fail-fast: false
      matrix:
        os: [
          ubuntu-latest,
          windows-latest,
          macos-latest,
        ]
        python-version: [
          '3.10',
          '3.11',
          '3.12',
          '3.13',
          '3.14',
          '3.14t',
        ]
    steps:
      - uses: actions/checkout@v6
      - name: Set up environment ${{ matrix.python-version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install tox and related dependencies
        run: |
          python -m pip install --upgrade pip
          pip install tox
          pip install tox-gh-actions
      - name: Run tox
        run: tox
  docker-build-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Get version from pyproject.toml
        id: get-version
        run: |
          VERSION=$(grep -m1 'version = ' pyproject.toml | cut -d'"' -f2)
          echo "version=$VERSION" >> $GITHUB_OUTPUT
      - name: Build Docker image
        run: |
          docker build \
            --build-arg VERSION_TAG=${{ steps.get-version.outputs.version }} \
            -t sherlock-test:latest .
      - name: Test Docker image runs
        run: docker run --rm sherlock-test:latest --version
update-site-list .github/workflows/update-site-list.yml
Triggers
push
Runs on
ubuntu-latest
Jobs
sync-json-data
Actions
sdushantha/github-action-push-to-another-repository
Commands
  • python devel/site-list.py
View raw YAML
name: Update Site List

# Trigger the workflow when changes are pushed to the main branch
# and the changes include the sherlock_project/resources/data.json file
on:
  push:
    branches:
      - master
    paths:
      - sherlock_project/resources/data.json

jobs:
  sync-json-data:
    # Use the latest version of Ubuntu as the runner environment
    runs-on: ubuntu-latest

    steps:
      # Check out the code at the specified pull request head commit
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          fetch-depth: 0

      # Install Python 3
      - name: Install Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'

      # Execute the site_list.py Python script
      - name: Execute site-list.py
        run: python devel/site-list.py

      - name: Pushes to another repository
        uses: sdushantha/github-action-push-to-another-repository@main
        env:
          SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
          API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
        with:
          source-directory: 'output'
          destination-github-username: 'sherlock-project'
          commit-message: 'Updated site list'
          destination-repository-name: 'sherlockproject.xyz'
          user-email: siddharth.dushantha@gmail.com
          target-branch: master
validate_modified_targets .github/workflows/validate_modified_targets.yml
Triggers
pull_request_target
Runs on
ubuntu-latest
Jobs
validate-modified-targets
Actions
abatilo/actions-poetry
Commands
  • poetry install --no-interaction --with dev
  • # Fetch only the PR's branch head (single network call in this step) git fetch origin pull/${{ github.event.pull_request.number }}/head:pr # Find the merge-base commit between the target branch and the PR branch MERGE_BASE=$(git merge-base origin/${{ github.base_ref }} pr) echo "Comparing PR head against merge-base commit: $MERGE_BASE" # Safely extract the file from the PR's head and the merge-base commit git show pr:sherlock_project/resources/data.json > data.json.head git show $MERGE_BASE:sherlock_project/resources/data.json > data.json.base # CRITICAL FIX: Overwrite the checked-out data.json with the one from the PR # This ensures that pytest runs against the new, updated file. cp data.json.head sherlock_project/resources/data.json
  • CHANGED=$( python - <<'EOF' import json import sys try: with open("data.json.base") as f: base = json.load(f) with open("data.json.head") as f: head = json.load(f) except FileNotFoundError as e: print(f"Error: Could not find {e.filename}", file=sys.stderr) sys.exit(1) except json.JSONDecodeError as e: print(f"Error: Could not decode JSON from a file - {e}", file=sys.stderr) sys.exit(1) changed = [] for k, v in head.items(): if k not in base or base[k] != v: changed.append(k) print(",".join(sorted(changed))) EOF ) # Preserve changelist echo -e ">>> Changed targets: \n$(echo $CHANGED | tr ',' '\n')" echo "changed_targets=$CHANGED" >> "$GITHUB_OUTPUT"
  • poetry run pytest tests/test_manifest.py::test_validate_manifest_against_local_schema
  • poetry run pytest -q --tb no -rA -m validate_targets -n 20 \ --chunked-sites "${{ steps.discover-modified.outputs.changed_targets }}" \ --junitxml=validation_results.xml
  • summary=$( poetry run python devel/summarize_site_validation.py validation_results.xml || echo "Failed to generate summary of test results" ) echo "$summary" > validation_summary.md
  • echo "No modified targets found"
View raw YAML
name: Modified Target Validation

on:
  pull_request_target:
    branches:
      - master
    paths:
      - "sherlock_project/resources/data.json"

jobs:
  validate-modified-targets:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          # Checkout the base branch but fetch all history to avoid a second fetch call
          ref: ${{ github.base_ref }}
          fetch-depth: 0

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.13"

      - name: Install Poetry
        uses: abatilo/actions-poetry@v4
        with:
          poetry-version: "latest"

      - name: Install dependencies
        run: |
          poetry install --no-interaction --with dev

      - name: Prepare JSON versions for comparison
        run: |
          # Fetch only the PR's branch head (single network call in this step)
          git fetch origin pull/${{ github.event.pull_request.number }}/head:pr

          # Find the merge-base commit between the target branch and the PR branch
          MERGE_BASE=$(git merge-base origin/${{ github.base_ref }} pr)
          echo "Comparing PR head against merge-base commit: $MERGE_BASE"

          # Safely extract the file from the PR's head and the merge-base commit
          git show pr:sherlock_project/resources/data.json > data.json.head
          git show $MERGE_BASE:sherlock_project/resources/data.json > data.json.base

          # CRITICAL FIX: Overwrite the checked-out data.json with the one from the PR
          # This ensures that pytest runs against the new, updated file.
          cp data.json.head sherlock_project/resources/data.json

      - name: Discover modified targets
        id: discover-modified
        run: |
          CHANGED=$(
            python - <<'EOF'
          import json
          import sys
          try:
              with open("data.json.base") as f: base = json.load(f)
              with open("data.json.head") as f: head = json.load(f)
          except FileNotFoundError as e:
              print(f"Error: Could not find {e.filename}", file=sys.stderr)
              sys.exit(1)
          except json.JSONDecodeError as e:
              print(f"Error: Could not decode JSON from a file - {e}", file=sys.stderr)
              sys.exit(1)

          changed = []
          for k, v in head.items():
              if k not in base or base[k] != v:
                  changed.append(k)

          print(",".join(sorted(changed)))
          EOF
          )

          # Preserve changelist
          echo -e ">>> Changed targets: \n$(echo $CHANGED | tr ',' '\n')"
          echo "changed_targets=$CHANGED" >> "$GITHUB_OUTPUT"

      - name: Validate remote manifest against local schema
        if: steps.discover-modified.outputs.changed_targets != ''
        run: |
          poetry run pytest tests/test_manifest.py::test_validate_manifest_against_local_schema

      # --- The rest of the steps below are unchanged ---

      - name: Validate modified targets
        if: steps.discover-modified.outputs.changed_targets != ''
        continue-on-error: true
        run: |
          poetry run pytest -q --tb no -rA -m validate_targets -n 20 \
            --chunked-sites "${{ steps.discover-modified.outputs.changed_targets }}" \
            --junitxml=validation_results.xml

      - name: Prepare validation summary
        if: steps.discover-modified.outputs.changed_targets != ''
        id: prepare-summary
        run: |
          summary=$(
            poetry run python devel/summarize_site_validation.py validation_results.xml || echo "Failed to generate summary of test results"
          )
          echo "$summary" > validation_summary.md

      - name: Announce validation results
        if: steps.discover-modified.outputs.changed_targets != ''
        uses: actions/github-script@v8
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('validation_summary.md', 'utf8');
            await github.rest.issues.createComment({
              issue_number: context.payload.pull_request.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: body,
            });

      - name: This step shows as ran when no modifications are found
        if: steps.discover-modified.outputs.changed_targets == ''
        run: |
          echo "No modified targets found"