2019-01-21 19:41:49 -05:00
|
|
|
package buildpacks
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2025-10-01 00:30:09 +03:00
|
|
|
"os"
|
2019-01-21 19:41:49 -05:00
|
|
|
|
|
|
|
|
"github.com/dokku/dokku/plugins/common"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// CommandAdd implements buildpacks:add
|
2020-05-28 19:47:07 -04:00
|
|
|
func CommandAdd(appName string, buildpack string, index int) error {
|
2020-12-25 00:00:26 -05:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
2020-04-07 00:14:52 -04:00
|
|
|
|
2020-05-28 19:47:07 -04:00
|
|
|
buildpack, err := validBuildpackURL(buildpack)
|
2020-04-07 00:14:52 -04:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
2020-05-28 19:47:07 -04:00
|
|
|
return common.PropertyListAdd("buildpacks", appName, "buildpacks", buildpack, index)
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CommandClear implements buildpacks:clear
|
2020-05-28 19:47:07 -04:00
|
|
|
func CommandClear(appName string) error {
|
2020-12-25 00:00:26 -05:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
2020-05-28 19:47:07 -04:00
|
|
|
return common.PropertyDelete("buildpacks", appName, "buildpacks")
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
2025-10-01 00:30:09 +03:00
|
|
|
// CommandDetect implements buildpacks:detect
|
2025-10-16 18:33:47 +03:00
|
|
|
func CommandDetect(appName string, branch string) (err error) {
|
2025-10-01 00:30:09 +03:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-01 00:46:05 +03:00
|
|
|
workDir := common.AppRoot(appName)
|
2025-10-16 18:33:47 +03:00
|
|
|
checkedOutDir, err := checkoutBareGitRepo(workDir, branch)
|
2025-10-16 17:17:29 +03:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
defer func() {
|
|
|
|
|
if err := os.RemoveAll(checkedOutDir); err != nil {
|
|
|
|
|
common.LogWarn(fmt.Sprintf("Failed to remove temporary directory %s: %v", checkedOutDir, err))
|
|
|
|
|
}
|
|
|
|
|
}()
|
2025-10-01 00:30:09 +03:00
|
|
|
|
|
|
|
|
dockerArgs := []string{
|
|
|
|
|
"run", "--rm",
|
2025-10-17 19:14:08 +03:00
|
|
|
"-v", fmt.Sprintf("%s:/tmp/app", checkedOutDir),
|
2025-10-01 00:30:09 +03:00
|
|
|
"gliderlabs/herokuish", "/bin/herokuish", "buildpack", "detect", "/tmp/app",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result, err := common.CallExecCommand(common.ExecCommandInput{
|
|
|
|
|
Command: common.DockerBin(),
|
|
|
|
|
Args: dockerArgs,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Buildpack detection failed: %s", result.StderrContents())
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-16 17:19:22 +03:00
|
|
|
common.LogVerbose(result.StdoutContents())
|
2025-10-01 00:30:09 +03:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 19:41:49 -05:00
|
|
|
// CommandList implements buildpacks:list
|
2020-05-28 19:47:07 -04:00
|
|
|
func CommandList(appName string) (err error) {
|
2020-12-25 00:00:26 -05:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buildpacks, err := common.PropertyListGet("buildpacks", appName, "buildpacks")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
common.LogInfo1Quiet(fmt.Sprintf("%s buildpack urls", appName))
|
|
|
|
|
for _, buildpack := range buildpacks {
|
|
|
|
|
common.LogVerbose(buildpack)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CommandRemove implements buildpacks:remove
|
2020-05-28 19:47:07 -04:00
|
|
|
func CommandRemove(appName string, buildpack string, index int) (err error) {
|
2020-12-25 00:00:26 -05:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if index != 0 && buildpack != "" {
|
|
|
|
|
err = errors.New("Please choose either index or Buildpack, but not both")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if index == 0 && buildpack == "" {
|
|
|
|
|
err = errors.New("Must specify a buildpack to remove, either by index or URL")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-07 00:14:52 -04:00
|
|
|
buildpack, err = validBuildpackURL(buildpack)
|
2024-03-13 06:53:05 -04:00
|
|
|
if index == 0 && err != nil {
|
2020-04-07 00:14:52 -04:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 19:41:49 -05:00
|
|
|
var buildpacks []string
|
|
|
|
|
buildpacks, err = common.PropertyListGet("buildpacks", appName, "buildpacks")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(buildpacks) == 0 {
|
2019-01-21 19:45:31 -05:00
|
|
|
err = fmt.Errorf("No buildpacks were found, next release on %s will detect buildpack normally", appName)
|
2019-01-21 19:41:49 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if index != 0 {
|
|
|
|
|
var value string
|
|
|
|
|
value, err = common.PropertyListGetByIndex("buildpacks", appName, "buildpacks", index-1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buildpack = value
|
|
|
|
|
} else {
|
|
|
|
|
_, err = common.PropertyListGetByValue("buildpacks", appName, "buildpacks", buildpack)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
common.LogInfo1Quiet(fmt.Sprintf("Removing %s", buildpack))
|
|
|
|
|
err = common.PropertyListRemove("buildpacks", appName, "buildpacks", buildpack)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-07 04:47:18 -04:00
|
|
|
// CommandReport displays a buildpacks report for one or more apps
|
2021-02-01 22:23:05 -05:00
|
|
|
func CommandReport(appName string, format string, infoFlag string) error {
|
2019-09-07 04:47:18 -04:00
|
|
|
if len(appName) == 0 {
|
|
|
|
|
apps, err := common.DokkuApps()
|
|
|
|
|
if err != nil {
|
2025-02-02 01:37:14 -05:00
|
|
|
if errors.Is(err, common.NoAppsExist) {
|
|
|
|
|
common.LogWarn(err.Error())
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2020-02-22 06:29:14 -05:00
|
|
|
return err
|
2019-09-07 04:47:18 -04:00
|
|
|
}
|
|
|
|
|
for _, appName := range apps {
|
2021-02-01 22:23:05 -05:00
|
|
|
if err := ReportSingleApp(appName, format, infoFlag); err != nil {
|
2020-02-22 06:29:14 -05:00
|
|
|
return err
|
|
|
|
|
}
|
2019-09-07 04:47:18 -04:00
|
|
|
}
|
2020-02-22 06:29:14 -05:00
|
|
|
return nil
|
2019-09-07 04:47:18 -04:00
|
|
|
}
|
|
|
|
|
|
2021-02-01 22:23:05 -05:00
|
|
|
return ReportSingleApp(appName, format, infoFlag)
|
2019-09-07 04:47:18 -04:00
|
|
|
}
|
|
|
|
|
|
2019-01-21 19:41:49 -05:00
|
|
|
// CommandSet implements buildpacks:set
|
2020-05-28 19:47:07 -04:00
|
|
|
func CommandSet(appName string, buildpack string, index int) error {
|
2020-12-25 00:00:26 -05:00
|
|
|
if err := common.VerifyAppName(appName); err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
2020-05-28 19:47:07 -04:00
|
|
|
buildpack, err := validBuildpackURL(buildpack)
|
2020-04-07 00:14:52 -04:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if index > 0 {
|
|
|
|
|
index--
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-28 19:47:07 -04:00
|
|
|
return common.PropertyListSet("buildpacks", appName, "buildpacks", buildpack, index)
|
2019-01-21 19:41:49 -05:00
|
|
|
}
|
2021-01-17 23:20:16 -05:00
|
|
|
|
2021-01-23 18:17:40 -05:00
|
|
|
// CommandSetProperty implements buildpacks:set-property
|
|
|
|
|
func CommandSetProperty(appName string, property string, value string) error {
|
|
|
|
|
oldStack := ""
|
|
|
|
|
if property == "stack" {
|
|
|
|
|
oldStack = common.PropertyGet("buildpacks", appName, "stack")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
common.CommandPropertySet("buildpacks", appName, property, value, DefaultProperties, GlobalProperties)
|
|
|
|
|
if property == "stack" && oldStack != value {
|
2022-01-13 19:42:11 +01:00
|
|
|
if appName != "--global" {
|
2024-03-14 02:19:03 -04:00
|
|
|
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
|
|
|
|
Trigger: "post-stack-set",
|
|
|
|
|
Args: []string{appName, value},
|
|
|
|
|
StreamStdio: true,
|
|
|
|
|
})
|
|
|
|
|
return err
|
2022-01-13 19:42:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apps, err := common.DokkuApps()
|
2025-03-08 23:49:11 -05:00
|
|
|
if err != nil && !errors.Is(err, common.NoAppsExist) {
|
2022-01-13 19:42:11 +01:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
for _, app := range apps {
|
2024-03-14 02:19:03 -04:00
|
|
|
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
|
|
|
|
Trigger: "post-stack-set",
|
|
|
|
|
Args: []string{app, value},
|
|
|
|
|
StreamStdio: true,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
2022-01-13 19:42:11 +01:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-23 17:37:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
2021-01-17 23:20:16 -05:00
|
|
|
}
|