Skip to content

Commit 8ad565e

Browse files
authored
Merge pull request #177 from meta-pytorch/env-pr-action
[CI] Comment on new env PRs
2 parents a177d5d + b34a11b commit 8ad565e

File tree

1 file changed

+100
-111
lines changed

1 file changed

+100
-111
lines changed

.github/workflows/pr-new-env.yml

Lines changed: 100 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: PR New Environment
22

33
on:
4+
workflow_dispatch:
45
pull_request_target:
56
types:
67
- opened
@@ -94,17 +95,13 @@ jobs:
9495
echo "new_envs_json=${NEW_ENVS_JSON}" >> "$GITHUB_OUTPUT"
9596
9697
deploy-and-health-check:
97-
name: Deploy and Validate New Environments
98+
name: Validate New Environments
9899
needs: detect-new-envs
99100
if: needs.detect-new-envs.outputs.has_new_envs == 'true'
100101
runs-on: ubuntu-latest
101102
strategy:
102103
matrix:
103104
environment: ${{ fromJSON(needs.detect-new-envs.outputs.new_envs_json) }}
104-
env:
105-
HF_TOKEN: ${{ secrets.HF_PR_TOKEN }}
106-
HF_NAMESPACE: ${{ vars.HF_PR_NAMESPACE }}
107-
SPACE_SUFFIX: -pr-${{ github.event.number }}
108105
steps:
109106
- name: Checkout PR code
110107
uses: actions/checkout@v4
@@ -114,144 +111,136 @@ jobs:
114111
fetch-depth: 0
115112
persist-credentials: false
116113

117-
- name: Default Hugging Face namespace
118-
if: env.HF_NAMESPACE == ''
119-
shell: bash
120-
run: echo "HF_NAMESPACE=openenv-testing" >> "$GITHUB_ENV"
121-
122-
- name: Verify Hugging Face token
123-
shell: bash
124-
run: |
125-
if [ -z "${HF_TOKEN:-}" ]; then
126-
echo "HF_TOKEN secret is required for deployment." >&2
127-
exit 1
128-
fi
129-
130-
- name: Install Hugging Face CLI
131-
shell: bash
132-
run: |
133-
curl -LsSf https://hf.co/cli/install.sh | bash
134-
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
114+
- name: Set up Python
115+
uses: actions/setup-python@v5
116+
with:
117+
python-version: '3.11'
135118

