test/release/artifacts_test.go
Rama main · réplica de lectura del repositorio original.
package release_test
import (
"slices"
"strings"
"testing"
)
func TestReleaseArtifactsRunOnEveryMainPush(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
if len(workflow.On.Push.Paths) != 0 {
t.Fatalf("release artifact pushes are restricted to %v", workflow.On.Push.Paths)
}
}
func TestReleaseDetectionCanSeeDrafts(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
version := requireJob(t, workflow, "version")
if version.Permissions["contents"] != "write" {
t.Fatal("release detection cannot see draft releases")
}
}
func TestReleaseArtifactVersionContract(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
version := requireJob(t, workflow, "version")
for _, output := range []string{"version", "pending", "sha"} {
if version.Outputs[output] == "" {
t.Errorf("version job has no %s output", output)
}
}
read := requireStep(t, version, "read")
if !strings.Contains(read.Run, "scripts/release-pending.sh") {
t.Fatal("version job does not ask the release-pending checker")
}
if !strings.Contains(read.Run, "scripts/release-commit.sh") {
t.Fatal("version job builds the dispatch head instead of the release commit")
}
}
func TestReleaseArtifactBuildsAreGatedOnPendingWork(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
jobs := []string{"dist", "image", "chart", "desktop", "desktop-linux", "publish"}
for _, name := range jobs {
job := requireJob(t, workflow, name)
if !strings.Contains(job.If, "pending") {
t.Errorf("%s job is not gated on pending release work", name)
}
}
}
func TestPublishedClusterModeCanUpgradeAndRollBackEveryNight(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/nightly.yaml")
clusterMode := requireJob(t, workflow, "cluster-mode-release")
if !contains(clusterMode.Needs, "published") {
t.Fatal("the cluster-mode lifecycle check does not read the published releases")
}
if clusterMode.Permissions["packages"] != "read" {
t.Fatal("the cluster-mode lifecycle check cannot pull the published packages")
}
if !containsRun(clusterMode.Steps, "helm registry login") {
t.Fatal("the cluster-mode lifecycle check does not authenticate to the chart registry")
}
lifecycle := requireRunStep(t, clusterMode, "test-cluster-mode-release")
if lifecycle.Env["PREVIOUS"] != "${{ needs.published.outputs.previous }}" {
t.Fatalf("previous release = %q", lifecycle.Env["PREVIOUS"])
}
if lifecycle.Env["CURRENT"] != "${{ needs.published.outputs.current }}" {
t.Fatalf("current release = %q", lifecycle.Env["CURRENT"])
}
requireClusterModeFailureHandling(t, clusterMode)
published := requireJob(t, workflow, "published")
releases := requireStep(t, published, "releases")
if !strings.Contains(releases.Run, "--exclude-drafts") {
t.Fatal("the published releases step would compare against a draft")
}
for _, output := range []string{"current", "previous", "tag"} {
if published.Outputs[output] == "" {
t.Errorf("published job has no %s output", output)
}
}
report := requireJob(t, workflow, "report")
if !contains(report.Needs, "cluster-mode-release") {
t.Fatal("the nightly report does not wait for the cluster-mode lifecycle check")
}
}
func TestClusterModeBrowsersRunEveryEngine(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/e2e.yaml")
browser := requireJob(t, workflow, "cluster-mode-browser")
matrix, ok := browser.Strategy["matrix"].(map[string]any)
if !ok {
t.Fatalf("cluster-mode matrix = %#v, want a mapping", browser.Strategy["matrix"])
}
engines, ok := matrix["browser"].(string)
if !ok {
t.Fatalf("cluster-mode browsers = %#v, want the selected engine list", matrix["browser"])
}
if !strings.Contains(engines, "needs.select.outputs.browsers") {
t.Fatalf("cluster-mode browsers = %q, want the engines the tier selected", engines)
}
suite := readJSON[suiteTiers](t, "e2e/suite.json")
want := []string{"chromium", "firefox", "webkit"}
if !slices.Equal(suite.NightlyBrowsers, want) {
t.Fatalf("nightly browsers = %v, want %v", suite.NightlyBrowsers, want)
}
for _, engine := range suite.CommitBrowsers {
if !contains(want, engine) {
t.Fatalf("commit browser %q is not an engine the suite knows", engine)
}
}
failFast, ok := browser.Strategy["fail-fast"].(bool)
if !ok {
t.Fatalf("cluster-mode fail-fast = %#v, want a boolean", browser.Strategy["fail-fast"])
}
if failFast {
t.Fatal("one cluster-mode browser failure cancels the other engines")
}
if !strings.Contains(browser.If, "cluster-mode-auth") {
t.Fatal("cluster-mode browser validation is not selected with its capability group")
}
if !containsRun(browser.Steps, "test-cluster-mode-browser") {
t.Fatal("cluster-mode browser job does not run the dedicated browser target")
}
run := requireRunStep(t, browser, "test-cluster-mode-browser")
if run.Env["BROWSER"] != "${{ matrix.browser }}" {
t.Fatalf("cluster-mode browser target receives %q, want the selected engine", run.Env["BROWSER"])
}
requireClusterModeFailureHandling(t, browser)
auth := requireJob(t, workflow, "cluster-mode-auth")
requireClusterModeFailureHandling(t, auth)
}
func TestTheReleaseEndsPublished(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
dist := requireJob(t, workflow, "dist")
if !containsRun(dist.Steps, "gh release upload") {
t.Fatal("the dist job builds artifacts without uploading them to the release")
}
publish := requireJob(t, workflow, "publish")
for _, command := range []string{"just package-manifests", "just publish-asset", "gh release edit"} {
if !containsRun(publish.Steps, command) {
t.Errorf("the publish job does not run %q", command)
}
}
last := publish.Steps[len(publish.Steps)-1]
if !strings.Contains(last.Run, "--draft=false --latest") {
t.Fatalf("the release ends on %q, want the draft flipped to the latest release", last.Run)
}
}
func TestReleaseImagePublication(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
image := requireJob(t, workflow, "image")
if image.Permissions["packages"] != "write" {
t.Fatal("image job cannot publish packages")
}
push := requireStep(t, image, "push")
pushed, ok := push.With["push"].(bool)
if !ok || !pushed {
t.Fatal("image build does not push")
}
if push.With["platforms"] != "linux/amd64,linux/arm64" {
t.Fatalf("image platforms are %v", push.With["platforms"])
}
tags, ok := push.With["tags"].(string)
if !ok {
t.Fatal("image tags are not a string")
}
if !strings.Contains(tags, "needs.version.outputs.version") {
t.Fatal("image tags do not use the release version")
}
}
func TestReleaseChartPublication(t *testing.T) {
workflow := readYAML[workflowFile](t, ".github/workflows/release-artifacts.yaml")
chart := requireJob(t, workflow, "chart")
if !contains(chart.Needs, "image") {
t.Fatal("chart job does not wait for the image")
}
if chart.Permissions["packages"] != "write" {
t.Fatal("chart job cannot publish packages")
}
commands := []string{"helm package", "helm push"}
for _, command := range commands {
if !containsRun(chart.Steps, command) {
t.Errorf("chart job does not run %q", command)
}
}
publish := requireJob(t, workflow, "publish")
if !contains(publish.Needs, "chart") {
t.Fatal("publish job does not wait for the chart")
}
}
func requireRunStep(t *testing.T, job workflowJob, command string) workflowStep {
t.Helper()
for _, step := range job.Steps {
if strings.Contains(step.Run, command) {
return step
}
}
t.Fatalf("job does not run %q", command)
return workflowStep{}
}
func requireClusterModeFailureHandling(t *testing.T, job workflowJob) {
t.Helper()
diagnostics := requireRunStep(t, job, "cluster-mode-diagnostics")
if diagnostics.If != "failure()" {
t.Fatalf("cluster-mode diagnostics condition = %q, want failure()", diagnostics.If)
}
cleanup := requireRunStep(t, job, "cluster-mode-down")
if cleanup.If != "always()" {
t.Fatalf("cluster-mode cleanup condition = %q, want always()", cleanup.If)
}
}