Files
dokku/plugins/builder/triggers.go
Jose Diaz-Gonzalez 1308e21947 feat: migrate environment variables to plugin properties
Standardize how environment variables are migrated to properties during
install triggers and migrate all remaining DOKKU_* config vars to their
appropriate plugin properties.

Adds a reusable MigrateConfigToProperties() function in the common
package with Transform callback and ListProperty support, plus a
migrate-config-to-property subcommand for the prop binary so shell
plugins can use the same code path.

Migrated variables and their new property owners:
- DOKKU_APP_PROXY_TYPE/DOKKU_PROXY_TYPE → proxy type
- DOKKU_DISABLE_PROXY → proxy disabled
- DOKKU_PROXY_PORT → ports proxy-port
- DOKKU_PROXY_SSL_PORT → ports proxy-ssl-port
- DOKKU_APP_RESTORE → ps restore
- DOKKU_SKIP_DEPLOY → ps skip-deploy
- DOKKU_START_CMD → ps start-cmd
- DOKKU_DOCKERFILE_START_CMD → ps dockerfile-start-cmd
- DOKKU_DISABLE_APP_AUTOCREATION → apps disable-autocreation
- DOKKU_APP_SHELL → scheduler shell
- DOKKU_SKIP_CLEANUP → builder skip-cleanup
- DOKKU_CHECKS_DISABLED → checks disabled
- DOKKU_CHECKS_SKIPPED → checks skipped
- DOKKU_CHECKS_WAIT → checks wait
- DOKKU_CHECKS_TIMEOUT → checks timeout
- DOKKU_CHECKS_ATTEMPTS → checks attempts
- DOKKU_DEFAULT_CHECKS_WAIT → checks default-wait
- DOKKU_SKIP_ALL_CHECKS → checks disabled (legacy)
- DOKKU_SKIP_DEFAULT_CHECKS → checks skipped (legacy)

Also refactors existing bespoke migration loops in scheduler, ports, ps,
builder, and nginx-vhosts plugins to use the standardized utility.

Removes DOKKU_PARALLEL_ARGUMENTS from documentation (unused in core).
Deprecates fn-migrate-config-to-property bash function.

closes #1558
2026-04-25 05:11:07 -04:00

193 lines
5.2 KiB
Go

package builder
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/dokku/dokku/plugins/common"
)
// TriggerBuilderDetect outputs a manually selected builder for the app
func TriggerBuilderDetect(appName string) error {
if builder := common.PropertyGet("builder", appName, "selected"); builder != "" {
fmt.Println(builder)
return nil
}
if builder := common.PropertyGet("builder", "--global", "selected"); builder != "" {
fmt.Println(builder)
return nil
}
return nil
}
// TriggerBuilderGetProperty writes the builder key to stdout for a given app container
func TriggerBuilderGetProperty(appName string, key string) error {
if _, ok := DefaultProperties[key]; !ok {
return errors.New("Invalid builder property specified")
}
fmt.Println(common.PropertyGet("builder", appName, key))
return nil
}
// TriggerBuilderSetProperty writes the builder key to stdout for a given app container
func TriggerBuilderSetProperty(appName string, key string, value string) error {
if _, ok := DefaultProperties[key]; !ok {
return errors.New("Invalid builder property specified")
}
return common.PropertyWrite("builder", appName, key, value)
}
// TriggerBuilderImageIsCNB prints true if an image is cnb based, false otherwise
func TriggerBuilderImageIsCNB(appName string, image string) error {
if common.IsImageCnbBased(image) {
fmt.Println("true")
} else {
fmt.Println("false")
}
return nil
}
// TriggerBuilderImageIsHerokuish prints true if an image is herokuish based, false otherwise
func TriggerBuilderImageIsHerokuish(appName string, image string) error {
if common.IsImageHerokuishBased(image, appName) {
fmt.Println("true")
} else {
fmt.Println("false")
}
return nil
}
// TriggerCorePostExtract moves a configured build-dir to be in the app root dir
func TriggerCorePostExtract(appName string, sourceWorkDir string) error {
buildDir := strings.Trim(reportComputedBuildDir(appName), "/")
if buildDir == "" {
return nil
}
newSourceWorkDir := filepath.Join(sourceWorkDir, buildDir)
if !common.DirectoryExists(newSourceWorkDir) {
return fmt.Errorf("Specified build-dir not found in sourcecode working directory: %v", buildDir)
}
tmpWorkDir, err := os.MkdirTemp(os.TempDir(), fmt.Sprintf("dokku-%s-%s", common.MustGetEnv("DOKKU_PID"), "CorePostExtract"))
if err != nil {
return fmt.Errorf("Unable to create temporary working directory: %v", err.Error())
}
if err := removeAllContents(tmpWorkDir); err != nil {
return fmt.Errorf("Unable to clear out temporary working directory for rewrite: %v", err.Error())
}
if err := common.Copy(newSourceWorkDir, tmpWorkDir); err != nil {
return fmt.Errorf("Unable to move build-dir to temporary working directory: %v", err.Error())
}
if err := removeAllContents(sourceWorkDir); err != nil {
return fmt.Errorf("Unable to clear out sourcecode working directory for rewrite: %v", err.Error())
}
if err := common.Copy(tmpWorkDir, sourceWorkDir); err != nil {
return fmt.Errorf("Unable to move build-dir to sourcecode working directory: %v", err.Error())
}
return nil
}
// TriggerInstall runs the install step for the builder plugin
func TriggerInstall() error {
if err := common.PropertySetup("builder"); err != nil {
return fmt.Errorf("Unable to install the builder plugin: %s", err.Error())
}
if err := common.MigrateConfigToProperties("builder", []common.MigrateConfigEntry{
{
ConfigVar: "DOKKU_APP_TYPE",
Property: "detected",
},
{
ConfigVar: "DOKKU_SKIP_CLEANUP",
GlobalConfigVar: "DOKKU_SKIP_CLEANUP",
Property: "skip-cleanup",
},
}); err != nil {
return err
}
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
Trigger: "install-builder-prune",
})
return err
}
// TriggerPostAppCloneSetup creates new builder files
func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error {
err := common.PropertyClone("builder", oldAppName, newAppName)
if err != nil {
return err
}
return nil
}
// TriggerPostAppRenameSetup renames builder files
func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
if err := common.PropertyClone("builder", oldAppName, newAppName); err != nil {
return err
}
if err := common.PropertyDestroy("builder", oldAppName); err != nil {
return err
}
return nil
}
// TriggerPostDelete destroys the builder property for a given app container
func TriggerPostDelete(appName string) error {
if err := common.PropertyDestroy("builder", appName); err != nil {
return err
}
imagesByAppLabel, err := common.DockerFilterImages([]string{
fmt.Sprintf("label=com.dokku.app-name=%s", appName),
})
if err != nil {
common.LogWarn(err.Error())
}
imageRepo := common.GetAppImageRepo(appName)
imagesByRepo, err := listImagesByImageRepo(imageRepo)
if err != nil {
common.LogWarn(err.Error())
}
images := append(imagesByAppLabel, imagesByRepo...)
common.RemoveImages(images)
return nil
}
// TriggerPostReleaseBuilder deletes unused build images
func TriggerPostReleaseBuilder(builderType string, appName string) error {
images, _ := common.DockerFilterImages([]string{
"label=com.dokku.image-stage=build",
fmt.Sprintf("label=com.dokku.app-name=%s", appName),
})
if err := common.RemoveImages(images); err != nil {
common.LogWarn(err.Error())
}
return nil
}