/
supersede.go
123 lines (108 loc) · 3.01 KB
/
supersede.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package main
import (
"encoding/json"
"fmt"
"path/filepath"
"github.com/taskcluster/httpbackoff/v3"
"github.com/taskcluster/taskcluster/v25/internal/scopes"
"github.com/taskcluster/taskcluster/v25/workers/generic-worker/fileutil"
)
var (
supersededByPath = filepath.Join("generic-worker", "superseded-by.json")
supersededByName = "public/superseded-by.json"
)
type SupersedeFeature struct {
}
type SupersedesServiceResponse struct {
TaskIDs []string `json:"supersedes"`
}
func (feature *SupersedeFeature) Name() string {
return "Supersede"
}
func (feature *SupersedeFeature) Initialise() error {
return nil
}
func (feature *SupersedeFeature) PersistState() error {
return nil
}
// Supersede is always enabled
func (feature *SupersedeFeature) IsEnabled(task *TaskRun) bool {
return true
}
type SupersedeTask struct {
task *TaskRun
}
func (l *SupersedeTask) ReservedArtifacts() []string {
return []string{
supersededByName,
}
}
func (feature *SupersedeFeature) NewTaskFeature(task *TaskRun) TaskFeature {
return &SupersedeTask{
task: task,
}
}
func (l *SupersedeTask) RequiredScopes() scopes.Required {
// let's not require any scopes, as I see no reason to control access to this feature
return scopes.Required{}
}
func (l *SupersedeTask) Start() *CommandExecutionError {
supersederURL := l.task.Payload.SupersederURL
if supersederURL == "" {
return nil
}
resp, _, err := httpbackoff.Get(supersederURL)
if err != nil {
// if problem with superseder service, let's run all tasks, and not resolve them all as exception
l.task.Warnf("[supersede] Problem accessing supersederUrl: %v", err)
l.task.Warn("[supersede] Not able to see if this task has been superseded!")
return nil
}
decoder := json.NewDecoder(resp.Body)
var supersedes SupersedesServiceResponse
err = decoder.Decode(&supersedes)
if err != nil {
// if problem with superseder service, let's run all tasks, and not resolve them all as exception
l.task.Warnf("[supersede] Not able to interpret response from supersederUrl %v as json list of task IDs: %v", supersederURL, err)
l.task.Warn("[supersede] Not able to see if this task has been superseded!")
return nil
}
taskIDs := supersedes.TaskIDs
if len(taskIDs) < 1 {
return nil
}
if l.task.TaskID != taskIDs[0] {
supersededByFile := filepath.Join(taskContext.TaskDir, supersededByPath)
err = fileutil.WriteToFileAsJSON(
map[string]string{
"taskId": taskIDs[0],
},
supersededByFile,
)
if err != nil {
panic(err)
}
e := l.task.uploadArtifact(
&S3Artifact{
BaseArtifact: &BaseArtifact{
Name: supersededByName,
Expires: l.task.Definition.Expires,
},
Path: supersededByPath,
ContentEncoding: "gzip",
ContentType: "application/json",
},
)
if e != nil {
panic(e)
}
return &CommandExecutionError{
TaskStatus: aborted,
Cause: fmt.Errorf("Task %v has been superseded by task %v", l.task.TaskID, taskIDs[0]),
Reason: superseded,
}
}
return nil
}
func (l *SupersedeTask) Stop(*ExecutionErrors) {
}