Skip to content

Add default env for script run #5002

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 1, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,24 @@ The commands run in the directory where this application configuration file exis

![](/images/script-run.png)

# When to rollback
## Default environment values

You can use the envrionment values related to the deployment.

| Name | Description | Example |
|-|-|-|
|SR_DEPLOYMENT_ID| The deployment id | 877625fc-196a-40f9-b6a9-99decd5494a0 |
|SR_APPLICATION_ID| The application id | 8d7609e0-9ff6-4dc7-a5ac-39660768606a |
|SR_APPLICATION_NAME| The application name | example |
|SR_TRIGGERED_AT| The timestamp when the deployment is triggered | 1719571113 |
|SR_TRIGGERED_COMMIT_HASH| The commit hash that triggered the deployment | 2bf969a3dad043aaf8ae6419943255e49377da0d |
|SR_REPOSITORY_URL| The repository url configured in the piped config | [email protected]:org/repo.git, https://github.com/org/repo |
|SR_SUMMARY| The summary of the deployment | Sync with the specified pipeline because piped received a command from user via web console or pipectl
|
|SR_CONTEXT_RAW| The json encoded string of above values | {"deploymentID":"877625fc-196a-40f9-b6a9-99decd5494a0","applicationID":"8d7609e0-9ff6-4dc7-a5ac-39660768606a","applicationName":"example","triggeredAt":1719571113,"triggeredCommitHash":"2bf969a3dad043aaf8ae6419943255e49377da0d","repositoryURL":"[email protected]:org/repo.git","labels":{"env":"example","team":"product"}} |
|SR_LABEL_XXX| The label attached to the deployment. The env name depends on the label name. For example, if a deployment has the labels `env:prd` and `team:server`, `SR_LABEL_ENV` and `SR_LABEL_TEAM` are registered. | prd, server |

## Rollback

You can define the command as `onRollback` to execute when to rollback similar to `run`.
Execute the command to rollback SCRIPT_RUN to the point where the deployment was canceled or failed.
Expand Down Expand Up @@ -114,7 +131,7 @@ Then
- If 4 is canceled or fails while running, only SCRIPT_RUN of 3 will be rollbacked.
- If 6 is canceled or fails while running, only SCRIPT_RUNs 3 and 5 will be rollbacked. The order of executing is 3 -> 5.

# Note
## Note
1. You can use `SCRIPT_RUN` stage with only the application kind of `KubernetesApp`. Soon we will implement it. for other application kinds.

2. The public piped image available in PipeCD main repo (ref: [Dockerfile](https://github.com/pipe-cd/pipecd/blob/master/cmd/piped/Dockerfile)) is based on [alpine](https://hub.docker.com/_/alpine/) and only has a few UNIX command available (ref: [piped-base Dockerfile](https://github.com/pipe-cd/pipecd/blob/master/tool/piped-base/Dockerfile)). If you want to use your commands, you can:
Expand Down
14 changes: 13 additions & 1 deletion pkg/app/piped/executor/kubernetes/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"go.uber.org/zap"

"github.com/pipe-cd/pipecd/pkg/app/piped/executor"
"github.com/pipe-cd/pipecd/pkg/app/piped/executor/scriptrun"
provider "github.com/pipe-cd/pipecd/pkg/app/piped/platformprovider/kubernetes"
"github.com/pipe-cd/pipecd/pkg/model"
)
Expand Down Expand Up @@ -206,7 +207,18 @@
}
}

envs := make([]string, 0, len(env))
ci := scriptrun.NewContextInfo(e.Deployment)
ciEnv, err := ci.BuildEnv()
if err != nil {
e.LogPersister.Errorf("failed to build srcipt run context info: %w", err)
return model.StageStatus_STAGE_FAILURE
}

Check warning on line 215 in pkg/app/piped/executor/kubernetes/rollback.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/executor/kubernetes/rollback.go#L210-L215

Added lines #L210 - L215 were not covered by tests

envs := make([]string, 0, len(ciEnv)+len(env))
for key, value := range ciEnv {
envs = append(envs, key+"="+value)
}

Check warning on line 220 in pkg/app/piped/executor/kubernetes/rollback.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/executor/kubernetes/rollback.go#L217-L220

Added lines #L217 - L220 were not covered by tests

for key, value := range env {
envs = append(envs, key+"="+value)
}
Expand Down
65 changes: 65 additions & 0 deletions pkg/app/piped/executor/scriptrun/script_run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package scriptrun

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
)

