Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/content/developers/release-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ This approval only applies to fork PRs from a contributor without push access

When testing this on `ddev-test/ddev`, do the same steps there first, and confirm `vars.DOCKER_ORG` on that repository points at the DockerHub org used for testing.

That org is not the one `versionconstants.go` names, so a binary built from `ddev-test/ddev` asks for `ddev/ddev-webserver:vX.Y.Z` while its images were published to `ddevhq`. Set `DDEV_DOCKER_ORG` to pull them from where they actually landed:

```bash
DDEV_DOCKER_ORG=ddevhq ddev start
```

It replaces the org on the web, db, router, ssh-agent, and xhgui images, leaving upstream images like `postgres` alone, and `ddev version` shows what it resolved to. Unset, it changes nothing.

Since a job referencing an environment that doesn't exist yet gets auto-created with no protection rules (silently *not* gating), verify the environment actually has a `required_reviewers` rule before relying on it, e.g. `gh api repos/<owner>/<repo>/environments/image-push`.

## Pushing Docker Images with the GitHub Actions Workflow
Expand Down
31 changes: 26 additions & 5 deletions pkg/docker/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package docker

import (
"fmt"
"os"
"regexp"
"strings"

"github.com/ddev/ddev/pkg/globalconfig"
"github.com/ddev/ddev/pkg/nodeps"
Expand All @@ -14,6 +16,25 @@ import (
// which of its image generations a pinned webimage/dbimage came from.
const DdevImageTagLabel = "com.ddev.image-tag"

// dockerOrgEnvVar overrides the organization the repositories in
// versionconstants.go live under. A ddev-test/ddev build publishes its images
// to `ddevhq` rather than `ddev`, so without this its own release cannot be
// pull-tested. Unset, which is every normal build, nothing changes.
// See ddev/ddev#8753.
const dockerOrgEnvVar = "DDEV_DOCKER_ORG"

// imageRepo returns an image reference with its organization replaced by
// dockerOrgEnvVar, when that is set. A reference with no organization (the
// upstream `postgres`) has nothing to replace and is returned unchanged.
func imageRepo(image string) string {
org := strings.Trim(strings.TrimSpace(os.Getenv(dockerOrgEnvVar)), "/")
i := strings.LastIndex(image, "/")
if org == "" || i < 0 {
return image
}
return org + image[i:]
}

// releaseTagPattern matches vX.Y.Z, or a prerelease like v1.25.4-rc1. Naming
// the kinds keeps `git describe`'s v1.25.4-15-gabcdef1 out. Also in
// release-prep.sh and release-marker.sh.
Expand All @@ -33,7 +54,7 @@ func resolveImageTag(tag, branch string) string {

// GetWebImage returns the correctly formatted web image:tag reference
func GetWebImage() string {
fullWebImg := versionconstants.WebImg
fullWebImg := imageRepo(versionconstants.WebImg)
if globalconfig.DdevGlobalConfig.UseHardenedImages {
fullWebImg = fullWebImg + "-prod"
}
Expand All @@ -57,21 +78,21 @@ func GetDBImage(dbType string, dbVersion string) string {
case nodeps.MariaDB:
fallthrough
default:
return fmt.Sprintf("%s-%s-%s:%s", versionconstants.DBImg, dbType, v, resolveImageTag(versionconstants.BaseDBTag, versionconstants.BaseDBTagBranch))
return fmt.Sprintf("%s-%s-%s:%s", imageRepo(versionconstants.DBImg), dbType, v, resolveImageTag(versionconstants.BaseDBTag, versionconstants.BaseDBTagBranch))
}
}

// GetSSHAuthImage returns the correctly formatted sshauth image:tag reference
func GetSSHAuthImage() string {
return fmt.Sprintf("%s:%s", versionconstants.SSHAuthImage, resolveImageTag(versionconstants.SSHAuthTag, versionconstants.SSHAuthTagBranch))
return fmt.Sprintf("%s:%s", imageRepo(versionconstants.SSHAuthImage), resolveImageTag(versionconstants.SSHAuthTag, versionconstants.SSHAuthTagBranch))
}

// GetRouterImage returns the router image:tag reference
func GetRouterImage() string {
return fmt.Sprintf("%s:%s", versionconstants.TraefikRouterImage, resolveImageTag(versionconstants.TraefikRouterTag, versionconstants.TraefikRouterTagBranch))
return fmt.Sprintf("%s:%s", imageRepo(versionconstants.TraefikRouterImage), resolveImageTag(versionconstants.TraefikRouterTag, versionconstants.TraefikRouterTagBranch))
}

// GetXhguiImage returns the xhgui image:tag reference
func GetXhguiImage() string {
return fmt.Sprintf("%s:%s", versionconstants.XhguiImage, resolveImageTag(versionconstants.XhguiTag, versionconstants.XhguiTagBranch))
return fmt.Sprintf("%s:%s", imageRepo(versionconstants.XhguiImage), resolveImageTag(versionconstants.XhguiTag, versionconstants.XhguiTagBranch))
}
19 changes: 19 additions & 0 deletions pkg/docker/images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package docker
import (
"testing"

"github.com/ddev/ddev/pkg/nodeps"
"github.com/stretchr/testify/require"
)

Expand All @@ -18,3 +19,21 @@ func TestResolveImageTag(t *testing.T) {
require.Equal(t, "c202e92108", resolveImageTag("c202e92108", "v1.25.4-dirty"))
require.Equal(t, "c202e92108", resolveImageTag("c202e92108", "v1.25.4-preview1"))
}

func TestImageRepoDockerOrg(t *testing.T) {
require.Equal(t, "ddev/ddev-webserver", imageRepo("ddev/ddev-webserver"))

t.Setenv(dockerOrgEnvVar, "ddevhq")
require.Equal(t, "ddevhq/ddev-webserver", imageRepo("ddev/ddev-webserver"))
require.Equal(t, "postgres", imageRepo("postgres"))

require.Regexp(t, `^ddevhq/ddev-webserver:`, GetWebImage())
require.Regexp(t, `^ddevhq/ddev-dbserver-mariadb-11\.8:`, GetDBImage(nodeps.MariaDB, nodeps.MariaDB118))
require.Regexp(t, `^ddevhq/ddev-ssh-agent:`, GetSSHAuthImage())
require.Regexp(t, `^ddevhq/ddev-traefik-router:`, GetRouterImage())
require.Regexp(t, `^ddevhq/ddev-xhgui:`, GetXhguiImage())
require.Equal(t, "postgres:17", GetDBImage(nodeps.Postgres, nodeps.Postgres17))

t.Setenv(dockerOrgEnvVar, "")
require.Equal(t, "ddev/ddev-webserver", imageRepo("ddev/ddev-webserver"))
}