name: Circuits Build on: pull_request: branches: - dev - staging - main paths: - "circuits/circuits/**" - ".github/workflows/artifacts.yml" workflow_dispatch: inputs: circuit-type: description: "Circuits to build (comma-separated: register, register_id, register_aadhaar, disclose, dsc). Leave empty to build all." required: false type: string default: "" circuit-name: description: "Circuit names to build (comma-separated: register_sha256_sha224_sha224_ecdsa_secp224r1, dsc_sha256_rsa_65537_4096). Cannot be used with circuit-type." required: false type: string default: "" run-id: description: "Run ID to download artifacts ." required: false type: string default: "" concurrency: group: circuits-build-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: runs-on: ["128ram"] permissions: contents: read actions: read env: CIRCOM_VERSION: "2.1.9" CIRCOM_SHA256: "e5575829252d763b7818049df9de2ef9304df834697de77fa63ce7babc23c967" steps: - name: Checkout Repository uses: actions/checkout@v6 - name: Install cpp dependencies run: | sudo apt-get update sudo apt-get install --yes \ build-essential \ libgmp-dev \ libsodium-dev \ nasm \ nlohmann-json3-dev \ wget - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Restore Circom binary id: circom-cache uses: actions/cache/restore@v4 with: path: ~/.cache/circom key: circom-v2.1.9 - name: Download Circom Binary v2.1.9 if: steps.circom-cache.outputs.cache-hit != 'true' run: | mkdir -p ~/.cache/circom # Download with curl (more reliable than wget in CI environments) # Use exponential backoff retry logic for attempt in 1 2 3; do echo "Download attempt $attempt/3..." if curl -L --connect-timeout 30 --max-time 300 \ --retry 3 --retry-delay 2 --retry-max-time 600 \ -o ~/.cache/circom/circom \ "https://github.com/iden3/circom/releases/download/v${{ env.CIRCOM_VERSION }}/circom-linux-amd64"; then echo "✅ Download successful!" break else echo "❌ Download failed on attempt $attempt" if [ $attempt -eq 3 ]; then echo "💥 All download attempts failed" exit 1 fi # Exponential backoff: 5s, 10s, 20s sleep_time=$((5 * attempt)) echo "⏳ Waiting ${sleep_time}s before retry..." sleep $sleep_time fi done # Verify file exists and has content if [ ! -f ~/.cache/circom/circom ]; then echo "💥 Error: circom binary file is missing" exit 1 fi if [ ! -s ~/.cache/circom/circom ]; then echo "💥 Error: circom binary file is empty" exit 1 fi echo "📁 File size: $(ls -lh ~/.cache/circom/circom | awk '{print $5}')" chmod +x ~/.cache/circom/circom # Verify checksum echo "🔍 Verifying checksum..." echo "${{ env.CIRCOM_SHA256 }} $HOME/.cache/circom/circom" | sha256sum -c - - name: Save Circom cache if: steps.circom-cache.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: path: ~/.cache/circom key: circom-v2.1.9 - name: Verify Circom checksum (cache hit) if: steps.circom-cache.outputs.cache-hit == 'true' run: | echo "${{ env.CIRCOM_SHA256 }} $HOME/.cache/circom/circom" | sha256sum -c - - name: Add Circom to PATH run: echo "$HOME/.cache/circom" >> "$GITHUB_PATH" - name: Read and sanitize Node.js version shell: bash run: | if [ ! -f .nvmrc ] || [ -z "$(cat .nvmrc)" ]; then echo "❌ .nvmrc is missing or empty"; exit 1; fi VERSION="$(tr -d '\r\n' < .nvmrc)" VERSION="${VERSION#v}" if ! [[ "$VERSION" =~ ^[0-9]+(\.[0-9]+){0,2}$ ]]; then echo "Invalid .nvmrc content: '$VERSION'"; exit 1; fi echo "NODE_VERSION=$VERSION" >> "$GITHUB_ENV" echo "NODE_VERSION_SANITIZED=${VERSION//\//-}" >> "$GITHUB_ENV" - name: Use Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Install Yarn run: npm i -g yarn - name: Install dependencies uses: ./.github/actions/yarn-install with: working_directory: circuits - name: Print Circom version run: circom --version - name: Download previous artifacts if: github.event_name == 'workflow_dispatch' && inputs.run-id != '' uses: dawidd6/action-download-artifact@v6 with: name: circuits path: output/ run_id: ${{ inputs.run-id }} - name: Build cpp circuits run: | chmod +x circuits/scripts/build/build_cpp.sh chmod +x circuits/scripts/build/build_single_circuit.sh # Validate inputs - only one should be provided if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then if [[ "${{ inputs.circuit-type }}" != "" && "${{ inputs.circuit-name }}" != "" ]]; then echo " Error: Cannot provide both circuit-type and circuit-name. Use only one." exit 1 fi fi # Check what type of build to perform if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.circuit-name }}" != "" ]]; then # Build circuits by name INPUT_CIRCUITS="${{ inputs.circuit-name }}" INPUT_CIRCUITS=$(echo "$INPUT_CIRCUITS" | tr -d ' ') IFS=',' read -ra CIRCUITS_ARRAY <<< "$INPUT_CIRCUITS" echo "Building selected circuits: ${{ inputs.circuit-name }}" for circuit_name in "${CIRCUITS_ARRAY[@]}"; do echo "Building circuit: $circuit_name" ./circuits/scripts/build/build_single_circuit.sh "$circuit_name" done elif [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.circuit-type }}" != "" ]]; then # Build circuits by type INPUT_CIRCUITS="${{ inputs.circuit-type }}" INPUT_CIRCUITS=$(echo "$INPUT_CIRCUITS" | tr -d ' ') IFS=',' read -ra CIRCUITS_ARRAY <<< "$INPUT_CIRCUITS" echo "Building selected circuits: ${{ inputs.circuit-type }}" for circuit in "${CIRCUITS_ARRAY[@]}"; do echo "Building circuit: $circuit" ./circuits/scripts/build/build_cpp.sh "$circuit" done else # Build all circuits (default behavior) echo "Building all circuits (default behavior)" ./circuits/scripts/build/build_cpp.sh register ./circuits/scripts/build/build_cpp.sh register_id ./circuits/scripts/build/build_cpp.sh register_aadhaar ./circuits/scripts/build/build_cpp.sh disclose ./circuits/scripts/build/build_cpp.sh dsc fi - name: Upload Artifact uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 with: name: circuits path: output/