...

Source file src/edge-infra.dev/pkg/f8n/warehouse/packagelock/packagelock.go

Documentation: edge-infra.dev/pkg/f8n/warehouse/packagelock

     1  package packagelock
     2  
     3  import (
     4  	_ "embed"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"sort"
     9  
    10  	"cuelang.org/go/cue"
    11  	"cuelang.org/go/cue/cuecontext"
    12  	"cuelang.org/go/encoding/gocode/gocodec"
    13  	"cuelang.org/go/encoding/yaml"
    14  
    15  	"edge-infra.dev/pkg/edge/yamlfmt"
    16  	"edge-infra.dev/pkg/lib/build/bazel"
    17  )
    18  
    19  var (
    20  	Packagelock = "packagelock"
    21  	//go:embed package-lock-rules.cue
    22  	rulesFile []byte
    23  )
    24  
    25  type Version struct {
    26  	Digest string   `json:"digest" yaml:"digest"`
    27  	Tags   []string `json:"tags,omitempty" yaml:"tags,omitempty"`
    28  }
    29  
    30  type LockPackage struct {
    31  	Name     string    `json:"name" yaml:"name"`
    32  	Versions []Version `json:"versions,omitempty" yaml:"versions,omitempty"`
    33  }
    34  
    35  type Packages []LockPackage
    36  
    37  func (p Packages) Sort() {
    38  	sort.Slice(p, func(i, j int) bool { return p[i].Name < p[j].Name })
    39  }
    40  
    41  type PackageLock struct {
    42  	Packages Packages `json:"packages" yaml:"packages"`
    43  }
    44  
    45  type Rules struct {
    46  	codec     *gocodec.Codec
    47  	ruleValue cue.Value
    48  }
    49  
    50  func NewRules() (Rules, error) {
    51  	c := cuecontext.New()
    52  	ruleValue := c.CompileBytes(rulesFile)
    53  	if ruleValue.Err() != nil {
    54  		return Rules{}, ruleValue.Err()
    55  	}
    56  
    57  	codec := gocodec.New(c, nil)
    58  
    59  	return Rules{codec: codec, ruleValue: ruleValue}, nil
    60  }
    61  
    62  func (plr Rules) ParsePackageLock(path string) (PackageLock, error) {
    63  	pl := &PackageLock{}
    64  
    65  	if bazel.IsBazelRun() {
    66  		if !filepath.IsAbs(path) {
    67  			path = filepath.Join(os.Getenv(bazel.BuildWorkspaceDir), path)
    68  		}
    69  	}
    70  
    71  	plReader, err := os.Open(path)
    72  	if err != nil {
    73  		return PackageLock{}, fmt.Errorf("failed to open file, err: %w", err)
    74  	}
    75  
    76  	plCueFile, err := yaml.Extract(path, plReader)
    77  	if err != nil {
    78  		return PackageLock{}, fmt.Errorf("failed to extract yaml, err: %w", err)
    79  	}
    80  	plReader.Close()
    81  
    82  	plCueValue, err := plr.codec.Decode(plCueFile)
    83  	if err != nil {
    84  		return PackageLock{}, err
    85  	}
    86  
    87  	err = plr.codec.Encode(plCueValue, pl)
    88  	if err != nil {
    89  		return PackageLock{}, err
    90  	}
    91  
    92  	err = plr.codec.Validate(plr.ruleValue, pl)
    93  
    94  	if err != nil {
    95  		return PackageLock{}, err
    96  	}
    97  
    98  	return *pl, nil
    99  }
   100  
   101  func (plr Rules) MarshalPackageLockYAML(pl PackageLock) ([]byte, error) {
   102  	pl.Packages.Sort()
   103  	plValue, err := plr.codec.Decode(pl)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	err = plr.codec.Validate(plr.ruleValue, plValue)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	plBytes, err := yaml.Encode(plValue)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	formatter := yamlfmt.NewByteFormatter()
   118  	formattedBytes, err := formatter.FormatBytes(plBytes)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	return formattedBytes, nil
   124  }
   125  

View as plain text