Files
dingtalk-workspace-cli/docs/automation.md
T

7.0 KiB

Maintainer Automation Notes

This document keeps agent- and maintainer-specific workflow notes out of the repository root while preserving repo-local guidance for automation.

Read Order

  1. README.md
  2. CONTRIBUTING.md
  3. docs/architecture.md
  4. This document

Project Snapshot

  • dws is a Go-based DingTalk Workspace CLI and MCP runtime bridge.
  • Product commands are loaded dynamically via internal/plugin from bundled descriptors.
  • Command handlers live in internal/helpers; runtime execution flows through internal/executor and internal/transport.

Repository Map

  • cmd: public CLI entrypoint
  • internal/app: root command wiring, static utility commands, plugin loading
  • internal/helpers: product command handlers (dev, chat, calendar, contact, etc.)
  • internal/plugin: plugin-based dynamic command loader
  • internal/cli: catalog types and static endpoint loader
  • internal/executor: invocation dispatch and result handling
  • internal/transport: MCP HTTP client and request signing
  • internal/auth: login, token management, agent-code detection
  • internal/audit: user operation audit log
  • internal/errors: structured error model with categories and hints
  • internal/keychain: OS keychain integration for credential storage
  • internal/security: endpoint allowlist and domain trust
  • internal/pat: PAT (Personal Access Token) authorization flow
  • docs/: public architecture and reference docs
  • scripts/: build, test, lint, packaging, and policy checks
  • test/: CLI, integration, contract, unit, and skill E2E test suites

Task Routing

  • Add or fix a command path: start from internal/helpers (handler implementations) or internal/app (command tree wiring)
  • Protocol or transport issues: inspect internal/transport
  • Auth or login issues: inspect internal/auth, internal/pat, internal/keychain
  • Error message or category issues: inspect internal/errors
  • Audit log issues: inspect internal/audit
  • Plugin loading or command surface: inspect internal/plugin
  • Failure or degraded mode: inspect internal/errors, internal/recovery

Policy Checks

When command surface or plugin descriptors change, run:

  • ./scripts/policy/check-command-surface.sh --strict
  • ./scripts/policy/check-open-source-assets.sh

Common Commands

make build
make test
make lint
./scripts/dev/ci-local.sh
git diff --check

Homebrew Formula PR Automation

Official tag releases require the repository Actions secret HOMEBREW_PR_TOKEN. Prefer a fine-grained personal access token owned by a maintainer or release-bot account, limited to this repository with Contents: write and Pull requests: write. If organization policy prevents that account from targeting the repository, use a dedicated classic token with only the public_repo scope. Do not reuse a broad developer token.

Store the dedicated token as the HOMEBREW_PR_TOKEN repository Actions secret and rotate it before its configured expiration. Replace it immediately if it is exposed, its owner loses repository access, or the release-bot ownership changes. The Release workflow uses this dedicated token only to push an automation/homebrew-* branch and open the stable or beta Formula PR. It does not push Formula changes directly to main. The default-branch governance preflight and every tag contract authenticate the token before publication, reject over-scoped classic tokens, confirm its identity, and run a controlled write canary. The canary pushes a unique automation/homebrew-token-canary-* branch with a [skip ci] commit, creates a draft PR, closes it, and deletes the branch with the same token. This proves both Contents and Pull requests write access before publication without merging anything. The gate also rejects reuse of RELEASE_GOVERNANCE_TOKEN. No maintainer environment variable is required when creating a tag. Using the built-in GITHUB_TOKEN is insufficient because organization policy prevents Actions from creating pull requests, and its generated PR events may require separate workflow approval.

Release Governance and Recovery

Store RELEASE_GOVERNANCE_TOKEN as a dedicated Actions secret with only repository Administration: read. The immutable-releases REST endpoint is an administration setting and cannot be read by the workflow's built-in GITHUB_TOKEN. Both the default-branch governance preflight and the tag contract use this same credential so a missing or expired identity is detected before an irreversible tag is created.

Create a protected release-recovery environment limited to protected branches, with a required reviewer, self-review disabled, and administrator bypass disabled. The workflow reads the environment through the GitHub API and fails closed unless the required-reviewer, prevent-self-review, and protected- branch rules are present. Recovery is restricted to an existing annotated tag whose exact tag object, commit, and failed tag-push run all match; it then reuses the normal release jobs. Do not put publication secrets in temporary branches or create ad-hoc recovery workflows.

Cloud-sealed releases mirror to OSS only when the repository variable ENABLE_OSS_MIRROR is exactly true. Leave the variable unset while no Bucket is provisioned; GitHub, npm, and Homebrew delivery can then complete without running the OSS step. Once enabled, missing credentials, an invalid Bucket, or an upload failure remains fail-closed. The cloud tag immutably records the decision as OSS-Mirror: enabled|deferred; publication and withdrawal consume that sealed value instead of the variable's later state. Deferred releases cannot use repair_oss_version; enabling OSS applies to later release tags until an audited immutable repair marker is implemented.

If an immutable GitHub Release and npm package were delivered but an enabled downstream China mirror failed, dispatch the normal Release workflow from the protected default branch with exactly one of repair_gitee_version or repair_oss_version. Channel repair accepts a fully successful exact release, or a failed exact-tag run only when its latest attempt completed the release contract, build, Apple signature, immutable GitHub publication, and npm delivery checks for the exact tagged commit. OSS repair additionally requires the tag's sealed policy to be enabled. It then downloads and re-verifies the immutable assets before invoking only the selected mirror. For a failed release, an OSS repair requires the OSS step itself to be the recorded failure. A Gitee repair accepts either a failed Gitee job or a Gitee job that was skipped behind that OSS failure; the latter is an explicit Gitee backfill and does not claim that OSS has been repaired. Gitee repair requires GITEE_TOKEN, GITEE_USER, and GITEE_REPO; OSS repair requires OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, OSS_ENDPOINT, and OSS_BUCKET (with optional OSS_PREFIX) as Actions secrets. Missing credentials fail the selected repair closed.

Handoff Checklist

Before handoff, include:

  1. Changed files and why
  2. Verification commands run and outcomes
  3. Known risks or follow-up work