name: Stable release

on:
    # Trigger a stable version release via GitHub's UI, with the ability to specify the type of release.
    workflow_dispatch:
        inputs:
            release_type:
                description: Release type
                required: true
                type: choice
                default: auto
                options:
                    - auto
                    - custom
                    - patch
                    - minor
                    - major
            custom_version:
                description: The custom version to bump to (only for "custom" type)
                required: false
                type: string
                default: ""

permissions:
    id-token: write
    contents: write
    actions: write

concurrency:
    group: release
    cancel-in-progress: false

jobs:
    release_metadata:
        name: Update release metadata
        uses: ./.github/workflows/_update_release_metadata.yaml
        secrets: inherit
        with:
          release_type: ${{ inputs.release_type }}
          custom_version: ${{ inputs.custom_version }}

    build_mcpb:
        name: Build MCPB package
        needs: [release_metadata]
        runs-on: ubuntu-latest
        steps:
            -   uses: actions/checkout@v6
                with:
                    ref: ${{ needs.release_metadata.outputs.changelog_commitish }}
            -   name: Use Node.js
                uses: actions/setup-node@v6
                with:
                    node-version-file: '.nvmrc'
            -   name: Install pnpm and dependencies
                uses: apify/actions/pnpm-install@v1.1.2
            -   name: Build module
                run: pnpm run build
            -   name: Prepare MCPB package
                # `pnpm deploy --prod mcpb` builds a self-contained deployment dir:
                # production-only deps, a flat (hoisted) node_modules with no `.pnpm/`
                # store or symlinks — the MCPB packer requires a portable tree.
                # Then we copy in the build output and assets the packer expects.
                run: |
                    pnpm deploy --prod mcpb
                    cp -r dist mcpb/dist
                    cp -r docs mcpb/docs
                    cp manifest.json mcpb/manifest.json
                    cp docs/apify-logo-claude-desktop.png mcpb/icon.png
                # `pnpm dlx` instead of `npx` because devEngines.packageManager is
                # pinned to pnpm with onFail: error — npx invokes npm, which is rejected
                # with EBADDEVENGINES at the repo root. Pinned mcpb version preserved
                # for reproducible builds.
            -   name: Validate MCPB manifest
                run: pnpm dlx @anthropic-ai/mcpb@2.1.2 validate mcpb/manifest.json
            -   name: Create MCPB package
                run: pnpm dlx @anthropic-ai/mcpb@2.1.2 pack mcpb/ apify-mcp-server.mcpb
            -   name: Clean MCPB package
                run: pnpm dlx @anthropic-ai/mcpb@2.1.2 clean apify-mcp-server.mcpb
            -   name: Upload MCPB artifacts
                uses: actions/upload-artifact@v4
                with:
                    name: mcpb-packages
                    path: apify-mcp-server.mcpb

    create_github_release:
        name: Create github release
        needs: [release_metadata, build_mcpb]
        runs-on: ubuntu-latest
        env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        steps:
            -   name: Download MCPB artifacts
                uses: actions/download-artifact@v4
                with:
                    name: mcpb-packages
            -   name: Create release
                uses: softprops/action-gh-release@v2
                with:
                    tag_name: ${{ needs.release_metadata.outputs.tag_name }}
                    name: ${{ needs.release_metadata.outputs.version_number }}
                    target_commitish: ${{ needs.release_metadata.outputs.changelog_commitish }}
                    body: ${{ needs.release_metadata.outputs.release_notes }}
                    files: apify-mcp-server.mcpb

    publish_to_npm:
        name: Publish to NPM
        needs: [ release_metadata ]
        runs-on: ubuntu-latest
        steps:
            -   name: Execute publish workflow
                uses: apify/actions/execute-workflow@v1.1.2
                with:
                    workflow: manual_publish_to_npm.yaml
                    inputs: >
                        {
                            "ref": "${{ needs.release_metadata.outputs.changelog_commitish }}",
                            "tag": "latest"
                        }

    smoke_test:
        name: Smoke test published package
        needs: [ release_metadata, publish_to_npm ]
        uses: ./.github/workflows/_smoke_test_npm_package.yaml
        with:
            version: ${{ needs.release_metadata.outputs.version_number }}

    bump_dependency_in_internal_repo:
        name: Bump dependency in apify-mcp-server-internal
        needs: [ release_metadata, publish_to_npm ]
        runs-on: ubuntu-latest
        env:
            GH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
        steps:
            -   name: Checkout internal repo
                uses: actions/checkout@v6
                with:
                    repository: apify/apify-mcp-server-internal
                    token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
            -   name: Resolve pnpm version from internal repo
                # Read the version from the internal repo's devEngines so this job
                # tracks the source of truth instead of carrying a hardcoded duplicate.
                # `jq -e` exits non-zero if the key is missing, so a structure change
                # in the internal repo's package.json fails this step loudly.
                id: pnpm-version
                run: |
                    version=$(jq -er '.devEngines.packageManager.version' package.json)
                    echo "version=$version" >> "$GITHUB_OUTPUT"
            -   name: Install pnpm
                # v6 is the first major running on Node 24 (matches `.nvmrc`).
                # Exact patch pin (vs. floating `v6`) sidesteps the unmarked
                # pre-releases in the v6 line (pnpm/action-setup#236) and lets
                # newer patches age 14 days before adoption.
                uses: pnpm/action-setup@v6.0.5
                with:
                    version: ${{ steps.pnpm-version.outputs.version }}
            -   name: Use Node.js
                uses: actions/setup-node@v6
                with:
                    node-version-file: '.nvmrc'
                    cache: 'pnpm'
                    cache-dependency-path: 'pnpm-lock.yaml'
                # The internal repo pins `devEngines.packageManager` (onFail: error),
                # so npm refuses to run inside the checkout. setup-node still calls
                # `npm config get cache` for env diagnostics — NPM_CONFIG_FORCE
                # (== `--force`) is the only documented bypass (npm/rfcs#830).
                # Scoped to this step; install work below uses pnpm.
                env:
                    NPM_CONFIG_FORCE: 'true'
            -   name: Configure GitHub Packages auth
                run: pnpm config set //npm.pkg.github.com/:_authToken ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
            -   name: Install updated dependency
                uses: nick-fields/retry@v3 # Retry to compensate for npm registry propagation lag
                with:
                    timeout_minutes: 10
                    max_attempts: 3
                    retry_wait_seconds: 30
                    command: pnpm add --save-exact @apify/actors-mcp-server@${{ needs.release_metadata.outputs.version_number }}
            -   name: Commit dependency bump
                id: commit
                uses: apify/actions/signed-commit@v1.0.0
                with:
                    message: "chore: bump @apify/actors-mcp-server to ${{ needs.release_metadata.outputs.version_number }}"
                    github-token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
                    repository: apify/apify-mcp-server-internal
                    branch: "release/${{ needs.release_metadata.outputs.tag_name }}"
                    create-branch: 'true'

            -   name: Create pull request
                if: steps.commit.outputs.committed == 'true'
                run: |
                    gh pr create \
                      --repo apify/apify-mcp-server-internal \
                      --head "release/${{ needs.release_metadata.outputs.tag_name }}" \
                      --title "chore: bump @apify/actors-mcp-server to ${{ needs.release_metadata.outputs.version_number }}" \
                      --body "$BODY" \
                      --reviewer "${{ github.actor }}"
                env:
                    GH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
                    BODY: |
                        Automated PR to bump `@apify/actors-mcp-server` to `${{ needs.release_metadata.outputs.version_number }}`.

                        ## Release notes

                        ${{ needs.release_metadata.outputs.release_notes }}

    publish_to_mcp_registry:
        name: Publish to MCP Registry
        needs: [ release_metadata ]
        runs-on: ubuntu-latest
        steps:
            -   uses: actions/checkout@v6
                with:
                    ref: ${{ needs.release_metadata.outputs.changelog_commitish }}
            -   name: Install mcp-publisher
                run: |
                    curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
                    sudo mv mcp-publisher /usr/local/bin/
            -   name: Login to MCP Registry
                env:
                    MCP_REGISTRY_PUBLISH_SECRET: ${{ secrets.MCP_REGISTRY_PUBLISH_SECRET }}
                run: |
                    set +x
                    mcp-publisher login dns --domain "apify.com" --private-key "${MCP_REGISTRY_PUBLISH_SECRET}"
            -   name: Publish to MCP Registry
                run: mcp-publisher publish
