name: StackFlow (Plan/Validate) on: workflow_dispatch: inputs: config: description: "Path to StackFlow config (e.g. StackFlow/svc-plus.yaml)" required: true type: string default: "StackFlow/svc-plus.yaml" phase: description: "Phase to run" required: true type: choice options: - validate - dns-plan pull_request: paths: - "StackFlow/**/*.yml" - "StackFlow/**/*.yaml" - "stackflow/**/*.yml" - "stackflow/**/*.yaml" - ".github/workflows/stackflow.yaml" - "scripts/stackflow/**" push: branches: - main paths: - "StackFlow/**/*.yml" - "StackFlow/**/*.yaml" - "stackflow/**/*.yml" - "stackflow/**/*.yaml" - ".github/workflows/stackflow.yaml" - "scripts/stackflow/**" jobs: resolve-configs: runs-on: ubuntu-latest outputs: configs: ${{ steps.set.outputs.configs }} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Resolve config list id: set shell: bash run: | set -euo pipefail if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then python - <<'PY' >> "$GITHUB_OUTPUT" import json print("configs=" + json.dumps(["${{ inputs.config }}"])) PY exit 0 fi if [[ "${{ github.event_name }}" == "pull_request" ]]; then git fetch origin "${{ github.base_ref }}" --depth=1 files="$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD || true)" else # push files="$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" || true)" fi configs="$(printf '%s\n' "$files" | grep -E '^(StackFlow|stackflow)/.*\.ya?ml$' || true)" if [[ -z "${configs}" ]]; then if [[ -f "stackflow/svc.plus.yaml" ]]; then configs="stackflow/svc.plus.yaml" else configs="StackFlow/svc-plus.yaml" fi fi printf '%s\n' "$configs" | python - <<'PY' >> "$GITHUB_OUTPUT" import json, sys configs = [l.strip() for l in sys.stdin.read().splitlines() if l.strip()] print("configs=" + json.dumps(configs)) PY stackflow: runs-on: ubuntu-latest needs: resolve-configs concurrency: group: stackflow-${{ github.ref }} cancel-in-progress: true strategy: fail-fast: false matrix: config: ${{ fromJson(needs.resolve-configs.outputs.configs) }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install deps run: | python -m pip install --upgrade pip python -m pip install -r scripts/stackflow/requirements.txt - name: Prepare output dir shell: bash run: | set -euo pipefail mkdir -p out - name: Run StackFlow (workflow_dispatch) if: ${{ github.event_name == 'workflow_dispatch' }} run: | python scripts/stackflow/runner.py \ --config "${{ inputs.config }}" \ --phase "${{ inputs.phase }}" - name: Validate (CI) if: ${{ github.event_name != 'workflow_dispatch' }} run: | python scripts/stackflow/runner.py \ --config "${{ matrix.config }}" \ --phase validate \ > "out/$(basename "${{ matrix.config }}").validate.json" - name: DNS Plan (CI) if: ${{ github.event_name != 'workflow_dispatch' }} run: | python scripts/stackflow/runner.py \ --config "${{ matrix.config }}" \ --phase dns-plan \ > "out/$(basename "${{ matrix.config }}").dns-plan.json" - name: Compute artifact name (CI) if: ${{ github.event_name != 'workflow_dispatch' }} shell: bash run: | set -euo pipefail name="${{ matrix.config }}" name="${name//\//-}" echo "ARTIFACT_NAME=stackflow-${name}" >> "$GITHUB_ENV" - name: Upload artifacts (CI) if: ${{ github.event_name != 'workflow_dispatch' }} uses: actions/upload-artifact@v4 with: name: ${{ env.ARTIFACT_NAME }} path: out/