136-
- name: Deploy environment to Hugging Face
119+
- name: Install OpenEnv package
137120
shell: bash
138121
run: |
139122
set -euo pipefail
140-
chmod +x scripts/deploy_to_hf.sh
141-
./scripts/deploy_to_hf.sh --env "${{ matrix.environment }}" --space-suffix "${SPACE_SUFFIX}" --hub-tag "openenv-pr"
123+
python -m pip install --upgrade pip
124+
pip install .
142125
143-
- name: Wait for deployment to stabilize
144-
shell: bash
145-
run: sleep 180
146-
147-
- name: Compute Space URLs
148-
id: urls
126+
- name: Run openenv validate --verbose
127+
id: validate
149128
shell: bash
150129
run: |
151-
set -euo pipefail
130+
set -u -o pipefail
131+
env_dir="src/envs/${{ matrix.environment }}"
152132
153-
if [ -z "${HF_NAMESPACE:-}" ]; then
154-
echo "HF_NAMESPACE is not configured; unable to compute space URLs." >&2
133+
if [ ! -d "$env_dir" ]; then
134+
echo "Environment directory not found: $env_dir" >&2
135+
echo "status=failure" >> "$GITHUB_OUTPUT"
136+
printf "details<<EOF\n%s\nEOF\n" "Environment directory not found" >> "$GITHUB_OUTPUT"
155137
exit 1
156138
fi
157139
158-
namespace_slug=$(echo "${HF_NAMESPACE}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
159-
space_name="${{ matrix.environment }}${SPACE_SUFFIX}"
160-
space_slug=$(echo "${space_name}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
161-
health_url="https://${namespace_slug}-${space_slug}.hf.space/health"
162-
live_url="https://${namespace_slug}-${space_slug}.hf.space"
163-
space_repo_url="https://huggingface.co/spaces/${HF_NAMESPACE}/${space_name}"
164-
165-
echo "namespace_slug=${namespace_slug}" >> "$GITHUB_OUTPUT"
166-
echo "space_name=${space_name}" >> "$GITHUB_OUTPUT"
167-
echo "space_slug=${space_slug}" >> "$GITHUB_OUTPUT"
168-
echo "health_url=${health_url}" >> "$GITHUB_OUTPUT"
169-
echo "live_url=${live_url}" >> "$GITHUB_OUTPUT"
170-
echo "space_repo_url=${space_repo_url}" >> "$GITHUB_OUTPUT"
171-
172-
- name: Perform environment health check
173-
id: health_check
174-
continue-on-error: true
175-
shell: bash
176-
env:
177-
HEALTH_URL: ${{ steps.urls.outputs.health_url }}
178-
SPACE_NAME: ${{ steps.urls.outputs.space_name }}
179-
run: |
180-
set -euo pipefail
140+
cd "$env_dir"
141+
echo "Running openenv validate --verbose in $(pwd)"
181142
182-
if [ -z "${HEALTH_URL:-}" ]; then
183-
echo "HEALTH_URL not provided; cannot perform health check." >&2
184-
exit 1
143+
output_file="$(mktemp)"
144+
if openenv validate --verbose | tee "$output_file"; then
145+
status="success"
146+
exit_code=0
147+
else
148+
status="failure"
149+
exit_code=$?
185150
fi
186151
187-
echo "Checking health for ${SPACE_NAME} at ${HEALTH_URL}"
152+
log_contents="$(cat "$output_file")"
153+
rm -f "$output_file"
188154
189-
success=0
190-
for attempt in {1..5}; do
191-
status=$(curl -sS -o response.json -w "%{http_code}" "$HEALTH_URL" || echo "000")
192-
if [ "$status" = "200" ]; then
193-
echo "Health check passed for ${SPACE_NAME}"
194-
cat response.json
195-
success=1
196-
break
197-
fi
198-
echo "Attempt ${attempt} returned status ${status}. Retrying in 30 seconds..."
199-
sleep 30
200-
done
155+
echo "status=${status}" >> "$GITHUB_OUTPUT"
156+
printf "details<<EOF\n%s\nEOF\n" "$log_contents" >> "$GITHUB_OUTPUT"
201157
202-
if [ $success -ne 1 ]; then
203-
echo "Health check failed for ${SPACE_NAME}" >&2
204-
if [ -f response.json ]; then
205-
echo "Last response payload:"
206-
cat response.json
207-
fi
208-
exit 1
209-
fi
158+
exit "$exit_code"
210159
211160
- name: Comment on PR with deployment status
212161
if: always()
213162
uses: actions/github-script@v7
214163
env:
215-
HEALTH_CONCLUSION: ${{ steps.health_check.conclusion }}
216-
SPACE_NAME: ${{ steps.urls.outputs.space_name }}
217-
LIVE_URL: ${{ steps.urls.outputs.live_url }}
218-
SPACE_REPO_URL: ${{ steps.urls.outputs.space_repo_url }}
164+
VALIDATION_STATUS: ${{ steps.validate.outputs.status }}
165+
VALIDATION_LOG: ${{ steps.validate.outputs.details }}
219166
ENV_NAME: ${{ matrix.environment }}
167+
COMMENT_TAG: "<!-- openenv-pr-preview -->"
220168
with:
221169
github-token: ${{ secrets.GITHUB_TOKEN }}
222170
script: |
223-
const status = process.env.HEALTH_CONCLUSION || 'failure';
224-
const spaceName = process.env.SPACE_NAME;
225-
const liveUrl = process.env.LIVE_URL;
226-
const repoUrl = process.env.SPACE_REPO_URL;
171+
const status = (process.env.VALIDATION_STATUS || '').toLowerCase() === 'success' ? 'success' : 'failure';
227172
const envName = process.env.ENV_NAME;
173+
const marker = process.env.COMMENT_TAG;
228174
229175
const header = status === 'success'
230-
? `✅ Deployment succeeded for \`${envName}\``
231-
: `⚠️ Deployment failed for \`${envName}\``;
176+
? `✅ Validation succeeded for \`${envName}\``
177+
: `⚠️ Validation failed for \`${envName}\``;
232178
233179
const summary = status === 'success'
234-
? 'Nice work! Wait for a code review and we\'re ready to go.'
235-
: 'Please resolve your environment.';
236-
237-
const body = [
180+
? 'Your env passes the vibe check. However, most environments should go straight to the hub, they will automatically be added to the official Env Hub collection on a nightly basis. Environments in the official specification repo are only meant to demonstrate usage of a specific spec feature for educational purposes. Re-run locally with:'
181+
: 'Validation reported issues. Review the log and re-run locally with `openenv validate --verbose`. Please note, we recently changed the standard template, your environment might pre-date this standard, follow the conversion guide https://github.com/meta-pytorch/OpenEnv/blob/main/scripts/CONVERT.md to convert your environment to the new standard.';
182+
183+
const envDir = 'src/envs/' + envName;
184+
const rawLog = process.env.VALIDATION_LOG || '';
185+
const trimmedLog = rawLog.trim();
186+
const maxLength = 6000;
187+
let displayLog = trimmedLog;
188+
if (displayLog.length > maxLength) {
189+
displayLog = displayLog.slice(0, maxLength) + '\n... (truncated)';
190+
}
191+
192+
const bodyLines = [
193+
marker,
194+
'',
238195
header,
239196
'',
240-
`- Space repo: [${repoUrl}](${repoUrl})`,
241-
`- Live URL: [${liveUrl}](${liveUrl})`,
242197
'',
243198
summary,
244199
'',
245-
'You can iterate locally or validate fixes by running `scripts/deploy_to_hf.sh --env "' + envName + '"`.'
246-
].join('\n');
247-
248-
await github.rest.issues.createComment({
249-
owner: context.repo.owner,
250-
repo: context.repo.repo,
251-
issue_number: context.payload.pull_request.number,
252-
body
253-
});
254-
255-
- name: Fail job if health check failed
256-
if: steps.health_check.conclusion == 'failure'
257-
run: exit 1
200+
'- `openenv validate --verbose ' + envDir + '`',
201+
'',
202+
'```\n' + displayLog + '\n```',
203+
'You can deploy the environment to Hugging Face Spaces by running `openenv push`.'
204+
];
205+
206+
const {owner, repo} = context.repo;
207+
const issue_number = context.payload.pull_request.number;
208+
const serverUrl = process.env.GITHUB_SERVER_URL || 'https://github.com';
209+
const runUrl = `${serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`;
210+
211+
if (status !== 'success') {
212+
bodyLines.push(`- Failed run: ${runUrl}`);
213+
} else {
214+
bodyLines.push(`- Success run: ${runUrl}`);
215+
}
216+
217+
const bodyText = bodyLines.join('\n');
218+
219+
const existing = await github.paginate(
220+
github.rest.issues.listComments,
221+
{ owner, repo, issue_number, per_page: 100 },
222+
(response, done) => {
223+
const match = response.data.find(comment => comment.body && comment.body.includes(marker));
224+
if (match) {
225+
done();
226+
return [match];
227+
}
228+
return [];
229+
}
230+
);
231+
232+
if (existing.length > 0) {
233+
await github.rest.issues.updateComment({
234+
owner,
235+
repo,
236+
comment_id: existing[0].id,
237+
body: bodyText,
238+
});
239+
} else {
240+
await github.rest.issues.createComment({
241+
owner,
242+
repo,
243+
issue_number,
244+
body: bodyText,
245+
});
246+
}

0 commit comments

Comments
 (0)