Merge branch 'main' into feat/85378080-chat-message-time-defaults
This commit is contained in:
@@ -2645,6 +2645,40 @@ jobs:
|
||||
"$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-github-tag-authority.sh" \
|
||||
"$RELEASE_VERSION" "$RELEASE_COMMIT" "$RELEASE_TAG_OBJECT"
|
||||
|
||||
# The sealed candidate tag is intentionally visible while its GitHub
|
||||
# authority is checked above. Compatibility must instead discover the
|
||||
# previous delivered stable tag, so hide only this verified candidate
|
||||
# from this isolated runner's local tag namespace.
|
||||
- name: Prepare delivered-stable compatibility ref view
|
||||
if: ${{ matrix.check == 'compatibility' }}
|
||||
env:
|
||||
RELEASE_VERSION: ${{ needs.release-contract.outputs.release_version }}
|
||||
RELEASE_COMMIT: ${{ needs.release-contract.outputs.release_commit }}
|
||||
RELEASE_TAG_OBJECT: ${{ needs.release-contract.outputs.release_tag_object }}
|
||||
PREVIOUS_STABLE: ${{ needs.release-contract.outputs.previous_stable }}
|
||||
PREVIOUS_STABLE_COMMIT: ${{ needs.release-contract.outputs.previous_stable_commit }}
|
||||
run: |
|
||||
set -eu
|
||||
test -n "$RELEASE_VERSION"
|
||||
test -n "$RELEASE_COMMIT"
|
||||
test -n "$RELEASE_TAG_OBJECT"
|
||||
test -n "$PREVIOUS_STABLE"
|
||||
test -n "$PREVIOUS_STABLE_COMMIT"
|
||||
test "$RELEASE_VERSION" != "$PREVIOUS_STABLE"
|
||||
test "$(git rev-parse HEAD)" = "$RELEASE_COMMIT"
|
||||
test "$(git rev-parse --verify "refs/tags/${RELEASE_VERSION}")" = "$RELEASE_TAG_OBJECT"
|
||||
test "$(git rev-parse --verify "refs/tags/${RELEASE_VERSION}^{commit}")" = "$RELEASE_COMMIT"
|
||||
test "$(git rev-parse --verify "${PREVIOUS_STABLE}^{commit}")" = "$PREVIOUS_STABLE_COMMIT"
|
||||
|
||||
git update-ref -d "refs/tags/${RELEASE_VERSION}" "$RELEASE_TAG_OBJECT"
|
||||
|
||||
if git show-ref --verify --quiet "refs/tags/${RELEASE_VERSION}"; then
|
||||
echo "sealed candidate tag is still visible to compatibility baseline discovery" >&2
|
||||
exit 2
|
||||
fi
|
||||
test "$(git rev-parse HEAD)" = "$RELEASE_COMMIT"
|
||||
test "$(git rev-parse --verify "${PREVIOUS_STABLE}^{commit}")" = "$PREVIOUS_STABLE_COMMIT"
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
class DingtalkWorkspaceCli < Formula
|
||||
desc "Automate DingTalk workspace tasks from the terminal"
|
||||
homepage "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli"
|
||||
version "1.0.57"
|
||||
version "1.0.58"
|
||||
license "Apache-2.0"
|
||||
|
||||
|
||||
on_macos do
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.57/dws-darwin-arm64.tar.gz"
|
||||
sha256 "c01c28dc13948a70fca905207073dc8dbd22f7ba7fc90e68b3316eb9a9c98e88"
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.58/dws-darwin-arm64.tar.gz"
|
||||
sha256 "7d98599f90cae9d42b51ff2863efc87dbfb4a3176ff3c84fc2216110c0157a70"
|
||||
else
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.57/dws-darwin-amd64.tar.gz"
|
||||
sha256 "d7baa218beefc851c6a933b456055195f8272984ce008d7e0122bdfc5dad94ea"
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.58/dws-darwin-amd64.tar.gz"
|
||||
sha256 "4c12e35e5bf7e0905812cd42dc94a5345068a2c16e306bb50b13c5c78b5cb95d"
|
||||
end
|
||||
end
|
||||
|
||||
on_linux do
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.57/dws-linux-arm64.tar.gz"
|
||||
sha256 "0bbe9c233a3ff585077bae1ac5000937c32d967846d14cc44c46f98d49b95ae2"
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.58/dws-linux-arm64.tar.gz"
|
||||
sha256 "5ef6bde24bc3db6a11a0f1d0b3343a048956b2cbcf6cd3409a037fb6ba425489"
|
||||
else
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.57/dws-linux-amd64.tar.gz"
|
||||
sha256 "f113ce3654f21d1f9ecc7c196f815aeafbca54d377a347b244a15116c5cba698"
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.58/dws-linux-amd64.tar.gz"
|
||||
sha256 "3ccadcc6f070a39d2b2ba20429a4fcdc2f21639bf79f34361dc7d16f501bfda6"
|
||||
end
|
||||
end
|
||||
|
||||
resource "skills" do
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.57/dws-skills.zip"
|
||||
sha256 "0c9667209cf30761427a8f9348149cbbf1e397aa3c25587e99f205bc7525e101"
|
||||
url "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.58/dws-skills.zip"
|
||||
sha256 "2626debc21c3daadfd155b4c167b2219b97e801398fe4441a8b48138960ab264"
|
||||
end
|
||||
|
||||
def install
|
||||
|
||||
@@ -928,6 +928,39 @@
|
||||
"state": "pending",
|
||||
"reason": "保留旧 argv 兼容性,并将 IM ID 规范 flag 设为唯一可见入口"
|
||||
},
|
||||
{
|
||||
"command": "dws chat message send",
|
||||
"legacy": {
|
||||
"name": "uuid",
|
||||
"before": {
|
||||
"present": true,
|
||||
"type": "string",
|
||||
"scope": "local",
|
||||
"required": false
|
||||
},
|
||||
"after": {
|
||||
"present": true,
|
||||
"type": "string",
|
||||
"scope": "local",
|
||||
"hidden": true,
|
||||
"alias_of": "idempotency-key"
|
||||
}
|
||||
},
|
||||
"canonical": {
|
||||
"name": "idempotency-key",
|
||||
"before": {
|
||||
"present": false
|
||||
},
|
||||
"after": {
|
||||
"present": true,
|
||||
"type": "string",
|
||||
"scope": "local",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"state": "pending",
|
||||
"reason": "保留旧 argv 兼容性,并将幂等参数规范 flag 设为唯一可见入口"
|
||||
},
|
||||
{
|
||||
"command": "dws chat message set-pin-msg",
|
||||
"legacy": {
|
||||
|
||||
@@ -1222,6 +1222,136 @@ func TestReleaseWorkflowParallelizesSealedValidationWithoutWeakeningPublication(
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseWorkflowHidesOnlyVerifiedSealedTagFromCompatibilityBaseline(t *testing.T) {
|
||||
t.Parallel()
|
||||
workflow := readReleaseWorkflow(t)
|
||||
validation := releaseWorkflowSection(t, workflow, " release-validation:\n", "\n release-plan:\n")
|
||||
preparedView := releaseWorkflowSection(
|
||||
t,
|
||||
validation,
|
||||
" - name: Prepare delivered-stable compatibility ref view\n",
|
||||
"\n - name: Set up Go\n",
|
||||
)
|
||||
script := releaseWorkflowRunScript(
|
||||
t,
|
||||
validation,
|
||||
"Prepare delivered-stable compatibility ref view",
|
||||
"Set up Go",
|
||||
)
|
||||
|
||||
if !strings.Contains(preparedView, "if: ${{ matrix.check == 'compatibility' }}") {
|
||||
t.Fatal("delivered-stable ref view must run only for the compatibility matrix leg")
|
||||
}
|
||||
for _, required := range []string{
|
||||
"RELEASE_VERSION: ${{ needs.release-contract.outputs.release_version }}",
|
||||
"RELEASE_COMMIT: ${{ needs.release-contract.outputs.release_commit }}",
|
||||
"RELEASE_TAG_OBJECT: ${{ needs.release-contract.outputs.release_tag_object }}",
|
||||
"PREVIOUS_STABLE: ${{ needs.release-contract.outputs.previous_stable }}",
|
||||
"PREVIOUS_STABLE_COMMIT: ${{ needs.release-contract.outputs.previous_stable_commit }}",
|
||||
} {
|
||||
if !strings.Contains(preparedView, required) {
|
||||
t.Errorf("delivered-stable compatibility view is missing %q", required)
|
||||
}
|
||||
}
|
||||
for _, required := range []string{
|
||||
`test "$RELEASE_VERSION" != "$PREVIOUS_STABLE"`,
|
||||
`test "$(git rev-parse HEAD)" = "$RELEASE_COMMIT"`,
|
||||
`test "$(git rev-parse --verify "refs/tags/${RELEASE_VERSION}")" = "$RELEASE_TAG_OBJECT"`,
|
||||
`test "$(git rev-parse --verify "refs/tags/${RELEASE_VERSION}^{commit}")" = "$RELEASE_COMMIT"`,
|
||||
`test "$(git rev-parse --verify "${PREVIOUS_STABLE}^{commit}")" = "$PREVIOUS_STABLE_COMMIT"`,
|
||||
`git update-ref -d "refs/tags/${RELEASE_VERSION}" "$RELEASE_TAG_OBJECT"`,
|
||||
`git show-ref --verify --quiet "refs/tags/${RELEASE_VERSION}"`,
|
||||
} {
|
||||
if !strings.Contains(script, required) {
|
||||
t.Errorf("delivered-stable compatibility view is missing %q", required)
|
||||
}
|
||||
}
|
||||
|
||||
verifiedTag := strings.Index(validation, "verify-github-tag-authority.sh")
|
||||
deleteLocalTag := strings.Index(validation, "git update-ref -d")
|
||||
compatibility := strings.Index(validation, "check-command-compatibility.sh")
|
||||
if verifiedTag == -1 || deleteLocalTag == -1 || compatibility == -1 ||
|
||||
verifiedTag > deleteLocalTag || deleteLocalTag > compatibility {
|
||||
t.Fatal("release tag authority verification, local candidate removal, and compatibility checking must stay ordered")
|
||||
}
|
||||
for _, forbidden := range []string{"git push --delete", "github.rest.git.deleteRef"} {
|
||||
if strings.Contains(workflow, forbidden) {
|
||||
t.Errorf("release workflow must not delete a remote ref: found %q", forbidden)
|
||||
}
|
||||
}
|
||||
|
||||
repo, err := os.MkdirTemp(".", ".release-compatibility-test-")
|
||||
if err != nil {
|
||||
t.Fatalf("MkdirTemp(release compatibility test repository) error = %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := os.RemoveAll(repo); err != nil {
|
||||
t.Errorf("RemoveAll(%s) error = %v", repo, err)
|
||||
}
|
||||
})
|
||||
mustRun(t, repo, "git", "init", "-b", "main")
|
||||
mustRun(t, repo, "git", "config", "user.name", "Release Compatibility Test")
|
||||
mustRun(t, repo, "git", "config", "user.email", "release-compatibility@example.com")
|
||||
mustWriteFile(t, filepath.Join(repo, "tracked"), []byte("stable\n"), 0o644)
|
||||
mustRun(t, repo, "git", "add", "tracked")
|
||||
mustRun(t, repo, "git", "commit", "-m", "stable release")
|
||||
previousStableCommit := strings.TrimSpace(mustOutput(t, repo, "git", "rev-parse", "HEAD"))
|
||||
mustRun(t, repo, "git", "tag", "-a", "v1.0.57", "-m", "v1.0.57")
|
||||
mustWriteFile(t, filepath.Join(repo, "tracked"), []byte("sealed\n"), 0o644)
|
||||
mustRun(t, repo, "git", "commit", "-am", "sealed release")
|
||||
releaseCommit := strings.TrimSpace(mustOutput(t, repo, "git", "rev-parse", "HEAD"))
|
||||
mustRun(t, repo, "git", "tag", "-a", "v1.0.58", "-m", "v1.0.58")
|
||||
releaseTagObject := strings.TrimSpace(mustOutput(t, repo, "git", "rev-parse", "refs/tags/v1.0.58"))
|
||||
|
||||
run := func(tagObject string) ([]byte, error) {
|
||||
cmd := exec.Command("sh", "-c", script)
|
||||
cmd.Dir = repo
|
||||
cmd.Env = make([]string, 0, len(os.Environ())+5)
|
||||
for _, entry := range os.Environ() {
|
||||
if strings.HasPrefix(entry, "RELEASE_VERSION=") ||
|
||||
strings.HasPrefix(entry, "RELEASE_COMMIT=") ||
|
||||
strings.HasPrefix(entry, "RELEASE_TAG_OBJECT=") ||
|
||||
strings.HasPrefix(entry, "PREVIOUS_STABLE=") ||
|
||||
strings.HasPrefix(entry, "PREVIOUS_STABLE_COMMIT=") {
|
||||
continue
|
||||
}
|
||||
cmd.Env = append(cmd.Env, entry)
|
||||
}
|
||||
cmd.Env = append(cmd.Env,
|
||||
"RELEASE_VERSION=v1.0.58",
|
||||
"RELEASE_COMMIT="+releaseCommit,
|
||||
"RELEASE_TAG_OBJECT="+tagObject,
|
||||
"PREVIOUS_STABLE=v1.0.57",
|
||||
"PREVIOUS_STABLE_COMMIT="+previousStableCommit,
|
||||
)
|
||||
return cmd.CombinedOutput()
|
||||
}
|
||||
|
||||
if output, err := run(releaseTagObject); err != nil {
|
||||
t.Fatalf("prepared compatibility ref view failed: %v\noutput:\n%s", err, output)
|
||||
}
|
||||
candidateTag := exec.Command("git", "rev-parse", "--verify", "refs/tags/v1.0.58")
|
||||
candidateTag.Dir = repo
|
||||
if _, err := candidateTag.CombinedOutput(); err == nil {
|
||||
t.Fatal("prepared compatibility ref view left the sealed candidate tag visible")
|
||||
}
|
||||
mustRun(t, repo, "git", "cat-file", "-e", releaseTagObject+"^{tag}")
|
||||
if got := strings.TrimSpace(mustOutput(t, repo, "git", "rev-parse", "refs/tags/v1.0.57^{commit}")); got != previousStableCommit {
|
||||
t.Fatalf("previous stable tag commit = %s, want %s", got, previousStableCommit)
|
||||
}
|
||||
if got := strings.TrimSpace(mustOutput(t, repo, "git", "rev-parse", "HEAD")); got != releaseCommit {
|
||||
t.Fatalf("HEAD after prepared compatibility ref view = %s, want %s", got, releaseCommit)
|
||||
}
|
||||
|
||||
mustRun(t, repo, "git", "update-ref", "refs/tags/v1.0.58", releaseTagObject)
|
||||
if output, err := run(strings.Repeat("0", 40)); err == nil {
|
||||
t.Fatalf("prepared compatibility ref view unexpectedly accepted a mismatched tag object\noutput:\n%s", output)
|
||||
}
|
||||
if got := strings.TrimSpace(mustOutput(t, repo, "git", "rev-parse", "refs/tags/v1.0.58")); got != releaseTagObject {
|
||||
t.Fatalf("mismatched tag object removed or changed the local sealed tag: got %s, want %s", got, releaseTagObject)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseFingerprintRefPatternsMatchAllAllocatedTags(t *testing.T) {
|
||||
t.Parallel()
|
||||
repo := t.TempDir()
|
||||
|
||||
Reference in New Issue
Block a user