Skip to content

블로그 글 추가: 2026-06-30-miles-a-pytorch-native-stack-for-large-scale-llm-rl-post-training, Miles: 대규모 LLM RL 사후 학습을 위한 PyTorch 네이티브 스택 #98

블로그 글 추가: 2026-06-30-miles-a-pytorch-native-stack-for-large-scale-llm-rl-post-training, Miles: 대규모 LLM RL 사후 학습을 위한 PyTorch 네이티브 스택

블로그 글 추가: 2026-06-30-miles-a-pytorch-native-stack-for-large-scale-llm-rl-post-training, Miles: 대규모 LLM RL 사후 학습을 위한 PyTorch 네이티브 스택 #98

Workflow file for this run

name: PR Preview
on:
pull_request:
types: [opened, synchronize, reopened, closed]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to build preview for'
required: true
type: number
schedule:
- cron: '0 0 * * 0' # 매주 일요일 자정 (UTC)
permissions:
contents: read
pull-requests: write
concurrency:
group: pr-preview-${{ github.event.pull_request.number || github.event.inputs.pr_number || 'cleanup' }}
cancel-in-progress: true
jobs:
build-and-deploy:
if: github.event_name == 'pull_request' && github.event.action != 'closed' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
env:
PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
steps:
- name: Checkout PR branch
uses: actions/checkout@v3
with:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/pull/{0}/head', github.event.inputs.pr_number) || '' }}
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 22.17.1
- name: Install node dependencies
run: |
npm install -g yarn
yarn install
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libffi-dev build-essential
- name: Set up Ruby 3.4
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.4.5
bundler-cache: true
- name: Verify bundler and install dependencies
run: |
bundler --version
gem install rake
bundle check || bundle install --jobs 4 --retry 3
- name: Initialize & update hub submodule
run: |
git submodule deinit -f . && git submodule update --init --recursive
git submodule update --remote
./_devel/update_hub_submodule.sh
- name: Copy vendor assets
run: make include-yarn-deps
- name: Build Jekyll site
env:
JEKYLL_GITHUB_TOKEN: ${{ secrets.JEKYLL_GITHUB_TOKEN }}
run: |
JEKYLL_ENV=preview bundle exec jekyll build
- name: Deploy to surge.sh
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository
env:
SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }}
SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
run: |
npm install -g surge
surge ./_site pytorchkr-pr-preview-${{ env.PR_NUMBER }}.surge.sh
- name: Comment preview URL on PR
if: success() && (github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository)
uses: actions/github-script@v7
with:
script: |
const prNumber = process.env.PR_NUMBER;
const previewUrl = `https://pytorchkr-pr-preview-${prNumber}.surge.sh`;
const body = [
'## PR Preview',
'',
'빌드가 완료되었습니다! 아래 링크에서 변경사항을 확인할 수 있습니다.',
'',
`**미리보기**: ${previewUrl}`,
'',
'> 이 미리보기는 PR이 업데이트될 때마다 자동으로 갱신됩니다.',
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const botComment = comments.find(c => c.body.includes('PR Preview'));
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}
- name: Comment build failure on PR
if: failure()
uses: actions/github-script@v7
with:
script: |
const prNumber = process.env.PR_NUMBER;
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const body = [
'## PR Preview - Build Failed',
'',
`빌드 중 오류가 발생했습니다. [워크플로우 로그](${runUrl})를 확인해주세요.`,
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const botComment = comments.find(c => c.body.includes('PR Preview'));
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}
cleanup:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Teardown surge.sh preview
env:
SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }}
SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
run: |
npm install -g surge
surge teardown pytorchkr-pr-preview-${{ github.event.pull_request.number }}.surge.sh
- name: Comment cleanup on PR
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const botComment = comments.find(c => c.body.includes('PR Preview'));
if (botComment) {
const body = [
'## PR Preview',
'',
'~~미리보기가 삭제되었습니다.~~',
'',
'> PR이 닫혀 미리보기가 자동으로 정리되었습니다.',
].join('\n');
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body,
});
}
stale-cleanup:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
env:
SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }}
SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
with:
script: |
const { data: pulls } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
sort: 'updated',
direction: 'desc',
per_page: 100,
});
const now = new Date();
const threeDaysAgo = new Date(now - 3 * 24 * 60 * 60 * 1000);
const stale = pulls.filter(pr => new Date(pr.closed_at) < threeDaysAgo);
if (stale.length === 0) {
console.log('No stale previews to clean up.');
return;
}
const prNumbers = stale.map(pr => pr.number);
console.log(`Cleaning up previews for ${prNumbers.length} closed PRs: ${prNumbers.join(', ')}`);
core.exportVariable('STALE_PRS', prNumbers.join(' '));
- name: Teardown stale surge.sh previews
if: env.STALE_PRS != ''
env:
SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }}
SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
run: |
npm install -g surge
for pr in $STALE_PRS; do
echo "Tearing down pytorchkr-pr-preview-${pr}.surge.sh..."
surge teardown "pytorchkr-pr-preview-${pr}.surge.sh" || true
done