Skip to content

Commit

Permalink
feat: add git-based promotion directives (#2537)
Browse files Browse the repository at this point in the history
Signed-off-by: Kent Rancourt <[email protected]>
Signed-off-by: Hidde Beydals <[email protected]>
Co-authored-by: Hidde Beydals <[email protected]>
  • Loading branch information
krancour and hiddeco authored Sep 17, 2024
1 parent f441c89 commit 5c88c84
Show file tree
Hide file tree
Showing 31 changed files with 2,733 additions and 494 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ jobs:
container:
image: golang:1.23.1-bookworm
steps:
# Install Git from "trixie" repository to get a more recent version than
# the one available in "stable". This can be removed once the version in
# "stable" is updated to >= 2.42.0 (which supports `--orphan` for `git
# worktree add`).
- name: Update Git to >= 2.42
run: |
echo "deb http://deb.debian.org/debian trixie main" > /etc/apt/sources.list.d/trixie.list
apt update && apt install -y -t trixie git
- name: Checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
Expand Down
11 changes: 10 additions & 1 deletion Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ RUN apt update && apt install -y ca-certificates curl gnupg unzip \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update && apt-get install nodejs -y \
&& npm install --global pnpm@${PNPM_VERSION}
&& npm install --global pnpm@${PNPM_VERSION} \
# Install Git from "trixie" repository to get a more recent version than
# the one available in "stable". This can be removed once the version in
# "stable" is updated to >= 2.42.0 (which supports `--orphan` for `git
# worktree add`).
&& echo "deb http://deb.debian.org/debian trixie main" > /etc/apt/sources.list.d/trixie.list \
&& apt update \
&& apt install -y -t trixie git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

ARG USER_ID=1000
ARG GROUP_ID=1000
Expand Down
4 changes: 4 additions & 0 deletions hack/codegen/directive-configs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ printf "${generated_code_warning}$(cat ${out_file})" > ${out_file}
# on Linux. So we use -i.bak, which works on both.
sed -i.bak 's/\*bool/bool/g' ${out_file}
sed -i.bak 's/\*string/string/g' ${out_file}
# As of right now, this transformation is ok, but we can revisit it if we ever
# need nullable numbers or non-int numbers.
sed -i.bak 's/\*float64/int64/g' ${out_file}

rm ${out_file}.bak

gofmt -w ${out_file}
3 changes: 2 additions & 1 deletion internal/argocd/revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ func GetDesiredRevision(
commit, err := freight.FindCommit(
ctx,
cl,
stage,
stage.Namespace,
stage.Spec.RequestedFreight,
desiredOrigin,
frght,
app.Spec.Source.RepoURL,
Expand Down
16 changes: 10 additions & 6 deletions internal/controller/freight/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import (
func FindCommit(
ctx context.Context,
cl client.Client,
stage *kargoapi.Stage,
project string,
freightReqs []kargoapi.FreightRequest,
desiredOrigin *kargoapi.FreightOrigin,
freight []kargoapi.FreightReference,
repoURL string,
Expand All @@ -25,23 +26,26 @@ func FindCommit(
// for, great. If there's more than one, there's ambiguity and we need to
// return an error.
if desiredOrigin == nil {
for i := range stage.Spec.RequestedFreight {
requestedFreight := stage.Spec.RequestedFreight[i]
for i := range freightReqs {
requestedFreight := freightReqs[i]
warehouse, err := kargoapi.GetWarehouse(
ctx,
cl,
types.NamespacedName{
Name: requestedFreight.Origin.Name,
Namespace: stage.Namespace,
Namespace: project,
},
)
if err != nil {
return nil, err
return nil, fmt.Errorf(
"error getting Warehouse %q in namespace %q: %w",
requestedFreight.Origin.Name, project, err,
)
}
if warehouse == nil {
return nil, fmt.Errorf(
"Warehouse %q not found in namespace %q",
requestedFreight.Origin.Name, stage.Namespace,
requestedFreight.Origin.Name, project,
)
}
for _, sub := range warehouse.Spec.Subscriptions {
Expand Down
15 changes: 9 additions & 6 deletions internal/controller/freight/finder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ func TestFindCommit(t *testing.T) {
testCases := []struct {
name string
client func() client.Client
Stage *kargoapi.Stage
stage *kargoapi.Stage
desiredOrigin *kargoapi.FreightOrigin
freight []kargoapi.FreightReference
assertions func(*testing.T, *kargoapi.GitCommit, error)
}{
{
name: "desired origin specified, but commit not found",
stage: &kargoapi.Stage{},
desiredOrigin: &testOrigin1,
freight: []kargoapi.FreightReference{
{
Expand All @@ -65,6 +66,7 @@ func TestFindCommit(t *testing.T) {
},
{
name: "desired origin specified and commit is found",
stage: &kargoapi.Stage{},
desiredOrigin: &testOrigin1,
freight: []kargoapi.FreightReference{
{
Expand All @@ -88,7 +90,7 @@ func TestFindCommit(t *testing.T) {
// desired origin
return fake.NewClientBuilder().WithScheme(scheme).Build()
},
Stage: &kargoapi.Stage{
stage: &kargoapi.Stage{
Spec: kargoapi.StageSpec{
RequestedFreight: []kargoapi.FreightRequest{{Origin: testOrigin1}},
},
Expand Down Expand Up @@ -118,7 +120,7 @@ func TestFindCommit(t *testing.T) {
},
).Build()
},
Stage: &kargoapi.Stage{
stage: &kargoapi.Stage{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
},
Expand Down Expand Up @@ -163,7 +165,7 @@ func TestFindCommit(t *testing.T) {
},
).Build()
},
Stage: &kargoapi.Stage{
stage: &kargoapi.Stage{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
},
Expand Down Expand Up @@ -203,7 +205,7 @@ func TestFindCommit(t *testing.T) {
},
).Build()
},
Stage: &kargoapi.Stage{
stage: &kargoapi.Stage{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
},
Expand Down Expand Up @@ -238,7 +240,8 @@ func TestFindCommit(t *testing.T) {
commit, err := FindCommit(
context.Background(),
cl,
testCase.Stage,
testCase.stage.Namespace,
testCase.stage.Spec.RequestedFreight,
testCase.desiredOrigin,
testCase.freight,
testRepoURL,
Expand Down
3 changes: 2 additions & 1 deletion internal/controller/promotion/argocd.go
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,8 @@ func (a *argoCDMechanism) applyArgoCDSourceUpdate(
commit, err := freight.FindCommit(
ctx,
a.kargoClient,
stage,
stage.Namespace,
stage.Spec.RequestedFreight,
desiredOrigin,
newFreight,
update.RepoURL,
Expand Down
10 changes: 9 additions & 1 deletion internal/controller/promotion/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,15 @@ func getReadRef(
newFreight []kargoapi.FreightReference,
) (string, *kargoapi.GitCommit, error) {
desiredOrigin := freight.GetDesiredOrigin(stage, update)
commit, err := freight.FindCommit(ctx, cli, stage, desiredOrigin, newFreight, update.RepoURL)
commit, err := freight.FindCommit(
ctx,
cli,
stage.Namespace,
stage.Spec.RequestedFreight,
desiredOrigin,
newFreight,
update.RepoURL,
)
if err != nil {
return "", nil,
fmt.Errorf("error finding commit from repo %q: %w", update.RepoURL, err)
Expand Down
5 changes: 2 additions & 3 deletions internal/directives/copy_directive.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ func (d *copyDirective) Name() string {
}

func (d *copyDirective) Run(ctx context.Context, stepCtx *StepContext) (Result, error) {
failure := Result{Status: StatusFailure}
// Validate the configuration against the JSON Schema.
if err := validate(d.schemaLoader, gojsonschema.NewGoLoader(stepCtx.Config), d.Name()); err != nil {
return failure, err
return Result{Status: StatusFailure}, err
}

// Convert the configuration into a typed object.
cfg, err := configToStruct[CopyConfig](stepCtx.Config)
if err != nil {
return failure, fmt.Errorf("could not convert config into %s config: %w", d.Name(), err)
return Result{Status: StatusFailure}, fmt.Errorf("could not convert config into %s config: %w", d.Name(), err)
}

return d.run(ctx, stepCtx, cfg)
Expand Down
10 changes: 8 additions & 2 deletions internal/directives/directive.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ type StepContext struct {
Config Config
// Project is the Project that the Promotion is associated with.
Project string
// Stage is the Stage that the Promotion is targeting.
Stage string
// FreightRequests is the list of Freight from various origins that is
// requested by the Stage targeted by the Promotion. This information is
// sometimes useful to Steps that reference a particular artifact and, in the
Expand Down Expand Up @@ -122,10 +124,14 @@ func (c Config) DeepCopy() Config {
type Status string

const (
// StatusSuccess is the result of a successful directive execution.
StatusSuccess Status = "Success"
// StatusFailure is the result of a failed directive execution.
StatusFailure Status = "Failure"
// StatusPending is the result of a directive execution that is waiting on
// some external state (such as waiting for an open PR to be merged or
// closed).
StatusPending Status = "Pending"
// StatusSuccess is the result of a successful directive execution.
StatusSuccess Status = "Success"
)

// Result represents the outcome of a directive execution, including its status
Expand Down
Loading

0 comments on commit 5c88c84

Please sign in to comment.