...

Source file src/edge-infra.dev/pkg/f8n/devinfra/job/job.go

Documentation: edge-infra.dev/pkg/f8n/devinfra/job

     1  package job
     2  
     3  import (
     4  	"encoding/json"
     5  	goerrors "errors"
     6  	"fmt"
     7  
     8  	"edge-infra.dev/pkg/lib/build/semver"
     9  )
    10  
    11  var (
    12  	ErrIncomplete    = goerrors.New("incomplete data pprovided to struct")
    13  	ErrSemVerInvalid = goerrors.New("version is not valid")
    14  )
    15  
    16  type StartedOption func(*Started)
    17  
    18  type Started struct {
    19  	timestamp int64
    20  	// machine job was ran on, can be used to identify failures clustered around
    21  	// one or more faulty nodes, or correlating failures with nodes under load, etc
    22  	machine string
    23  	// Optional PR number
    24  	pull   string
    25  	commit string
    26  	repo   string
    27  	// Complete SemVer, should be unique per commit to master.  Either generated
    28  	// by the job, or used to download artifacts produced by another job (e.g., periodic
    29  	// e2e test)
    30  	version string
    31  }
    32  
    33  type StartedJSON struct {
    34  	Timestamp int64  `json:"timestamp,omitempty"`
    35  	Machine   string `json:"machine,omitempty"`
    36  	Pull      string `json:"pull,omitempty"`
    37  	Commit    string `json:"commit,omitempty"`
    38  	Repo      string `json:"repo,omitempty"`
    39  	Version   string `json:"version,omitempty"`
    40  }
    41  
    42  type FinishedOption func(*Finished)
    43  
    44  type Finished struct {
    45  	// empty value indicates incomplete job
    46  	timestamp int64
    47  	passed    bool
    48  	// TestGrid uses map[string]interface{} here, I think we can likely get away
    49  	// with just strings
    50  	metadata map[string]string
    51  }
    52  
    53  type FinishedJSON struct {
    54  	Timestamp int64             `json:"timestamp,omitempty"`
    55  	Passed    bool              `json:"passed,omitempty"`
    56  	Metadata  map[string]string `json:"metadata,omitempty"`
    57  }
    58  
    59  func NewStarted(opts ...StartedOption) (*Started, error) {
    60  	s := &Started{}
    61  	for _, opt := range opts {
    62  		opt(s)
    63  	}
    64  
    65  	// check that all the mandatory data exists
    66  	if s.commit == "" || s.machine == "" || s.repo == "" || s.timestamp == 0 ||
    67  		s.version == "" {
    68  		return &Started{}, fmt.Errorf("%w", ErrIncomplete)
    69  	}
    70  
    71  	// check that the semver is valid
    72  	if err := semver.IsValidSemver(s.version); err != nil {
    73  		return &Started{}, fmt.Errorf("%s %w", s.version, ErrSemVerInvalid)
    74  	}
    75  
    76  	return s, nil
    77  }
    78  
    79  func (s *Started) MarshalJSON() ([]byte, error) {
    80  	return json.Marshal(&StartedJSON{
    81  		Timestamp: s.timestamp,
    82  		Machine:   s.machine,
    83  		Pull:      s.pull,
    84  		Commit:    s.commit,
    85  		Repo:      s.repo,
    86  		Version:   s.version,
    87  	})
    88  }
    89  
    90  func (s *Started) ToJSON() ([]byte, error) {
    91  	startedjson, err := json.Marshal(s)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  	return startedjson, nil
    96  }
    97  
    98  func WithCommit(commit string) StartedOption {
    99  	return func(o *Started) {
   100  		o.commit = commit
   101  	}
   102  }
   103  
   104  func WithTimestamp(timestamp int64) StartedOption {
   105  	return func(o *Started) {
   106  		o.timestamp = timestamp
   107  	}
   108  }
   109  
   110  func WithMachine(machine string) StartedOption {
   111  	return func(o *Started) {
   112  		o.machine = machine
   113  	}
   114  }
   115  
   116  func WithPull(pull string) StartedOption {
   117  	return func(o *Started) {
   118  		o.pull = pull
   119  	}
   120  }
   121  
   122  func WithRepo(repo string) StartedOption {
   123  	return func(o *Started) {
   124  		o.repo = repo
   125  	}
   126  }
   127  
   128  func WithVersion(version string) StartedOption {
   129  	return func(o *Started) {
   130  		o.version = version
   131  	}
   132  }
   133  
   134  func NewFinished(opts ...FinishedOption) (*Finished, error) {
   135  	f := &Finished{}
   136  	for _, opt := range opts {
   137  		opt(f)
   138  	}
   139  
   140  	// check that all the mandatory data exists
   141  	if f.timestamp == 0 {
   142  		return &Finished{}, fmt.Errorf("%w", ErrIncomplete)
   143  	}
   144  
   145  	return f, nil
   146  }
   147  
   148  func (f *Finished) ToJSON() ([]byte, error) {
   149  	jsonfile, err := json.Marshal(f)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	return jsonfile, nil
   154  }
   155  
   156  func (f *Finished) MarshalJSON() ([]byte, error) {
   157  	return json.Marshal(&FinishedJSON{
   158  		Timestamp: f.timestamp,
   159  		Passed:    f.passed,
   160  		Metadata:  f.metadata,
   161  	})
   162  }
   163  
   164  func WithFinishedTimestamp(timestamp int64) FinishedOption {
   165  	return func(o *Finished) {
   166  		o.timestamp = timestamp
   167  	}
   168  }
   169  
   170  func WithPassed(passed bool) FinishedOption {
   171  	return func(f *Finished) {
   172  		f.passed = passed
   173  	}
   174  }
   175  
   176  func WithMetadata(metadata map[string]string) FinishedOption {
   177  	return func(f *Finished) {
   178  		f.metadata = metadata
   179  	}
   180  }
   181  

View as plain text