mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-29 00:28:19 +00:00
fix: unnamed jobs in ui (#4137)
This commit is contained in:
@@ -164,21 +164,33 @@ var IndexTemplate = template.Must(template.New("index.html.tmpl").Parse(`
|
||||
<section>
|
||||
<p class="title-heading small"><strong>Jobs</strong></p>
|
||||
{{ if .PullToJobMapping }}
|
||||
<div class="pulls-grid">
|
||||
<div class="lock-grid">
|
||||
<div class="lock-header">
|
||||
<span>Repository</span>
|
||||
<span>Project</span>
|
||||
<span>Workspace</span>
|
||||
<span>Jobs</span>
|
||||
<span>Date/Time</span>
|
||||
<span>Step</span>
|
||||
<span>Description</span>
|
||||
</div>
|
||||
{{ range .PullToJobMapping }}
|
||||
<div class="pulls-row">
|
||||
<span class="pulls-element">{{.Pull.RepoFullName}} #{{.Pull.PullNum}}</span>
|
||||
<span class="pulls-element"><code>{{.Pull.Path}}</code></span>
|
||||
<span class="pulls-element"><code>{{.Pull.Workspace}}</code></span>
|
||||
<span class="pulls-element">{{ .Pull.RepoFullName }} #{{ .Pull.PullNum }}</span>
|
||||
<span class="pulls-element">{{ if .Pull.Path }}<code>{{ .Pull.Path }}</code>{{ end }}</span>
|
||||
<span class="pulls-element">{{ if .Pull.Workspace }}<code>{{ .Pull.Workspace }}</code>{{ end }}</span>
|
||||
<span class="pulls-element">
|
||||
{{ range .JobIDInfos }}
|
||||
<div><a href="{{ $basePath }}{{ .JobIDUrl }}" target="_blank">{{ .TimeFormatted }}</a></div>
|
||||
<div><span class="lock-datetime">{{ .TimeFormatted }}</span></div>
|
||||
{{ end }}
|
||||
</span>
|
||||
<span class="pulls-element">
|
||||
{{ range .JobIDInfos }}
|
||||
<div><a href="{{ $basePath }}{{ .JobIDUrl }}" target="_blank">{{ .JobStep }}</a></div>
|
||||
{{ end }}
|
||||
</span>
|
||||
<span class="pulls-element">
|
||||
{{ range .JobIDInfos }}
|
||||
<div>{{ .JobDescription }}</div>
|
||||
{{ end }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/runatlantis/atlantis/server/jobs"
|
||||
. "github.com/runatlantis/atlantis/testing"
|
||||
)
|
||||
|
||||
@@ -28,6 +29,21 @@ func TestIndexTemplate(t *testing.T) {
|
||||
},
|
||||
AtlantisVersion: "v0.0.0",
|
||||
CleanedBasePath: "/path",
|
||||
PullToJobMapping: []jobs.PullInfoWithJobIDs{
|
||||
{
|
||||
Pull: jobs.PullInfo{
|
||||
PullNum: 1,
|
||||
Repo: "repo",
|
||||
RepoFullName: "repo full name",
|
||||
ProjectName: "project name",
|
||||
Path: "path",
|
||||
Workspace: "workspace",
|
||||
},
|
||||
JobIDInfos: []jobs.JobIDInfo{
|
||||
{JobID: "job id", JobIDUrl: "job id url", JobDescription: "job description", Time: time.Now(), TimeFormatted: "02-01-2006 15:04:05", JobStep: "job step"},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
Ok(t, err)
|
||||
}
|
||||
|
||||
@@ -611,27 +611,39 @@ func (p ProjectPlanStatus) String() string {
|
||||
type WorkflowHookCommandContext struct {
|
||||
// BaseRepo is the repository that the pull request will be merged into.
|
||||
BaseRepo Repo
|
||||
// HeadRepo is the repository that is getting merged into the BaseRepo.
|
||||
// If the pull request branch is from the same repository then HeadRepo will
|
||||
// be the same as BaseRepo.
|
||||
HeadRepo Repo
|
||||
// Log is a logger that's been set up for this context.
|
||||
Log logging.SimpleLogging
|
||||
// Pull is the pull request we're responding to.
|
||||
Pull PullRequest
|
||||
// User is the user that triggered this command.
|
||||
User User
|
||||
// Verbose is true when the user would like verbose output.
|
||||
Verbose bool
|
||||
// The name of the command that is being executed, i.e. 'plan', 'apply' etc.
|
||||
CommandName string
|
||||
// EscapedCommentArgs are the extra arguments that were added to the atlantis
|
||||
// command, ex. atlantis plan -- -target=resource. We then escape them
|
||||
// by adding a \ before each character so that they can be used within
|
||||
// sh -c safely, i.e. sh -c "terraform plan $(touch bad)".
|
||||
EscapedCommentArgs []string
|
||||
// HeadRepo is the repository that is getting merged into the BaseRepo.
|
||||
// If the pull request branch is from the same repository then HeadRepo will
|
||||
// be the same as BaseRepo.
|
||||
HeadRepo Repo
|
||||
// HookDescription is a description of the hook that is being executed.
|
||||
HookDescription string
|
||||
// UUID for reference
|
||||
HookID string
|
||||
// The name of the command that is being executed, i.e. 'plan', 'apply' etc.
|
||||
CommandName string
|
||||
// HookStepName is the name of the step that is being executed.
|
||||
HookStepName string
|
||||
// Log is a logger that's been set up for this context.
|
||||
Log logging.SimpleLogging
|
||||
// Pull is the pull request we're responding to.
|
||||
Pull PullRequest
|
||||
// ProjectName is the name of the project set in atlantis.yaml. If there was
|
||||
// no name this will be an empty string.
|
||||
ProjectName string
|
||||
// RepoRelDir is the directory of this project relative to the repo root.
|
||||
RepoRelDir string
|
||||
// User is the user that triggered this command.
|
||||
User User
|
||||
// Verbose is true when the user would like verbose output.
|
||||
Verbose bool
|
||||
// Workspace is the Terraform workspace this project is in. It will always
|
||||
// be set.
|
||||
Workspace string
|
||||
}
|
||||
|
||||
// PlanSuccessStats holds stats for a plan.
|
||||
|
||||
@@ -104,20 +104,22 @@ func (w *DefaultPostWorkflowHooksCommandRunner) runHooks(
|
||||
) error {
|
||||
|
||||
for i, hook := range postWorkflowHooks {
|
||||
hookDescription := hook.StepDescription
|
||||
if hookDescription == "" {
|
||||
hookDescription = fmt.Sprintf("Post workflow hook #%d", i)
|
||||
ctx.HookDescription = hook.StepDescription
|
||||
if ctx.HookDescription == "" {
|
||||
ctx.HookDescription = fmt.Sprintf("Post workflow hook #%d", i)
|
||||
}
|
||||
|
||||
ctx.HookStepName = fmt.Sprintf("post %s #%d", ctx.CommandName, i)
|
||||
|
||||
ctx.Log.Debug("Processing post workflow hook '%s', Command '%s', Target commands [%s]",
|
||||
hookDescription, ctx.CommandName, hook.Commands)
|
||||
ctx.HookDescription, ctx.CommandName, hook.Commands)
|
||||
if hook.Commands != "" && !strings.Contains(hook.Commands, ctx.CommandName) {
|
||||
ctx.Log.Debug("Skipping post workflow hook '%s' as command '%s' is not in Commands [%s]",
|
||||
hookDescription, ctx.CommandName, hook.Commands)
|
||||
ctx.HookDescription, ctx.CommandName, hook.Commands)
|
||||
continue
|
||||
}
|
||||
|
||||
ctx.Log.Debug("Running post workflow hook: '%s'", hookDescription)
|
||||
ctx.Log.Debug("Running post workflow hook: '%s'", ctx.HookDescription)
|
||||
ctx.HookID = uuid.NewString()
|
||||
shell := hook.Shell
|
||||
if shell == "" {
|
||||
@@ -134,20 +136,20 @@ func (w *DefaultPostWorkflowHooksCommandRunner) runHooks(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.PendingCommitStatus, hookDescription, "", url); err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.PendingCommitStatus, ctx.HookDescription, "", url); err != nil {
|
||||
ctx.Log.Warn("unable to update post workflow hook status: %s", err)
|
||||
}
|
||||
|
||||
_, runtimeDesc, err := w.PostWorkflowHookRunner.Run(ctx, hook.RunCommand, shell, shellArgs, repoDir)
|
||||
|
||||
if err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.FailedCommitStatus, hookDescription, runtimeDesc, url); err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.FailedCommitStatus, ctx.HookDescription, runtimeDesc, url); err != nil {
|
||||
ctx.Log.Warn("unable to update post workflow hook status: %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.SuccessCommitStatus, hookDescription, runtimeDesc, url); err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePostWorkflowHook(ctx.Pull, models.SuccessCommitStatus, ctx.HookDescription, runtimeDesc, url); err != nil {
|
||||
ctx.Log.Warn("unable to update post workflow hook status: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,20 +113,22 @@ func (w *DefaultPreWorkflowHooksCommandRunner) runHooks(
|
||||
repoDir string,
|
||||
) error {
|
||||
for i, hook := range preWorkflowHooks {
|
||||
hookDescription := hook.StepDescription
|
||||
if hookDescription == "" {
|
||||
hookDescription = fmt.Sprintf("Pre workflow hook #%d", i)
|
||||
ctx.HookDescription = hook.StepDescription
|
||||
if ctx.HookDescription == "" {
|
||||
ctx.HookDescription = fmt.Sprintf("Pre workflow hook #%d", i)
|
||||
}
|
||||
|
||||
ctx.HookStepName = fmt.Sprintf("pre %s #%d", ctx.CommandName, i)
|
||||
|
||||
ctx.Log.Debug("Processing pre workflow hook '%s', Command '%s', Target commands [%s]",
|
||||
hookDescription, ctx.CommandName, hook.Commands)
|
||||
ctx.HookDescription, ctx.CommandName, hook.Commands)
|
||||
if hook.Commands != "" && !strings.Contains(hook.Commands, ctx.CommandName) {
|
||||
ctx.Log.Debug("Skipping pre workflow hook '%s' as command '%s' is not in Commands [%s]",
|
||||
hookDescription, ctx.CommandName, hook.Commands)
|
||||
ctx.HookDescription, ctx.CommandName, hook.Commands)
|
||||
continue
|
||||
}
|
||||
|
||||
ctx.Log.Debug("Running pre workflow hook: '%s'", hookDescription)
|
||||
ctx.Log.Debug("Running pre workflow hook: '%s'", ctx.HookDescription)
|
||||
ctx.HookID = uuid.NewString()
|
||||
shell := hook.Shell
|
||||
if shell == "" {
|
||||
@@ -143,7 +145,7 @@ func (w *DefaultPreWorkflowHooksCommandRunner) runHooks(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.PendingCommitStatus, hookDescription, "", url); err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.PendingCommitStatus, ctx.HookDescription, "", url); err != nil {
|
||||
ctx.Log.Warn("unable to update pre workflow hook status: %s", err)
|
||||
return err
|
||||
}
|
||||
@@ -151,13 +153,13 @@ func (w *DefaultPreWorkflowHooksCommandRunner) runHooks(
|
||||
_, runtimeDesc, err := w.PreWorkflowHookRunner.Run(ctx, hook.RunCommand, shell, shellArgs, repoDir)
|
||||
|
||||
if err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.FailedCommitStatus, hookDescription, runtimeDesc, url); err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.FailedCommitStatus, ctx.HookDescription, runtimeDesc, url); err != nil {
|
||||
ctx.Log.Warn("unable to update pre workflow hook status: %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.SuccessCommitStatus, hookDescription, runtimeDesc, url); err != nil {
|
||||
if err := w.CommitStatusUpdater.UpdatePreWorkflowHook(ctx.Pull, models.SuccessCommitStatus, ctx.HookDescription, runtimeDesc, url); err != nil {
|
||||
ctx.Log.Warn("unable to update pre workflow hook status: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -24,10 +24,12 @@ type PullInfo struct {
|
||||
}
|
||||
|
||||
type JobIDInfo struct {
|
||||
JobID string
|
||||
JobIDUrl string
|
||||
Time time.Time
|
||||
TimeFormatted string
|
||||
JobID string
|
||||
JobIDUrl string
|
||||
JobDescription string
|
||||
Time time.Time
|
||||
TimeFormatted string
|
||||
JobStep string
|
||||
}
|
||||
|
||||
type PullInfoWithJobIDs struct {
|
||||
@@ -37,7 +39,9 @@ type PullInfoWithJobIDs struct {
|
||||
|
||||
type JobInfo struct {
|
||||
PullInfo
|
||||
HeadCommit string
|
||||
HeadCommit string
|
||||
JobDescription string
|
||||
JobStep string
|
||||
}
|
||||
|
||||
type ProjectCmdOutputLine struct {
|
||||
@@ -111,19 +115,15 @@ func (p *AsyncProjectCommandOutputHandler) GetPullToJobMapping() []PullInfoWithJ
|
||||
|
||||
p.pullToJobMapping.Range(func(key, value interface{}) bool {
|
||||
pullInfo := key.(PullInfo)
|
||||
jobIDMap := value.(map[string]time.Time)
|
||||
jobIDMap := value.(map[string]JobIDInfo)
|
||||
|
||||
p := PullInfoWithJobIDs{
|
||||
Pull: pullInfo,
|
||||
JobIDInfos: make([]JobIDInfo, 0, len(jobIDMap)),
|
||||
}
|
||||
|
||||
for jobID, theTime := range jobIDMap {
|
||||
jobIDInfo := JobIDInfo{
|
||||
JobID: jobID,
|
||||
Time: theTime,
|
||||
}
|
||||
p.JobIDInfos = append(p.JobIDInfos, jobIDInfo)
|
||||
for _, JobIDInfo := range jobIDMap {
|
||||
p.JobIDInfos = append(p.JobIDInfos, JobIDInfo)
|
||||
}
|
||||
|
||||
pullToJobMappings = append(pullToJobMappings, p)
|
||||
@@ -154,6 +154,7 @@ func (p *AsyncProjectCommandOutputHandler) Send(ctx command.ProjectContext, msg
|
||||
Path: ctx.RepoRelDir,
|
||||
Workspace: ctx.Workspace,
|
||||
},
|
||||
JobStep: ctx.CommandName.String(),
|
||||
},
|
||||
Line: msg,
|
||||
OperationComplete: operationComplete,
|
||||
@@ -166,9 +167,12 @@ func (p *AsyncProjectCommandOutputHandler) SendWorkflowHook(ctx models.WorkflowH
|
||||
JobInfo: JobInfo{
|
||||
HeadCommit: ctx.Pull.HeadCommit,
|
||||
PullInfo: PullInfo{
|
||||
PullNum: ctx.Pull.Num,
|
||||
Repo: ctx.BaseRepo.Name,
|
||||
PullNum: ctx.Pull.Num,
|
||||
Repo: ctx.BaseRepo.Name,
|
||||
RepoFullName: ctx.BaseRepo.FullName,
|
||||
},
|
||||
JobDescription: ctx.HookDescription,
|
||||
JobStep: ctx.HookStepName,
|
||||
},
|
||||
Line: msg,
|
||||
OperationComplete: operationComplete,
|
||||
@@ -188,11 +192,16 @@ func (p *AsyncProjectCommandOutputHandler) Handle() {
|
||||
|
||||
// Add job to pullToJob mapping
|
||||
if _, ok := p.pullToJobMapping.Load(msg.JobInfo.PullInfo); !ok {
|
||||
p.pullToJobMapping.Store(msg.JobInfo.PullInfo, map[string]time.Time{})
|
||||
p.pullToJobMapping.Store(msg.JobInfo.PullInfo, map[string]JobIDInfo{})
|
||||
}
|
||||
value, _ := p.pullToJobMapping.Load(msg.JobInfo.PullInfo)
|
||||
jobMapping := value.(map[string]time.Time)
|
||||
jobMapping[msg.JobID] = time.Now()
|
||||
jobMapping := value.(map[string]JobIDInfo)
|
||||
jobMapping[msg.JobID] = JobIDInfo{
|
||||
JobID: msg.JobID,
|
||||
JobDescription: msg.JobInfo.JobDescription,
|
||||
Time: time.Now(),
|
||||
JobStep: msg.JobInfo.JobStep,
|
||||
}
|
||||
|
||||
// Forward new message to all receiver channels and output buffer
|
||||
p.writeLogLine(msg.JobID, msg.Line)
|
||||
@@ -289,16 +298,16 @@ func (p *AsyncProjectCommandOutputHandler) GetProjectOutputBuffer(jobID string)
|
||||
return p.projectOutputBuffers[jobID]
|
||||
}
|
||||
|
||||
func (p *AsyncProjectCommandOutputHandler) GetJobIDMapForPull(pullInfo PullInfo) map[string]time.Time {
|
||||
func (p *AsyncProjectCommandOutputHandler) GetJobIDMapForPull(pullInfo PullInfo) map[string]JobIDInfo {
|
||||
if value, ok := p.pullToJobMapping.Load(pullInfo); ok {
|
||||
return value.(map[string]time.Time)
|
||||
return value.(map[string]JobIDInfo)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *AsyncProjectCommandOutputHandler) CleanUp(pullInfo PullInfo) {
|
||||
if value, ok := p.pullToJobMapping.Load(pullInfo); ok {
|
||||
jobMapping := value.(map[string]time.Time)
|
||||
jobMapping := value.(map[string]JobIDInfo)
|
||||
for jobID := range jobMapping {
|
||||
p.projectOutputBuffersLock.Lock()
|
||||
delete(p.projectOutputBuffers, jobID)
|
||||
|
||||
@@ -256,7 +256,6 @@ tbody {
|
||||
|
||||
.lock-row {
|
||||
display: contents;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.lock-row a {
|
||||
@@ -311,7 +310,6 @@ tbody {
|
||||
|
||||
.pulls-row {
|
||||
display: contents;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.pulls-element {
|
||||
|
||||
Reference in New Issue
Block a user