diff --git a/.github/workflows/effx-analyze.yml b/.github/workflows/effx-analyze.yml new file mode 100644 index 0000000..d690998 --- /dev/null +++ b/.github/workflows/effx-analyze.yml @@ -0,0 +1,75 @@ +name: effx analyze + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +permissions: + contents: read + +jobs: + analyze: + runs-on: ubuntu-latest + steps: + - name: Check out pull request without credentials + uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Check out immutable effx tool revision + uses: actions/checkout@v4 + with: + repository: phibkro/oxlint-effect-plugin + ref: 0e41f6b05b08f7ecfd91c7e55e77e98d8b650b02 + path: .effx-tool + persist-credentials: false + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.13 + - name: Install the reviewed effx tool + working-directory: .effx-tool + run: | + bun install --frozen-lockfile --ignore-scripts + bun run build + - name: Create repository-independent EffectTS configuration + run: | + cat > .effx-oxlintrc.json <<'JSON' + { + "jsPlugins": [{ "name": "effect", "specifier": "./.effx-tool/dist/index.js" }], + "ignorePatterns": [".effx-tool/**", "node_modules/**", "dist/**", "build/**", "coverage/**", ".git/**"], + "rules": { + "effect/no-ambient-console": ["error", { "role": "effect-library", "platform": "portable" }], + "effect/no-ambient-authority": ["error", { "role": "effect-library", "platform": "portable" }], + "effect/no-cross-runtime": ["error", { "role": "effect-library", "platform": "portable" }], + "effect/no-premature-execution": ["error", { "role": "effect-library", "platform": "portable" }], + "effect/no-native-promise-control-flow": ["error", { "role": "effect-library", "platform": "portable" }], + "effect/no-raw-json-parse": ["error", { "role": "effect-library", "platform": "portable", "boundaries": ["external-data"] }], + "effect/no-untyped-throw": ["error", { "role": "effect-library", "platform": "portable" }], + "effect/no-opaque-instance-fields": ["error", { "role": "effect-library", "platform": "portable" }] + } + } + JSON + - name: Run Oxlint with structured output + run: | + set +e + .effx-tool/node_modules/.bin/oxlint --config .effx-oxlintrc.json --format json . > effx-oxlint.json + status=$? + set -e + test -s effx-oxlint.json + test "$status" -le 1 + - name: Translate diagnostics + run: bun .effx-tool/dist/cli.js translate < effx-oxlint.json > effx-diagnostics.json + - name: Build immutable publication input + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} + EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: bun .effx-tool/scripts/build-github-input.ts effx-diagnostics.json > effx-input.json + - name: Upload decoded analysis result + uses: actions/upload-artifact@v4 + with: + name: effx-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} + path: effx-input.json + if-no-files-found: error + retention-days: 7 diff --git a/.github/workflows/effx-publish.yml b/.github/workflows/effx-publish.yml new file mode 100644 index 0000000..739dd45 --- /dev/null +++ b/.github/workflows/effx-publish.yml @@ -0,0 +1,59 @@ +name: effx publish + +on: + workflow_run: + workflows: ["effx analyze"] + types: [completed] + +permissions: + actions: read + checks: write + contents: read + pull-requests: write + +jobs: + publish: + if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Check out immutable effx tool revision + uses: actions/checkout@v4 + with: + repository: phibkro/oxlint-effect-plugin + ref: 0e41f6b05b08f7ecfd91c7e55e77e98d8b650b02 + path: .effx-tool + persist-credentials: false + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.13 + - name: Download unprivileged analysis artifact + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + RUN_ID: ${{ github.event.workflow_run.id }} + run: gh run download "$RUN_ID" --repo "$GH_REPO" --dir .effx-input + - name: Select and verify immutable analysis input + env: + EXPECTED_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + run: | + input="$(find .effx-input -name effx-input.json -type f -print -quit)" + test -n "$input" + test "$(find .effx-input -name effx-input.json -type f | wc -l)" -eq 1 + test "$(jq -r '.expectedHeadSha' "$input")" = "$EXPECTED_HEAD_SHA" + test "$(jq -r '.observedHeadSha' "$input")" = "$EXPECTED_HEAD_SHA" + cp "$input" .effx-input.json + - name: Install the reviewed effx tool + working-directory: .effx-tool + run: | + bun install --frozen-lockfile --ignore-scripts + bun run build + - name: Produce fail-closed publication plan + run: bun .effx-tool/dist/cli.js github plan < .effx-input.json > .effx-plan.json + - name: Publish canonical Check and review comments + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + EXPECTED_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} + run: bun .effx-tool/scripts/publish-github-plan.ts .effx-plan.json diff --git a/docs/effx-migration-guide.md b/docs/effx-migration-guide.md new file mode 100644 index 0000000..18d4aee --- /dev/null +++ b/docs/effx-migration-guide.md @@ -0,0 +1,18 @@ +# effx migration review + +Classification: `agent-migration-opt-in-required` + +This repository declares an Effect release outside the exact reviewed effx release `4.0.0-beta.107`. The pull request adds the two-stage effx review integration, but it does not change dependencies or application source. + +## Required migration review + +1. Review every Effect-family dependency against `4.0.0-beta.107`. +2. Supply exact reviewed targets for every `@effect/*` package. Do not guess package versions. +3. Run this repository's package-manager, type, lint, and test checks. +4. Opt in explicitly before an agent changes application source. + +## Limits + +- No mechanical migration was proven safe from the observed dependency declarations. +- The integration performs syntax and scope enforcement. Effect-specific typed diagnostics remain owned by `@effect/tsgo`. +- The publication workflow uses only artifacts from the unprivileged analysis workflow and binds publication to the immutable pull-request head SHA.