func Test_ContextInfo_BuildEnv(t *testing.T) {
tests := []struct {
name string
ci *ContextInfo
want map[string]string
wantErr bool
}{
{
name: "success",
ci: &ContextInfo{
DeploymentID: "deployment-id",
ApplicationID: "application-id",
ApplicationName: "application-name",
TriggeredAt: 1234567890,
TriggeredCommitHash: "commit-hash",
RepositoryURL: "repo-url",
Labels: map[string]string{
"key1": "value1",
"key2": "value2",
},
Summary: "summary",
},
want: map[string]string{
"SR_DEPLOYMENT_ID": "deployment-id",
"SR_APPLICATION_ID": "application-id",
"SR_APPLICATION_NAME": "application-name",
"SR_TRIGGERED_AT": "1234567890",
"SR_TRIGGERED_COMMIT_HASH": "commit-hash",
"SR_REPOSITORY_URL": "repo-url",
"SR_SUMMARY": "summary",
"SR_LABELS_KEY1": "value1",
"SR_LABELS_KEY2": "value2",
},
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.ci.BuildEnv()
assert.Equal(t, tt.wantErr, err != nil)

for k, v := range got {
if k == "SR_CONTEXT_RAW" {
continue
}
assert.Equal(t, tt.want[k], v)
}

var gotRaw ContextInfo
err = json.Unmarshal([]byte(got["SR_CONTEXT_RAW"]), &gotRaw)
assert.Nil(t, err)
assert.Equal(t, tt.ci, &gotRaw)
})
}
}
67 changes: 66 additions & 1 deletion pkg/app/piped/executor/scriptrun/scriptrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
package scriptrun

import (
"encoding/json"
"os"
"os/exec"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -99,7 +101,18 @@
}
}

envs := make([]string, 0, len(opts.Env))
ci := NewContextInfo(e.Deployment)
ciEnv, err := ci.BuildEnv()
if err != nil {
e.LogPersister.Errorf("failed to build srcipt run context info: %w", err)
return model.StageStatus_STAGE_FAILURE
}

Check warning on line 109 in pkg/app/piped/executor/scriptrun/scriptrun.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/executor/scriptrun/scriptrun.go#L104-L109

Added lines #L104 - L109 were not covered by tests

envs := make([]string, 0, len(ciEnv)+len(opts.Env))
for key, value := range ciEnv {
envs = append(envs, key+"="+value)
}

Check warning on line 114 in pkg/app/piped/executor/scriptrun/scriptrun.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/executor/scriptrun/scriptrun.go#L111-L114

Added lines #L111 - L114 were not covered by tests

for key, value := range opts.Env {
envs = append(envs, key+"="+value)
}
Expand All @@ -116,6 +129,58 @@
return model.StageStatus_STAGE_SUCCESS
}

// ContextInfo is the information that will be passed to the script run stage.
type ContextInfo struct {
DeploymentID string `json:"deploymentID,omitempty"`
ApplicationID string `json:"applicationID,omitempty"`
ApplicationName string `json:"applicationName,omitempty"`
TriggeredAt int64 `json:"triggeredAt,omitempty"`
TriggeredCommitHash string `json:"triggeredCommitHash,omitempty"`
RepositoryURL string `json:"repositoryURL,omitempty"`
Summary string `json:"summary,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}

// NewContextInfo creates a new ContextInfo from the given deployment.
func NewContextInfo(d *model.Deployment) *ContextInfo {
return &ContextInfo{
DeploymentID: d.Id,
ApplicationID: d.ApplicationId,
ApplicationName: d.ApplicationName,
TriggeredAt: d.Trigger.Timestamp,
TriggeredCommitHash: d.Trigger.Commit.Hash,
RepositoryURL: d.GitPath.Repo.Remote,
Summary: d.Summary,
Labels: d.Labels,
}

Check warning on line 155 in pkg/app/piped/executor/scriptrun/scriptrun.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/executor/scriptrun/scriptrun.go#L145-L155

Added lines #L145 - L155 were not covered by tests
}

// BuildEnv builds the environment variables from the context info.
func (src *ContextInfo) BuildEnv() (map[string]string, error) {
b, err := json.Marshal(src)
if err != nil {
return nil, err
}

Check warning on line 163 in pkg/app/piped/executor/scriptrun/scriptrun.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/executor/scriptrun/scriptrun.go#L162-L163

Added lines #L162 - L163 were not covered by tests

envs := map[string]string{
"SR_DEPLOYMENT_ID": src.DeploymentID,
"SR_APPLICATION_ID": src.ApplicationID,
"SR_APPLICATION_NAME": src.ApplicationName,
"SR_TRIGGERED_AT": strconv.FormatInt(src.TriggeredAt, 10),
"SR_TRIGGERED_COMMIT_HASH": src.TriggeredCommitHash,
"SR_REPOSITORY_URL": src.RepositoryURL,
"SR_SUMMARY": src.Summary,
"SR_CONTEXT_RAW": string(b), // Add the raw json string as an environment variable.
}

for k, v := range src.Labels {
eName := "SR_LABELS_" + strings.ToUpper(k)
envs[eName] = v
}

return envs, nil
}

type RollbackExecutor struct {
executor.Input
}
Expand Down
Loading