Skip to content

Commit e3ac67a

Browse files
authored
linux_job_v3: add label-gated HF cache refresh for OSDC runners (#8402)
## Summary Adds a `ci-refresh-hf-cache` label-gated path to refresh the shared OSDC HuggingFace cache from a `linux_job_v3` job, mirroring `pytorch/pytorch`'s `_linux-test.yml`. - **Resolve HF cache mode** (before `Run script`): with the label, repoints `HF_HOME`/`HF_DATASETS_CACHE` at writable `$RUNNER_TEMP` and forces online downloads via `GITHUB_ENV` (warm-copied from the seeded mount for incremental refresh). No label → unchanged read-only offline mount. The user `script` needs no changes. - **Refresh steps** (after `Run script`, gated on `HF_CACHE_REFRESH=1`): assume the `gha_workflow_hf-cache-write` OIDC role and `aws s3 sync` `hub/` + `datasets/` back to the bucket. Security: the label needs repo write access, the role trust policy gates on the calling repo, and auth runs after the script. Both refresh steps are `continue-on-error`. ## Consumer prerequisites (not in this PR) 1. Add the consuming repo (e.g. `pytorch/torchtitan`) to the `gha_workflow_hf-cache-write` trust policy in `pytorch-gha-infra`. 2. Create the `ci-refresh-hf-cache` label in that repo.
1 parent 7dea3c6 commit e3ac67a

2 files changed

Lines changed: 99 additions & 0 deletions

File tree

.github/workflows/linux_job_v3.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,31 @@ jobs:
209209
binary-matrix: ${{ inputs.binary-matrix }}
210210
target-os: "linux"
211211

212+
# Refresh run (PR labeled 'ci-refresh-hf-cache'): point HF at writable
213+
# ${RUNNER_TEMP} and download fresh, overriding the read-only /mnt/hf_cache
214+
# mount; the sync step below pushes it back to S3. Otherwise leave the mount.
215+
- name: Resolve HF cache mode
216+
shell: bash
217+
run: |
218+
set -euo pipefail
219+
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'ci-refresh-hf-cache') }}" == "true" ]]; then
220+
{
221+
echo "HF_CACHE_REFRESH=1"
222+
echo "TRANSFORMERS_OFFLINE=0"
223+
echo "HF_DATASETS_OFFLINE=0"
224+
echo "HF_HOME=${RUNNER_TEMP}/hf_cache"
225+
echo "HF_DATASETS_CACHE=${RUNNER_TEMP}/hf_datasets"
226+
} >> "${GITHUB_ENV}"
227+
mkdir -p "${RUNNER_TEMP}/hf_cache" "${RUNNER_TEMP}/hf_datasets"
228+
# datasets writes lock/arrow files even for seeded datasets, so warm the
229+
# writable dir from the read-only mount (matches pytorch's _linux-test.yml).
230+
if [[ -d /mnt/hf_cache/datasets ]]; then
231+
cp -a /mnt/hf_cache/datasets/. "${RUNNER_TEMP}/hf_datasets/" 2>/dev/null || true
232+
fi
233+
else
234+
echo "HF_CACHE_REFRESH=0" >> "${GITHUB_ENV}"
235+
fi
236+
212237
- name: Run script
213238
continue-on-error: ${{ inputs.continue-on-error }}
214239
working-directory: ${{ inputs.repository || github.repository }}
@@ -296,3 +321,44 @@ jobs:
296321
s3-prefix: ${{ env.REPOSITORY }}/${{ github.event.pull_request.number }}
297322
# Overwrite doc previews for the same PR
298323
overwrite: true
324+
325+
# HF cache refresh runs LAST: it swaps the job's AWS creds to the write role,
326+
# so it must come after every step that relies on role/arc (artifact/doc uploads).
327+
# The write role's trust policy gates on the calling repo, so unapproved repos
328+
# just fail auth here and the sync step is skipped rather than running with
329+
# leftover creds.
330+
- name: Authenticate to refresh the HF cache in S3
331+
id: hf-cache-auth
332+
if: ${{ always() && env.HF_CACHE_REFRESH == '1' }}
333+
continue-on-error: true
334+
uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # v1.7.0
335+
with:
336+
role-to-assume: arn:aws:iam::308535385114:role/gha_workflow_hf-cache-write
337+
aws-region: us-east-1
338+
339+
- name: Refresh the HF cache in S3
340+
if: ${{ always() && env.HF_CACHE_REFRESH == '1' && steps.hf-cache-auth.outcome == 'success' }}
341+
continue-on-error: true
342+
shell: bash
343+
run: |
344+
set -x
345+
# HF_CACHE_S3_BUCKET/REGION are injected by the OSDC hf-cache module.
346+
if [[ -z "${HF_CACHE_S3_BUCKET:-}" || -z "${HF_CACHE_S3_REGION:-}" ]]; then
347+
echo "HF_CACHE_S3_BUCKET/REGION unset (not an hf-cache runner) - skipping sync"
348+
exit 0
349+
fi
350+
# The job image may not ship the AWS CLI; fall back to a throwaway venv.
351+
AWS=aws
352+
if ! command -v aws >/dev/null 2>&1; then
353+
python3 -m venv /tmp/awscli-venv
354+
/tmp/awscli-venv/bin/pip install --quiet awscli==1.45.39
355+
AWS=/tmp/awscli-venv/bin/aws
356+
fi
357+
if [[ -d "${RUNNER_TEMP}/hf_cache/hub" ]]; then
358+
"${AWS}" s3 sync "${RUNNER_TEMP}/hf_cache/hub" "s3://${HF_CACHE_S3_BUCKET}/hub" \
359+
--region "${HF_CACHE_S3_REGION}" --no-progress
360+
fi
361+
if [[ -d "${RUNNER_TEMP}/hf_datasets" ]]; then
362+
"${AWS}" s3 sync "${RUNNER_TEMP}/hf_datasets" "s3://${HF_CACHE_S3_BUCKET}/datasets" \
363+
--region "${HF_CACHE_S3_REGION}" --no-progress
364+
fi

