name: CD on: push: branches: [main] paths: - "recipes/**" - ".github/workflows/ci.yml" - ".github/workflows/cd.yml" - ".github/scripts/**" workflow_dispatch: jobs: detect-targets: runs-on: ubuntu-latest outputs: matrix: ${{ steps.detect.outputs.matrix }} has_targets: ${{ steps.detect.outputs.has_targets }} steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Detect changed recipe targets id: detect shell: bash run: | set -euo pipefail base="${ACT_BASE_SHA:-${{ github.event.before }}}" if [[ -n "${ACT_CHANGED_FILES:-}" ]]; then base="${base:-act-base}" elif [[ -z "$base" || "$base" == "0000000000000000000000000000000000000000" ]]; then if git rev-parse HEAD^ >/dev/null 2>&1; then base="$(git rev-parse HEAD^)" else base="$(git rev-list --max-parents=0 HEAD)" fi fi head="${ACT_HEAD_SHA:-${{ github.sha }}}" matrix="$(python3 .github/scripts/detect_recipe_matrix.py --base "$base" --head "$head" --conandata-mode changed)" echo "matrix=$matrix" >> "$GITHUB_OUTPUT" if [[ "$matrix" == '{"include": []}' ]]; then echo "has_targets=false" >> "$GITHUB_OUTPUT" else echo "has_targets=true" >> "$GITHUB_OUTPUT" fi publish: needs: detect-targets if: needs.detect-targets.outputs.has_targets == 'true' runs-on: ubuntu-latest strategy: fail-fast: false matrix: ${{ fromJson(needs.detect-targets.outputs.matrix) }} env: CONAN_REMOTE_URL: ${{ secrets.CONAN_REMOTE_URL }} CONAN_LOGIN_USERNAME: ${{ secrets.CONAN_LOGIN_USERNAME || secrets.GITEA_USERNAME }} CONAN_PASSWORD: ${{ secrets.CONAN_PASSWORD || secrets.GITEA_TOKEN }} steps: - name: Checkout uses: actions/checkout@v6 - name: Install host build tools uses: awalsh128/cache-apt-pkgs-action@latest with: packages: build-essential gcc-14 g++-14 cmake ninja-build graphviz crudini version: 1.0 execute_install_scripts: true - name: Set gcc-14 as default run: | sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 10 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 10 - name: Setup Conan client uses: conan-io/setup-conan@v1 with: version: "2.*" use_venv: true - name: Validate required Conan secrets run: | test -n "$CONAN_REMOTE_URL" || (echo "Missing secret: CONAN_REMOTE_URL" && exit 1) test -n "$CONAN_LOGIN_USERNAME" || (echo "Missing secret: CONAN_LOGIN_USERNAME" && exit 1) test -n "$CONAN_PASSWORD" || (echo "Missing secret: CONAN_PASSWORD" && exit 1) - name: Detect Conan profile run: | conan profile detect --force crudini --set ~/.conan2/profiles/default settings compiler.cppstd 23 - name: Login private Conan remote run: | conan remote add org "$CONAN_REMOTE_URL" --force conan remote login org "$CONAN_LOGIN_USERNAME" --password "$CONAN_PASSWORD" conan remote list - name: Build package run: | conan create "${{ matrix.path }}" --version="${{ matrix.version }}" --build=missing - name: Upload package if missing on remote shell: bash run: | set -euo pipefail ref="${{ matrix.reference }}" remote_json="$(conan list "${ref}:*" -r org --format=json || true)" if python3 -c 'import json, sys; data = json.loads((sys.argv[1].strip() or "{}")); has_package = any(isinstance(recipe_data, dict) and recipe_data.get("packages") for remote_data in data.values() if isinstance(remote_data, dict) for recipe_data in remote_data.values()); sys.exit(0 if has_package else 1)' "$remote_json" then echo "Remote already has packages for ${ref}; skipping upload." exit 0 fi conan upload "${ref}" -r org --confirm no-targets: needs: detect-targets if: needs.detect-targets.outputs.has_targets != 'true' runs-on: ubuntu-latest steps: - name: No changed recipes run: echo "No recipe targets detected for publishing."