diff --git a/.ci/docker/common/install_user.sh b/.ci/docker/common/install_user.sh index 6deb62086b..dc9d1b8a86 100644 --- a/.ci/docker/common/install_user.sh +++ b/.ci/docker/common/install_user.sh @@ -9,9 +9,9 @@ set -ex -# Same as ec2-user -echo "ci-user:x:1000:1000::/var/lib/ci-user:" >> /etc/passwd -echo "ci-user:x:1000:" >> /etc/group +# Same uid as the OSDC runner, which owns the job workspace +echo "ci-user:x:1001:1001::/var/lib/ci-user:" >> /etc/passwd +echo "ci-user:x:1001:" >> /etc/group # Needed on Focal or newer echo "ci-user:*:19110:0:99999:7:::" >> /etc/shadow diff --git a/.github/labeler.yml b/.github/labeler.yml index d1a7c744ed..33e8f2a318 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -3,3 +3,17 @@ - .ci/docker/** - .github/workflows/docker-build.yml draft: false + +"ciflow/docs": + globs: + - "*.rst" + - "*.py" + - Makefile + - requirements.txt + - _static/** + - _templates/** + - "*_source/**" + - .jenkins/** + - .github/workflows/_build-tutorials-base.yml + - .github/workflows/build-tutorials.yml + draft: false diff --git a/.github/pytorch-probot.yml b/.github/pytorch-probot.yml index 606596e520..ca3fc45398 100644 --- a/.github/pytorch-probot.yml +++ b/.github/pytorch-probot.yml @@ -1,4 +1,5 @@ tracking_issue: 1896 ciflow_push_tags: - ciflow/docker +- ciflow/docs labeler_config: labeler.yml diff --git a/.github/workflows/_build-tutorials-base.yml b/.github/workflows/_build-tutorials-base.yml index f42ef7e1d2..9c6d749302 100644 --- a/.github/workflows/_build-tutorials-base.yml +++ b/.github/workflows/_build-tutorials-base.yml @@ -20,138 +20,100 @@ on: default: "pytorch/tutorials" jobs: - worker: - name: pytorch_tutorial_build_worker - strategy: - matrix: - include: - - { shard: 1, num_shards: 15, runner: "linux.g5.12xlarge.nvidia.gpu" } - - { shard: 2, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 3, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 4, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 5, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 6, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 7, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 8, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 9, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 10, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 11, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 12, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 13, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 14, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - - { shard: 15, num_shards: 15, runner: "linux.g5.4xlarge.nvidia.gpu" } - fail-fast: false - runs-on: ${{ matrix.runner }} + docker-image: + name: Resolve CI docker image + runs-on: ubuntu-latest + outputs: + docker-image: ${{ steps.tag.outputs.docker-image }} steps: - - name: Setup SSH (Click me for login details) - uses: pytorch/test-infra/.github/actions/setup-ssh@main - with: - github-secret: ${{ secrets.GITHUB_TOKEN }} - instructions: | - All testing is done inside the container, to start an interactive session run: - docker exec -it $(docker container ps --format '{{.ID}}') bash - - name: Checkout Tutorials uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Setup Linux - uses: pytorch/pytorch/.github/actions/setup-linux@main - - name: Install nvidia driver, nvidia-docker runtime, set GPU_FLAG - uses: pytorch/test-infra/.github/actions/setup-nvidia@main - - - name: Calculate/build docker image - id: calculate-docker-image - uses: pytorch/test-infra/.github/actions/calculate-docker-image@main - with: - docker-image-name: tutorials - - - name: Pull docker image - uses: pytorch/test-infra/.github/actions/pull-docker-image@main - with: - docker-image: ${{ steps.calculate-docker-image.outputs.docker-image }} - - - name: Build - shell: bash - env: - DOCKER_IMAGE: ${{ steps.calculate-docker-image.outputs.docker-image }} - NUM_WORKERS: ${{ matrix.num_shards }} - WORKER_ID: ${{ matrix.shard }} - COMMIT_ID: ${{ github.sha }} - JOB_TYPE: worker - COMMIT_SOURCE: ${{ github.ref }} - USE_NIGHTLY: ${{ inputs.USE_NIGHTLY }} - UPLOAD: ${{ inputs.UPLOAD }} + # Built and pushed by docker-build.yml, which a PR changing .ci/docker gets + # through the ciflow/docker label + - name: Compute the image tag + id: tag run: | - set -ex - - chmod +x ".jenkins/build.sh" - - container_name=$(docker run \ - ${GPU_FLAG:-} \ - -e WORKER_ID \ - -e NUM_WORKERS \ - -e COMMIT_ID \ - -e JOB_TYPE \ - -e COMMIT_SOURCE \ - -e USE_NIGHTLY \ - -e UPLOAD \ - --env-file="/tmp/github_env_${GITHUB_RUN_ID}" \ - --tty \ - --detach \ - --shm-size=2gb \ - --name="${container_name}" \ - -v "${GITHUB_WORKSPACE}:/var/lib/workspace" \ - -w /var/lib/workspace \ - "${DOCKER_IMAGE}" - ) - - docker exec -u ci-user -t "${container_name}" sh -c ".jenkins/build.sh" - - - name: Teardown Linux - uses: pytorch/test-infra/.github/actions/teardown-linux@main - if: always() + set -eu + DOCKER_TAG="$(git rev-parse HEAD:.ci/docker)" + echo "docker-image=308535385114.dkr.ecr.us-east-1.amazonaws.com/tutorials/tutorials:${DOCKER_TAG}" >> "${GITHUB_OUTPUT}" + worker: + name: pytorch_tutorial_build_worker + needs: docker-image + uses: pytorch/test-infra/.github/workflows/linux_job_v3.yml@main + permissions: + id-token: write + contents: read + strategy: + matrix: + include: + - { shard: 1, num_shards: 15, runner: "mt-l-x86aavx2-45-167-a10g-4" } + - { shard: 2, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 3, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 4, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 5, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 6, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 7, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 8, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 9, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 10, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 11, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 12, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 13, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 14, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + - { shard: 15, num_shards: 15, runner: "mt-l-x86aavx2-11-41-a10g" } + fail-fast: false + with: + job-name: pytorch_tutorial_build_worker + runner: ${{ matrix.runner }} + docker-image: ${{ needs.docker-image.outputs.docker-image }} + gpu-arch-type: cuda + fetch-depth: 0 + timeout: 120 + script: | + set -ex + + export NUM_WORKERS=${{ matrix.num_shards }} + export WORKER_ID=${{ matrix.shard }} + export COMMIT_ID=${{ github.sha }} + export JOB_TYPE=worker + export COMMIT_SOURCE=${{ github.ref }} + export USE_NIGHTLY=${{ inputs.USE_NIGHTLY }} + export UPLOAD=${{ inputs.UPLOAD }} + + .jenkins/build.sh + + # Not on linux_job_v3: a job calling a reusable workflow cannot set the environment + # that holds PYTORCHBOT_TOKEN, and the preview goes to a caller-chosen S3 prefix manager: name: pytorch_tutorial_build_manager - needs: worker - runs-on: [self-hosted, linux.2xlarge] + needs: [docker-image, worker] + runs-on: mt-l-x86iavx512-8-64 + container: + image: ${{ needs.docker-image.outputs.docker-image }} if: ${{ inputs.UPLOAD == 1 }} environment: ${{ github.ref == 'refs/heads/main' && 'pytorchbot-env' || '' }} + permissions: + id-token: write + contents: read + timeout-minutes: 120 steps: - - name: Setup SSH (Click me for login details) - uses: pytorch/test-infra/.github/actions/setup-ssh@main - with: - github-secret: ${{ secrets.GITHUB_TOKEN }} - instructions: | - All testing is done inside the container, to start an interactive session run: - docker exec -it $(docker container ps --format '{{.ID}}') bash - - name: Checkout Tutorials uses: actions/checkout@v6 with: fetch-depth: 0 - - name: Setup Linux - uses: pytorch/pytorch/.github/actions/setup-linux@main - - - name: Calculate/build docker image - id: calculate-docker-image - uses: pytorch/test-infra/.github/actions/calculate-docker-image@main + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 with: - docker-image-name: tutorials - - - name: Pull docker image - uses: pytorch/test-infra/.github/actions/pull-docker-image@main - with: - docker-image: ${{ steps.calculate-docker-image.outputs.docker-image }} + role-to-assume: arn:aws:iam::308535385114:role/arc + aws-region: us-east-1 + role-duration-seconds: 18000 - name: Build shell: bash env: - DOCKER_IMAGE: ${{ steps.calculate-docker-image.outputs.docker-image }} NUM_WORKERS: 15 WORKER_ID: 0 COMMIT_ID: ${{ github.sha }} @@ -161,39 +123,21 @@ jobs: USE_NIGHTLY: ${{ inputs.USE_NIGHTLY }} run: | set -ex + .jenkins/build.sh - chmod +x ".jenkins/build.sh" - - container_name=$(docker run \ - ${GPU_FLAG:-} \ - -e WORKER_ID \ - -e NUM_WORKERS \ - -e COMMIT_ID \ - -e JOB_TYPE \ - -e COMMIT_SOURCE \ - -e GITHUB_PYTORCHBOT_TOKEN \ - -e USE_NIGHTLY \ - --env-file="/tmp/github_env_${GITHUB_RUN_ID}" \ - --tty \ - --detach \ - --name="${container_name}" \ - -v "${GITHUB_WORKSPACE}:/var/lib/workspace" \ - -w /var/lib/workspace \ - "${DOCKER_IMAGE}" - ) - - docker exec -u ci-user -t "${container_name}" sh -c ".jenkins/build.sh" + # The ciflow/docs/ tag still names the pull request, so the preview + # keeps the per-PR prefix. An expression cannot split a ref, hence the step. + - name: Resolve the preview prefix + id: preview + if: ${{ startsWith(github.ref, 'refs/tags/ciflow/docs/') }} + run: echo "prefix=${GITHUB_REF##*/}" >> "${GITHUB_OUTPUT}" - name: Upload docs preview uses: seemethere/upload-artifact-s3@v5 - if: ${{ github.event_name == 'pull_request' }} + if: ${{ startsWith(github.ref, 'refs/tags/ciflow/docs/') }} with: retention-days: 14 s3-bucket: doc-previews if-no-files-found: error path: docs - s3-prefix: ${{ inputs.S3_PREFIX }}/${{ github.event.pull_request.number }} - - - name: Teardown Linux - uses: pytorch/test-infra/.github/actions/teardown-linux@main - if: always() + s3-prefix: ${{ inputs.S3_PREFIX }}/${{ steps.preview.outputs.prefix }} diff --git a/.github/workflows/build-tutorials-nightly.yml b/.github/workflows/build-tutorials-nightly.yml index 57aff644a8..98935baa33 100644 --- a/.github/workflows/build-tutorials-nightly.yml +++ b/.github/workflows/build-tutorials-nightly.yml @@ -29,6 +29,9 @@ concurrency: jobs: build: + permissions: + id-token: write + contents: read uses: ./.github/workflows/_build-tutorials-base.yml secrets: inherit with: diff --git a/.github/workflows/build-tutorials.yml b/.github/workflows/build-tutorials.yml index 58372d557e..bbbeedeaab 100644 --- a/.github/workflows/build-tutorials.yml +++ b/.github/workflows/build-tutorials.yml @@ -1,10 +1,13 @@ name: Build tutorials on: - pull_request: push: branches: - main + # A fork PR gets no OIDC token to upload the preview, so a PR builds through + # the ciflow/docs label, which pushes this tag from the base repo + tags: + - ciflow/docs/* concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.event_name == 'workflow_dispatch' }}-${{ github.event_name == 'schedule' }} @@ -12,6 +15,9 @@ concurrency: jobs: build: + permissions: + id-token: write + contents: read uses: ./.github/workflows/_build-tutorials-base.yml secrets: inherit with: