2023-12-22 23:59:23 +00:00
|
|
|
package plugin
|
|
|
|
|
|
|
|
import (
|
2024-05-06 18:30:18 +00:00
|
|
|
"fmt"
|
2023-12-22 23:59:23 +00:00
|
|
|
"os"
|
2024-05-06 18:30:18 +00:00
|
|
|
"path/filepath"
|
2023-12-22 23:59:23 +00:00
|
|
|
"strings"
|
2023-12-23 15:12:56 +00:00
|
|
|
"time"
|
2023-12-22 23:59:23 +00:00
|
|
|
|
|
|
|
"github.com/cenkalti/backoff/v4"
|
2023-12-23 15:12:56 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
2024-05-06 18:30:18 +00:00
|
|
|
"github.com/thegeeklab/wp-plugin-go/v2/types"
|
2023-12-22 23:59:23 +00:00
|
|
|
"golang.org/x/sys/execabs"
|
|
|
|
)
|
|
|
|
|
2024-05-06 18:30:18 +00:00
|
|
|
const (
|
|
|
|
netrcFile = `machine %s
|
|
|
|
login %s
|
|
|
|
password %s
|
|
|
|
`
|
|
|
|
strictFilePerm = 0o600
|
|
|
|
)
|
|
|
|
|
2023-12-22 23:59:23 +00:00
|
|
|
// shouldRetry returns true if the command should be re-executed. Currently
|
|
|
|
// this only returns true if the remote ref does not exist.
|
|
|
|
func shouldRetry(s string) bool {
|
|
|
|
return strings.Contains(s, "find remote ref")
|
|
|
|
}
|
|
|
|
|
|
|
|
func newBackoff(maxRetries uint64) backoff.BackOff {
|
|
|
|
b := backoff.NewExponentialBackOff()
|
|
|
|
b.InitialInterval = daemonBackoffInitialInterval
|
|
|
|
b.Multiplier = daemonBackoffMultiplier
|
|
|
|
|
|
|
|
return backoff.WithMaxRetries(b, maxRetries)
|
|
|
|
}
|
|
|
|
|
2024-05-06 18:30:18 +00:00
|
|
|
func retryCmd(cmd *types.Cmd) error {
|
2023-12-23 15:12:56 +00:00
|
|
|
backoffOps := func() error {
|
|
|
|
// copy the original command
|
|
|
|
//nolint:gosec
|
2024-05-06 18:30:18 +00:00
|
|
|
retry := &types.Cmd{
|
|
|
|
Cmd: execabs.Command(cmd.Cmd.Path, cmd.Cmd.Args...),
|
|
|
|
}
|
2023-12-23 15:12:56 +00:00
|
|
|
retry.Env = cmd.Env
|
2024-05-06 18:30:18 +00:00
|
|
|
retry.Stdout = cmd.Stdout
|
|
|
|
retry.Stderr = cmd.Stderr
|
|
|
|
retry.Dir = cmd.Dir
|
2023-12-23 15:12:56 +00:00
|
|
|
|
2024-05-06 18:30:18 +00:00
|
|
|
return retry.Run()
|
2023-12-23 15:12:56 +00:00
|
|
|
}
|
|
|
|
backoffLog := func(err error, delay time.Duration) {
|
|
|
|
log.Error().Msgf("failed to find remote ref: %v: retry in %s", err, delay.Truncate(time.Second))
|
|
|
|
}
|
|
|
|
|
|
|
|
return backoff.RetryNotify(backoffOps, newBackoff(daemonBackoffMaxRetries), backoffLog)
|
|
|
|
}
|
2024-05-06 18:30:18 +00:00
|
|
|
|
|
|
|
// WriteNetrc writes the netrc file.
|
|
|
|
func WriteNetrc(path, machine, login, password string) error {
|
|
|
|
netrcPath := filepath.Join(path, ".netrc")
|
|
|
|
netrcContent := fmt.Sprintf(netrcFile, machine, login, password)
|
|
|
|
|
|
|
|
if err := os.WriteFile(netrcPath, []byte(netrcContent), strictFilePerm); err != nil {
|
|
|
|
return fmt.Errorf("failed to create .netrc file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|