1package models
2
3import (
4 "fmt"
5 "path"
6 "strings"
7
8 "github.com/go-git/go-git/v5/plumbing"
9 "tangled.sh/tangled.sh/core/api/tangled"
10 "tangled.sh/tangled.sh/core/workflow"
11)
12
13func nixConfStep() Step {
14 setupCmd := `echo 'extra-experimental-features = nix-command flakes' >> /etc/nix/nix.conf
15echo 'build-users-group = ' >> /etc/nix/nix.conf`
16 return Step{
17 Command: setupCmd,
18 Name: "Configure Nix",
19 }
20}
21
22// checkoutStep checks out the specified ref in the cloned repository.
23func checkoutStep(twf tangled.Pipeline_Workflow, tr tangled.Pipeline_TriggerMetadata) Step {
24 if twf.Clone.Skip {
25 return Step{}
26 }
27
28 var ref string
29 switch tr.Kind {
30 case "push":
31 ref = tr.Push.NewSha
32 case "pull_request":
33 ref = tr.PullRequest.TargetBranch
34
35 // TODO: this needs to be specified in lexicon
36 case "manual":
37 ref = tr.Repo.DefaultBranch
38 }
39
40 checkoutCmd := fmt.Sprintf("git config advice.detachedHead false; git checkout --progress --force %s", ref)
41
42 return Step{
43 Command: checkoutCmd,
44 Name: "Checkout ref " + ref,
45 }
46}
47
48// cloneOptsAsSteps processes clone options and adds corresponding steps
49// to the beginning of the workflow's step list if cloning is not skipped.
50func cloneStep(twf tangled.Pipeline_Workflow, tr tangled.Pipeline_TriggerMetadata, dev bool) Step {
51 if twf.Clone.Skip {
52 return Step{}
53 }
54
55 uri := "https://"
56 if dev {
57 uri = "http://"
58 tr.Repo.Knot = strings.ReplaceAll(tr.Repo.Knot, "localhost", "host.docker.internal")
59 }
60
61 cloneUrl := uri + path.Join(tr.Repo.Knot, tr.Repo.Did, tr.Repo.Repo)
62 cloneCmd := []string{"git", "clone", cloneUrl, "."}
63
64 // default clone depth is 1
65 cloneDepth := 1
66 if twf.Clone.Depth > 1 {
67 cloneDepth = int(twf.Clone.Depth)
68 }
69 cloneCmd = append(cloneCmd, fmt.Sprintf("--depth=%d", cloneDepth))
70
71 // select the clone branch
72 cloneBranch := ""
73 switch tr.Kind {
74 case workflow.TriggerKindManual:
75 // TODO: unimplemented
76 case workflow.TriggerKindPush:
77 ref := tr.Push.Ref
78 refName := plumbing.ReferenceName(ref)
79 cloneBranch = refName.Short()
80 case workflow.TriggerKindPullRequest:
81 cloneBranch = tr.PullRequest.SourceBranch
82 }
83
84 if cloneBranch != "" {
85 cloneCmd = append(cloneCmd, fmt.Sprintf("--branch=%s", cloneBranch))
86 }
87
88 if twf.Clone.Submodules {
89 cloneCmd = append(cloneCmd, "--recursive")
90 }
91
92 fmt.Println(strings.Join(cloneCmd, " "))
93
94 cloneStep := Step{
95 Command: strings.Join(cloneCmd, " "),
96 Name: "Clone repository into workspace",
97 }
98 return cloneStep
99}
100
101// dependencyStep processes dependencies defined in the workflow.
102// For dependencies using a custom registry (i.e. not nixpkgs), it collects
103// all packages and adds a single 'nix profile install' step to the
104// beginning of the workflow's step list.
105func dependencyStep(twf tangled.Pipeline_Workflow) *Step {
106 var customPackages []string
107
108 for _, d := range twf.Dependencies {
109 registry := d.Registry
110 packages := d.Packages
111
112 if registry == "nixpkgs" {
113 continue
114 }
115
116 // collect packages from custom registries
117 for _, pkg := range packages {
118 customPackages = append(customPackages, fmt.Sprintf("'%s#%s'", registry, pkg))
119 }
120 }
121
122 if len(customPackages) > 0 {
123 installCmd := "nix --extra-experimental-features nix-command --extra-experimental-features flakes profile install"
124 cmd := fmt.Sprintf("%s %s", installCmd, strings.Join(customPackages, " "))
125 installStep := Step{
126 Command: cmd,
127 Name: "Install custom dependencies",
128 Environment: map[string]string{
129 "NIX_NO_COLOR": "1",
130 "NIX_SHOW_DOWNLOAD_PROGRESS": "0",
131 },
132 }
133 return &installStep
134 }
135 return nil
136}