Skip to content

PNCP discovery

PNCP discovery #524

name: PNCP discovery
on:
schedule:
- cron: "05 * * * *"
workflow_dispatch:
inputs:
opportunity_v2:
description: "Emit one parent opportunity per PNCP control number"
required: false
default: false
type: boolean
shadow:
description: "Artifact-only v2 run; never submit to production"
required: false
default: true
type: boolean
concurrency:
group: pipeline-trigger
cancel-in-progress: false
jobs:
discover-pncp:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout scheduler repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: pip
cache-dependency-path: requirements-ocr-worker.txt
- name: Install OCR worker dependencies
run: pip install -r requirements-ocr-worker.txt
- name: Restore PNCP update checkpoint
uses: actions/cache@v4
with:
path: .cache/pncp-last-successful-update.json
key: pncp-update-checkpoint-${{ runner.os }}-${{ github.run_id }}
restore-keys: |
pncp-update-checkpoint-${{ runner.os }}-
- name: Run PNCP discovery, download, OCR, and submission
run: python scripts/discover_pncp_candidates.py
env:
RENDER_APP_URL: ${{ secrets.RENDER_APP_URL }}
PIPELINE_SECRET: ${{ secrets.PIPELINE_SECRET }}
PNCP_UPDATE_CHECKPOINT_PATH: .cache/pncp-last-successful-update.json
PNCP_MIN_NOTICE_YEAR: "2026"
PNCP_MAX_CANDIDATES_PER_RUN: "50"
PNCP_MAX_PROCESSED_CANDIDATES_PER_RUN: "20"
PNCP_MAX_SUBMITTABLE_CANDIDATES_PER_RUN: "5"
PNCP_FETCH_MAX_ATTEMPTS: "2"
PNCP_FETCH_BACKOFF_SECONDS: "2"
PNCP_FETCH_TIMEOUT_SECONDS: "8"
SCRAPE_MAX_PDF_BYTES: "15000000"
KREUZBERG_PADDLE_LANGUAGE: "latin"
KREUZBERG_PADDLE_MODEL_TIER: "tiny"
KREUZBERG_USE_GPU: "false"
KREUZBERG_FORCE_OCR_DEFAULT: "false"
KREUZBERG_EXTRACTION_TIMEOUT_SECONDS: "120"
FLAGS_use_mkldnn: "0"
PADDLE_PDX_ENABLE_MKLDNN_BYDEFAULT: "0"
PNCP_OPPORTUNITY_V2_ENABLED: ${{ github.event_name == 'workflow_dispatch' && inputs.opportunity_v2 }}
PNCP_OPPORTUNITY_V2_SHADOW: ${{ github.event_name != 'workflow_dispatch' || inputs.shadow }}
PNCP_OPPORTUNITY_V2_ARTIFACT: artifacts/pncp-v2/opportunities.json
- name: Upload PNCP v2 shadow inventory
if: always()
uses: actions/upload-artifact@v4
with:
name: pncp-v2-shadow
path: artifacts/pncp-v2
if-no-files-found: ignore