# This job will generate a codegen diff, upload it to S3, and link to it in a comment on the PR.
name: PR Bot
on:
  workflow_call:
    inputs:
      issue_number:
        description: The issue number to post the diff comment to.
        required: true
        type: string
      base_revision:
        description: Base git revision.
        required: true
        type: string
      head_revision:
        description: Head git revision.
        required: true
        type: string
    secrets:
      SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME:
        required: true
      SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN:
        required: true

# Allow one instance of this workflow per pull request, and cancel older runs when new changes are pushed
concurrency:
  group: pull-request-bot-yml-${{ inputs.issue_number }}
  cancel-in-progress: true

env:
  apt_dependencies: libssl-dev gnuplot jq
  java_version: 17
  rust_toolchain_components: clippy,rustfmt
  rust_nightly_version: nightly-2024-02-07

jobs:
  generate-diff:
    runs-on: smithy_ubuntu-latest_8-core
    name: Generate diff and upload to S3
    env:
      AWS_REGION: us-west-2
      S3_BUCKET_NAME: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME }}
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    outputs:
      bot-message: ${{ steps.generate-diff.outputs.bot-message }}
    steps:
    - uses: actions/checkout@v4
      with:
        path: smithy-rs
        ref: ${{ inputs.head_revision }}
    - name: Generate diff
      uses: ./smithy-rs/.github/actions/docker-build
      with:
        action: generate-codegen-diff
        action-arguments: ${{ inputs.base_revision }}
    - uses: aws-actions/configure-aws-credentials@v4
      name: Acquire credentials for uploading to S3
      with:
        role-to-assume: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN }}
        role-session-name: GitHubActions
        aws-region: us-west-2
    - name: Upload diff to S3
      run: |
        if [[ -d artifacts/codegen-diff/${{ inputs.base_revision }} ]]; then
            aws s3 cp artifacts/codegen-diff/${{ inputs.base_revision }} \
                "s3://${S3_BUCKET_NAME}/codegen-diff/${{ inputs.base_revision }}" --recursive
        fi

  generate-doc-preview:
    runs-on: smithy_ubuntu-latest_8-core
    name: Generate rustdoc preview and upload to S3
    env:
      AWS_REGION: us-west-2
      S3_BUCKET_NAME: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME }}
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    outputs:
      bot-message: ${{ steps.generate-preview.outputs.bot-message }}
    steps:
    - uses: actions/checkout@v4
    - uses: actions/cache@v4
      name: Gradle Cache
      with:
        path: |
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
        restore-keys: |
          ${{ runner.os }}-gradle-
      # JDK is needed to generate code
    - name: Set up JDK
      uses: actions/setup-java@v4
      with:
        distribution: corretto
        java-package: jdk
        java-version: ${{ env.java_version }}
    - uses: dtolnay/rust-toolchain@master
      with:
        toolchain: ${{ env.rust_nightly_version }}
    - name: Generate doc preview
      id: generate-preview
      # Only generate three of the smallest services since the doc build can be very large. STS and SSO must be
      # included since aws-config depends on them. Transcribe Streaming and DynamoDB (paginators/waiters) were chosen
      # below to stay small while still representing most features. Combined, they are about ~20MB at time of writing.
      run: |
        ./gradlew -Paws.services=+sts,+sso,+ssooidc,+transcribestreaming,+dynamodb :aws:sdk:assemble

        # Copy the Server runtime crate(s) in
        cp -r rust-runtime/aws-smithy-http-server rust-runtime/aws-smithy-http-server-python rust-runtime/aws-smithy-http-server-typescript aws/sdk/build/aws-sdk/sdk

        pushd aws/sdk/build/aws-sdk

        # Remove example crates from workspace
        sed -i '/examples/d' Cargo.toml

        # Add server runtime crates to the workspace
        sed -i 's/"sdk\/sts",/"sdk\/sts","sdk\/aws-smithy-http-server","sdk\/aws-smithy-http-server-python","sdk\/aws-smithy-http-server-typescript",/' Cargo.toml

        RUSTDOCFLAGS="--cfg docsrs" cargo +${{ env.rust_nightly_version }} doc --all-features --no-deps

        popd
        ./tools/ci-scripts/generate-doc-preview-index.sh ${{ inputs.base_revision }}

        echo 'bot-message=A [new doc preview](https://d2luzm2xt3nokh.cloudfront.net/docs/'${{ inputs.head_revision }}'/index.html) is ready to view.' >> "${GITHUB_OUTPUT}"
    - uses: aws-actions/configure-aws-credentials@v4
      name: Acquire credentials for uploading to S3
      with:
        role-to-assume: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN }}
        role-session-name: GitHubActions
        aws-region: us-west-2
    - name: Upload doc preview to S3
      run: |
        aws s3 cp target/doc "s3://${S3_BUCKET_NAME}/docs/${{ inputs.head_revision }}" --recursive

  post-bot-comment:
    needs:
    - generate-diff
    - generate-doc-preview
    runs-on: ubuntu-latest
    name: Post bot comment
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    steps:
    - uses: actions/checkout@v4
      with:
        path: smithy-rs
    - name: Download all artifacts
      uses: ./smithy-rs/.github/actions/download-all-artifacts
    - name: Set bot message outputs
      id: bot-messages
      run: |
        set -eux
        echo "codegen-diff=$(cat ./bot-message-codegen-diff)" >> "${GITHUB_OUTPUT}"
    - name: Post bot comment
      uses: actions/github-script@v7
      with:
        script: |
          await github.rest.issues.createComment({
            issue_number: ${{ inputs.issue_number }},
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: '${{ steps.bot-messages.outputs.codegen-diff }}\n\n' +
              '${{ needs.generate-doc-preview.outputs.bot-message }}\n\n'
          })
