238 lines
10 KiB
YAML
238 lines
10 KiB
YAML
name: DSH Upstream Update
|
||
|
||
on:
|
||
schedule:
|
||
- cron: "0 4 * * *"
|
||
workflow_dispatch:
|
||
|
||
concurrency:
|
||
group: dsh-upstream-update
|
||
cancel-in-progress: false
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
env:
|
||
BASE_BRANCH: dev
|
||
CANDIDATE_BRANCH: automation/dsh-upstream-candidate
|
||
DSH_PACKAGE: "@deepseek-ai/dsh"
|
||
SUPPORTED_TARGET: release/supported-target.json
|
||
ENVIRONMENT_DEFINITION: container/environment/definition.json
|
||
|
||
jobs:
|
||
discover:
|
||
name: Discover and propose upstream DSH
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
pull-requests: write
|
||
outputs:
|
||
changed: ${{ steps.candidate.outputs.changed }}
|
||
current: ${{ steps.candidate.outputs.current }}
|
||
upstream: ${{ steps.candidate.outputs.upstream }}
|
||
environment: ${{ steps.candidate.outputs.environment }}
|
||
pull_request_url: ${{ steps.propose.outputs.pull_request_url }}
|
||
pull_request_number: ${{ steps.propose.outputs.pull_request_number }}
|
||
head_sha: ${{ steps.propose.outputs.head_sha }}
|
||
|
||
steps:
|
||
- name: Checkout protected branch
|
||
uses: actions/checkout@v6
|
||
with:
|
||
ref: ${{ env.BASE_BRANCH }}
|
||
fetch-depth: 0
|
||
|
||
- name: Set up Node.js
|
||
uses: actions/setup-node@v6
|
||
with:
|
||
node-version: 24
|
||
|
||
- name: Resolve latest official DSH
|
||
id: upstream
|
||
run: |
|
||
npm view "${DSH_PACKAGE}@latest" version --json > "$RUNNER_TEMP/dsh-version.json"
|
||
version="$(jq -er 'if type == "string" then . else error("expected one version") end' "$RUNNER_TEMP/dsh-version.json")"
|
||
printf 'version=%s\n' "$version" >> "$GITHUB_OUTPUT"
|
||
|
||
- name: Advance candidate Supported Target
|
||
id: candidate
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
UPSTREAM_VERSION: ${{ steps.upstream.outputs.version }}
|
||
run: |
|
||
base_sha="$(git rev-parse HEAD)"
|
||
current="$(jq -er '.latestSupportedDsh' "$SUPPORTED_TARGET")"
|
||
trusted_platform="$RUNNER_TEMP/trusted-platform"
|
||
mkdir -p "$trusted_platform/tools"
|
||
cp -R container/platform/lib "$trusted_platform/lib"
|
||
cp container/platform/tools/supported-target.mjs "$trusted_platform/tools/supported-target.mjs"
|
||
git config user.name "github-actions[bot]"
|
||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||
candidate_remote_sha="$(git ls-remote --heads origin "$CANDIDATE_BRANCH" | cut -f 1)"
|
||
git switch --create "$CANDIDATE_BRANCH" "$base_sha"
|
||
result="$(node "$trusted_platform/tools/supported-target.mjs" advance \
|
||
"$SUPPORTED_TARGET" "$ENVIRONMENT_DEFINITION" "$UPSTREAM_VERSION")"
|
||
changed="$(jq -r 'if (.changed | type) == "boolean" then .changed else error("expected boolean changed") end' <<<"$result")"
|
||
environment="$(jq -er '.target.environment' <<<"$result")"
|
||
{
|
||
printf 'changed=%s\n' "$changed"
|
||
printf 'current=%s\n' "$current"
|
||
printf 'upstream=%s\n' "$UPSTREAM_VERSION"
|
||
printf 'environment=%s\n' "$environment"
|
||
printf 'candidate_remote_sha=%s\n' "$candidate_remote_sha"
|
||
} >> "$GITHUB_OUTPUT"
|
||
# shellcheck disable=SC2016
|
||
{
|
||
printf '### DSH upstream discovery\n\n'
|
||
printf -- '- Latest Supported: `%s`\n' "$current"
|
||
printf -- '- Latest Official: `%s`\n' "$UPSTREAM_VERSION"
|
||
printf -- '- Environment: `%s`\n' "$environment"
|
||
printf -- '- Candidate required: `%s`\n' "$changed"
|
||
} >> "$GITHUB_STEP_SUMMARY"
|
||
|
||
- name: Create or update candidate pull request
|
||
id: propose
|
||
if: steps.candidate.outputs.changed == 'true'
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
CURRENT_VERSION: ${{ steps.candidate.outputs.current }}
|
||
UPSTREAM_VERSION: ${{ steps.candidate.outputs.upstream }}
|
||
ENVIRONMENT_VERSION: ${{ steps.candidate.outputs.environment }}
|
||
run: |
|
||
git add -- "$SUPPORTED_TARGET"
|
||
git commit -m "chore(dsh): validate ${UPSTREAM_VERSION}"
|
||
|
||
candidate_remote_sha="${{ steps.candidate.outputs.candidate_remote_sha }}"
|
||
if [ -n "$candidate_remote_sha" ]; then
|
||
git push --force-with-lease="refs/heads/$CANDIDATE_BRANCH:$candidate_remote_sha" \
|
||
origin "HEAD:refs/heads/$CANDIDATE_BRANCH"
|
||
else
|
||
git push origin "HEAD:refs/heads/$CANDIDATE_BRANCH"
|
||
fi
|
||
|
||
body="$RUNNER_TEMP/dsh-candidate-pr.md"
|
||
# shellcheck disable=SC2016
|
||
{
|
||
printf '## DSH candidate validation\n\n'
|
||
printf '| State | Version |\n|---|---|\n'
|
||
printf '| Latest Supported | `%s` |\n' "$CURRENT_VERSION"
|
||
printf '| Latest Official candidate | `%s` |\n' "$UPSTREAM_VERSION"
|
||
printf '| Current Environment | `%s` |\n\n' "$ENVIRONMENT_VERSION"
|
||
printf 'This PR changes only the candidate Supported Target. Compatibility CI validates the new DSH with the current Environment. Merge into dev records the validated candidate; promotion from dev to main remains the production publication gate.\n'
|
||
} > "$body"
|
||
|
||
pr_number="$(gh pr list --state open --head "$CANDIDATE_BRANCH" --json number --jq '.[0].number // empty')"
|
||
if [ -z "$pr_number" ]; then
|
||
pr_url="$(gh pr create \
|
||
--base "$BASE_BRANCH" \
|
||
--head "$CANDIDATE_BRANCH" \
|
||
--title "chore(dsh): validate ${UPSTREAM_VERSION}" \
|
||
--body-file "$body")"
|
||
pr_number="$(gh pr view "$pr_url" --json number --jq .number)"
|
||
else
|
||
gh pr edit "$pr_number" \
|
||
--base "$BASE_BRANCH" \
|
||
--title "chore(dsh): validate ${UPSTREAM_VERSION}" \
|
||
--body-file "$body"
|
||
pr_url="$(gh pr view "$pr_number" --json url --jq .url)"
|
||
fi
|
||
{
|
||
printf 'pull_request_url=%s\n' "$pr_url"
|
||
printf 'pull_request_number=%s\n' "$pr_number"
|
||
printf 'head_sha=%s\n' "$(git rev-parse HEAD)"
|
||
} >> "$GITHUB_OUTPUT"
|
||
printf 'Candidate PR: %s\n' "$pr_url" >> "$GITHUB_STEP_SUMMARY"
|
||
|
||
validate-candidate:
|
||
name: Validate candidate Runtime
|
||
needs: discover
|
||
if: needs.discover.outputs.changed == 'true'
|
||
permissions:
|
||
contents: read
|
||
uses: ./.github/workflows/dsh-candidate-validation.yml
|
||
with:
|
||
ref: ${{ needs.discover.outputs.head_sha }}
|
||
|
||
report-validation:
|
||
name: Report candidate validation
|
||
needs: [discover, validate-candidate]
|
||
if: always() && needs.discover.outputs.changed == 'true'
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: read
|
||
pull-requests: write
|
||
statuses: write
|
||
steps:
|
||
- name: Publish commit status and PR report
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
HEAD_SHA: ${{ needs.discover.outputs.head_sha }}
|
||
PR_NUMBER: ${{ needs.discover.outputs.pull_request_number }}
|
||
VALIDATION_RESULT: ${{ needs.validate-candidate.result }}
|
||
UPSTREAM_VERSION: ${{ needs.discover.outputs.upstream }}
|
||
ENVIRONMENT_VERSION: ${{ needs.discover.outputs.environment }}
|
||
run: |
|
||
if [ "$VALIDATION_RESULT" = success ]; then
|
||
state=success
|
||
label=passed
|
||
description="Candidate Runtime validation passed"
|
||
else
|
||
state=failure
|
||
label=failed
|
||
description="Candidate Runtime validation failed"
|
||
fi
|
||
run_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
|
||
gh api --method POST "/repos/${GITHUB_REPOSITORY}/statuses/${HEAD_SHA}" \
|
||
-f state="$state" \
|
||
-f context='DSH candidate Runtime' \
|
||
-f description="$description" \
|
||
-f target_url="$run_url" >/dev/null
|
||
gh pr comment "$PR_NUMBER" \
|
||
--repo "$GITHUB_REPOSITORY" \
|
||
--body "DSH \`${UPSTREAM_VERSION}\` with Environment \`${ENVIRONMENT_VERSION}\` **${label}** compatibility validation. [Open workflow run](${run_url})."
|
||
printf 'Candidate validation %s: %s\n' "$label" "$run_url" >> "$GITHUB_STEP_SUMMARY"
|
||
|
||
notify-discovered:
|
||
name: Notify upstream discovery
|
||
needs: discover
|
||
if: needs.discover.outputs.changed == 'true'
|
||
uses: yjrszcq/github-workflows/.github/workflows/gotify-notify.yml@c4c7fe9e17854cd4962913ac2792513eab0be988
|
||
with:
|
||
title: 发现 DSH 上游新版本 ${{ needs.discover.outputs.upstream }}
|
||
message: >-
|
||
当前支持版本:${{ needs.discover.outputs.current }};上游候选版本:${{ needs.discover.outputs.upstream }}。
|
||
候选 Environment:${{ needs.discover.outputs.environment }}。
|
||
候选 PR:${{ needs.discover.outputs.pull_request_url }}
|
||
priority: 6
|
||
secrets:
|
||
gotify_url: ${{ secrets.GOTIFY_URL }}
|
||
gotify_token: ${{ secrets.GOTIFY_TOKEN }}
|
||
|
||
notify-result:
|
||
name: Notify upstream check result
|
||
needs: [discover, validate-candidate]
|
||
if: >-
|
||
always() &&
|
||
(needs.discover.result == 'failure' || needs.discover.outputs.changed == 'true')
|
||
uses: yjrszcq/github-workflows/.github/workflows/gotify-notify.yml@c4c7fe9e17854cd4962913ac2792513eab0be988
|
||
with:
|
||
title: >-
|
||
${{
|
||
needs.discover.result == 'failure' && 'DSH 上游检查失败' ||
|
||
(needs.validate-candidate.result == 'success' &&
|
||
format('DSH {0} 候选版本验证通过', needs.discover.outputs.upstream) ||
|
||
format('DSH {0} 候选版本验证失败', needs.discover.outputs.upstream))
|
||
}}
|
||
message: >-
|
||
${{
|
||
needs.discover.result == 'failure' &&
|
||
format('获取或生成 DSH 上游候选版本失败。工作流:{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) ||
|
||
(needs.validate-candidate.result == 'success' &&
|
||
format('DSH {0} 已通过 Environment {1} 兼容性验证。请审核并合并:{2}', needs.discover.outputs.upstream, needs.discover.outputs.environment, needs.discover.outputs.pull_request_url) ||
|
||
format('DSH {0} 未通过 Environment {1} 兼容性验证,需要适配 Environment。工作流:{2}/{3}/actions/runs/{4}', needs.discover.outputs.upstream, needs.discover.outputs.environment, github.server_url, github.repository, github.run_id))
|
||
}}
|
||
priority: ${{ (needs.discover.result == 'failure' || needs.validate-candidate.result != 'success') && 8 || 7 }}
|
||
secrets:
|
||
gotify_url: ${{ secrets.GOTIFY_URL }}
|
||
gotify_token: ${{ secrets.GOTIFY_TOKEN }}
|