diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8890c37 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 5 + labels: + - "type: dependencies" + commit-message: + prefix: "ci" diff --git a/.github/workflows/preview-labels.yml b/.github/workflows/preview-labels.yml new file mode 100644 index 0000000..e9ed549 --- /dev/null +++ b/.github/workflows/preview-labels.yml @@ -0,0 +1,62 @@ +name: Preview organization labels + +on: + workflow_dispatch: + inputs: + repository: + description: "只预览指定仓库;留空预览全部可见仓库" + required: false + type: string + default: "" + + pull_request: + paths: + - ".github/labels.yml" + - ".github/actions/sync-labels/**" + - ".github/workflows/preview-labels.yml" + - ".github/workflows/sync-labels.yml" + + push: + branches: + - main + paths: + - ".github/labels.yml" + - ".github/actions/sync-labels/**" + - ".github/workflows/preview-labels.yml" + - ".github/workflows/sync-labels.yml" + + schedule: + # 每周一 UTC 03:17 检查公开可见仓库的标签漂移。 + - cron: "17 3 * * 1" + +permissions: + contents: read + issues: read + +concurrency: + group: preview-organization-labels-${{ github.ref }} + cancel-in-progress: true + +jobs: + preview-labels: + name: Preview organization label changes + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout governance repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + persist-credentials: false + + - name: Preview MathArts label synchronization + uses: ./.github/actions/sync-labels + with: + token: ${{ github.token }} + owner: ${{ github.repository_owner }} + config_file: ".github/labels.yml" + dry_run: "true" + repository: >- + ${{ github.event_name == 'workflow_dispatch' + && inputs.repository + || '' }} diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 326c244..0fe74ec 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -1,83 +1,47 @@ -name: Sync organization labels +name: Apply organization labels on: workflow_dispatch: inputs: - dry_run: - description: "仅预览变更;关闭后才会实际修改标签" - required: true - type: boolean - default: true - repository: description: "只同步指定仓库;留空同步全部仓库" required: false type: string default: "" - push: - branches: - - main - paths: - - ".github/labels.yml" - - ".github/actions/sync-labels/**" - - ".github/workflows/sync-labels.yml" - - schedule: - # 每周一 UTC 03:17 预览标签漂移,不自动写入仓库。 - - cron: "17 3 * * 1" + confirm_apply: + description: "确认执行真实标签变更" + required: true + type: boolean + default: false permissions: contents: read concurrency: - group: sync-organization-labels + group: apply-organization-labels cancel-in-progress: false jobs: - sync-labels: - name: Preview or synchronize organization labels + apply-labels: + name: Apply organization label changes + if: ${{ github.ref == 'refs/heads/main' && inputs.confirm_apply }} runs-on: ubuntu-latest timeout-minutes: 30 + environment: + name: label-governance-production steps: - name: Checkout governance repository - uses: actions/checkout@v7 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false - - name: Diagnose label sync token - shell: bash - env: - GH_TOKEN: ${{ secrets.LABEL_SYNC_TOKEN }} - run: | - set -euo pipefail - - echo "Testing repository access..." - gh api \ - -H "Accept: application/vnd.github+json" \ - /repos/matharts/.github \ - --jq '{full_name, private, archived, permissions}' - - echo "Testing label read access..." - gh api \ - -H "Accept: application/vnd.github+json" \ - "/repos/matharts/.github/labels?per_page=1" \ - --include - - - name: Run MathArts label sync + - name: Apply MathArts label synchronization uses: ./.github/actions/sync-labels with: - token: ${{ secrets.LABEL_SYNC_TOKEN }} + token: ${{ secrets.LABEL_SYNC_WRITE_TOKEN }} owner: ${{ github.repository_owner }} config_file: ".github/labels.yml" - - # Push 和定时任务只做预览。只有手动触发并关闭 dry_run 才实际写入。 - dry_run: >- - ${{ github.event_name != 'workflow_dispatch' - || inputs.dry_run }} - - repository: >- - ${{ github.event_name == 'workflow_dispatch' - && inputs.repository - || '' }} + dry_run: "false" + repository: ${{ inputs.repository }} diff --git a/.github/workflows/validate-documentation.yml b/.github/workflows/validate-documentation.yml index 8cbd5b9..43a95ab 100644 --- a/.github/workflows/validate-documentation.yml +++ b/.github/workflows/validate-documentation.yml @@ -42,7 +42,7 @@ jobs: timeout-minutes: 5 steps: - name: Checkout repository - uses: actions/checkout@v7 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false @@ -68,10 +68,10 @@ jobs: name: Lint Markdown runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false - - uses: DavidAnson/markdownlint-cli2-action@v24 + - uses: DavidAnson/markdownlint-cli2-action@8de2aa07cae85fd17c0b35642db70cf5495f1d25 # v24 with: config: ".markdownlint-cli2.jsonc" globs: "**/*.md" @@ -81,7 +81,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false @@ -99,10 +99,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false - - uses: lycheeverse/lychee-action@v2 + - uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2 with: args: >- --config lychee.toml diff --git a/README.md b/README.md index 996d42f..0e8f2ca 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,12 @@ MathArts 的组织级标签由两个权威来源共同维护: 标签同步只管理组织保留的 `type:*`、`status:*`、`priority:*`、`impact:*`、`process:*`、`resolution:*` 系列、贡献入口标签及其历史别名。项目仓库可以增加 `area:*`、`package:*`、`platform:*` 或其他项目特定标签,自动化会保留这些扩展标签。 -推送和定时任务只预览标签漂移。实际修改必须通过手动触发标签同步工作流,并明确关闭 Dry Run。 +标签自动化分为两个权限边界: + +* [`preview-labels.yml`](.github/workflows/preview-labels.yml) 在推送、定时任务或手动触发时使用只读 `github.token` 预览公开可见仓库的标签漂移,不读取跨仓库写令牌; +* [`sync-labels.yml`](.github/workflows/sync-labels.yml) 只允许从 `main` 手动触发真实变更,并绑定 `label-governance-production` Environment。 + +真实同步所需的 `LABEL_SYNC_WRITE_TOKEN` 必须配置为 `label-governance-production` 的 Environment Secret,而不是普通仓库 Secret。该 Environment 应在仓库设置中启用 Required reviewers,并禁止发起者自行批准。 ## 维护原则