name: headless-render-regression

on:
  push:
    branches: ["**"]
  pull_request:
    branches: ["**"]
  schedule:
    # 02:30 Asia/Taipei every day, before downstream translation sync.
    - cron: "30 18 * * *"
  workflow_dispatch:
    inputs:
      upstream_template_test_refs:
        description: "Space-separated upstream refs for fast offline transform/package checks."
        required: false
        default: "latest main v1.30.0+"
      upstream_template_artifact_refs:
        description: "Space-separated released upstream refs to package as clean scaffold artifacts."
        required: false
        default: "v1.29.1+"

env:
  UPSTREAM_TEMPLATE_ARTIFACT_REFS: ${{ github.event.inputs.upstream_template_artifact_refs || 'v1.29.1+' }}
  UPSTREAM_TEMPLATE_REPOSITORY: ds-wizard/science-europe-template
  UPSTREAM_TEMPLATE_TEST_METAMODEL_VERSION: "18.0"
  UPSTREAM_TEMPLATE_TEST_REFS: ${{ github.event.inputs.upstream_template_test_refs || 'latest main v1.30.0+' }}

permissions:
  contents: write
  pull-requests: write

jobs:
  offline-checks:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v7

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

      - name: Install dependencies
        run: make install-dev

      - name: Validate upstream template refs
        run: |
          make test-upstream-tags \
            UPSTREAM_TEMPLATE_REPOSITORY="$UPSTREAM_TEMPLATE_REPOSITORY" \
            UPSTREAM_TEMPLATE_TEST_REFS="$UPSTREAM_TEMPLATE_TEST_REFS" \
            UPSTREAM_TEMPLATE_TEST_METAMODEL_VERSION="$UPSTREAM_TEMPLATE_TEST_METAMODEL_VERSION"

      - name: Discover upstream DSW compatibility
        id: discover_compat
        continue-on-error: true
        run: |
          make discover-upstream-compat \
            UPSTREAM_TEMPLATE_REPOSITORY="$UPSTREAM_TEMPLATE_REPOSITORY" \
            UPSTREAM_TEMPLATE_DISCOVERY_REFS="$UPSTREAM_TEMPLATE_ARTIFACT_REFS" \
            UPSTREAM_TEMPLATE_DISCOVERY_REPORT="outputs/upstream-compat/discovery.md"

      - name: Open DSW compatibility probe PR
        if: steps.discover_compat.outcome == 'failure' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/master')
        env:
          DEFAULT_BRANCH: ${{ github.event.repository.default_branch || 'master' }}
          GH_TOKEN: ${{ github.token }}
        run: |
          python scripts/ci/create_dsw_compat_pr.py \
            --report outputs/upstream-compat/discovery.md \
            --evidence-config config/regression-evidence.yml \
            --repository "$GITHUB_REPOSITORY" \
            --base "$DEFAULT_BRANCH"

      - name: Fail pull request on unsupported upstream metamodel
        if: steps.discover_compat.outcome == 'failure' && github.event_name == 'pull_request'
        run: |
          echo "::error title=Unsupported upstream metamodel::See the DSW compatibility discovery summary."
          exit 1

      - name: Check formatting
        run: make format-check

      - name: Run lint
        run: make lint

      - name: Run tests
        run: make test

  render-regression:
    runs-on: ubuntu-latest
    needs: offline-checks
    timeout-minutes: 45
    strategy:
      fail-fast: false
      matrix:
        include:
          # BEGIN GENERATED DSW RUNTIME MATRIX
          - metamodel_key: "17-1"
            metamodel_version: "17.1"
            dsw_version: "4.26"
            tdk_version: "4.26.1"
            upstream_template_artifact_refs: "v1.29.1"
          - metamodel_key: "18-0"
            metamodel_version: "18.0"
            dsw_version: "4.30"
            tdk_version: "4.30.2"
            upstream_template_artifact_refs: "v1.30.0+"
          # END GENERATED DSW RUNTIME MATRIX
    env:
      DSW_API_URL: http://localhost:3000/wizard-api
      DSW_EMAIL: albert.einstein@example.com
      DSW_PASSWORD: password
      DSW_VERSION: ${{ matrix.dsw_version }}
      UPSTREAM_TEMPLATE_PREVIEW_METAMODEL_VERSION: ${{ matrix.metamodel_version }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v7

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

      - name: Install dependencies
        run: make install-dev

      - name: Install matching dsw-tdk
        run: |
          .venv/bin/python -m pip install "dsw-tdk==${{ matrix.tdk_version }}"
          .venv/bin/dsw-tdk --version

      - name: Build clean upstream version artifacts
        env:
          UPSTREAM_TEMPLATE_ARTIFACT_REFS: ${{ github.event.inputs.upstream_template_artifact_refs || matrix.upstream_template_artifact_refs }}
          UPSTREAM_TEMPLATE_ARTIFACT_METAMODEL_VERSION: ${{ matrix.metamodel_version }}
        run: |
          make build-upstream-artifacts \
            UPSTREAM_TEMPLATE_REPOSITORY="$UPSTREAM_TEMPLATE_REPOSITORY" \
            UPSTREAM_TEMPLATE_ARTIFACT_REFS="$UPSTREAM_TEMPLATE_ARTIFACT_REFS" \
            UPSTREAM_TEMPLATE_ARTIFACT_METAMODEL_VERSION="$UPSTREAM_TEMPLATE_ARTIFACT_METAMODEL_VERSION"

      - name: Generate expanded compatibility ledger
        run: make generate-compat-ledger

      - name: Start local DSW stack
        run: make start-ci-dsw

      - name: Run preview regression
        run: make render-regression-ci-plan

      - name: Summarize preview regression coverage
        if: always()
        env:
          REGRESSION_SUMMARY_LABEL: Metamodel ${{ matrix.metamodel_version }} Render Regression
        run: |
          make summarize-regression-coverage \
            REGRESSION_SUMMARY_LABEL="$REGRESSION_SUMMARY_LABEL"

      - name: Render clean upstream version previews
        env:
          DSW_API_URL: http://localhost:3000/wizard-api
          DSW_EMAIL: albert.einstein@example.com
          DSW_PASSWORD: password
          DSW_DOWNLOAD_HOST_ALIAS: host.docker.internal=localhost
        run: make render-upstream-artifact-previews

      - name: Verify complete runtime evidence
        run: make verify-runtime-evidence

      - name: Collect DSW logs
        if: always()
        run: make ci-dsw-logs

      - name: Upload regression artifacts
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: regression-artifacts-metamodel-${{ matrix.metamodel_key }}
          include-hidden-files: true
          path: outputs/

      - name: Upload clean upstream version artifacts
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: clean-upstream-version-artifacts-metamodel-${{ matrix.metamodel_key }}
          include-hidden-files: true
          path: |
            outputs/compat-ledger/
            outputs/runtime-evidence/
            outputs/upstream-workspaces/
            outputs/document-templates/dsw-science-europe/**/scaffold/
            outputs/project-render/dsw-science-europe/**/scaffold/

      - name: Stage clean scaffold release assets
        if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/master'
        run: |
          python scripts/ci/publish_clean_scaffold_releases.py \
            --repository "$GITHUB_REPOSITORY" \
            --run-id "$GITHUB_RUN_ID" \
            --commit-sha "$GITHUB_SHA" \
            --dry-run

      - name: Publish clean scaffold release assets
        if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/master'
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          python scripts/ci/publish_clean_scaffold_releases.py \
            --repository "$GITHUB_REPOSITORY" \
            --run-id "$GITHUB_RUN_ID" \
            --commit-sha "$GITHUB_SHA" \
            --skip-staging

      - name: Stop local DSW stack
        if: always()
        run: make stop-ci-dsw