.github/workflows/test_linux_job_v3.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,36 @@ jobs:
205205
conda create --yes --quiet -n test python="${PYTHON_VERSION}"
206206
conda activate test
207207
python --version | grep "${PYTHON_VERSION}"
208+
# Verifies the "Resolve HF cache mode" step propagated the right env into the
209+
# script step. Adapts to the label: a PR labeled 'ci-refresh-hf-cache' exercises
210+
# the refresh branch (HF repointed to writable RUNNER_TEMP), any other PR
211+
# exercises the default (read-only) branch.
212+
# The actual S3 sync needs the write role + an approved repo, so it isn't covered.
213+
test-hf-cache-mode:
214+
uses: ./.github/workflows/linux_job_v3.yml
215+
permissions:
216+
id-token: write
217+
contents: read
218+
with:
219+
job-name: "linux-hf-cache-mode"
220+
runner: mt-l-x86iavx512-8-64
221+
test-infra-repository: ${{ github.repository }}
222+
test-infra-ref: ${{ github.ref }}
223+
gpu-arch-type: cpu
224+
gpu-arch-version: ""
225+
script: |
226+
set -x
227+
echo "HF_CACHE_REFRESH=${HF_CACHE_REFRESH:-<unset>} HF_HOME=${HF_HOME:-<unset>}"
228+
if [[ "${HF_CACHE_REFRESH:-}" == "1" ]]; then
229+
# Refresh branch: HF must be repointed at writable RUNNER_TEMP and online.
230+
[[ "${HF_HOME}" == "${RUNNER_TEMP}/hf_cache" ]] || { echo "HF_HOME not repointed"; exit 1; }
231+
[[ "${HF_DATASETS_CACHE}" == "${RUNNER_TEMP}/hf_datasets" ]] || { echo "HF_DATASETS_CACHE not repointed"; exit 1; }
232+
[[ "${TRANSFORMERS_OFFLINE}" == "0" && "${HF_DATASETS_OFFLINE}" == "0" ]] || { echo "not forced online"; exit 1; }
233+
touch "${HF_HOME}/.writable_probe" || { echo "HF_HOME not writable"; exit 1; }
234+
echo "refresh-mode env OK"
235+
else
236+
# Default branch: v3 must NOT hijack HF_HOME to the refresh temp dir.
237+
[[ "${HF_CACHE_REFRESH:-}" == "0" ]] || { echo "expected HF_CACHE_REFRESH=0"; exit 1; }
238+
[[ "${HF_HOME:-}" != "${RUNNER_TEMP}/hf_cache" ]] || { echo "HF_HOME unexpectedly repointed"; exit 1; }
239+
echo "default-mode env OK"
240+
fi

0 commit comments

Comments
 (0)