Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add git-based promotion directives #2537

Merged
merged 6 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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 @@
// 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,
)

Check warning on line 43 in internal/controller/freight/finder.go

View check run for this annotation

Codecov / codecov/patch

internal/controller/freight/finder.go#L40-L43

Added lines #L40 - L43 were not covered by tests
}
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) 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

Check warning on line 39 in internal/directives/copy_directive.go

View check run for this annotation

Codecov / codecov/patch

internal/directives/copy_directive.go#L39

Added line #L39 was not covered by tests
}

// 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)

Check warning on line 45 in internal/directives/copy_directive.go

View check run for this annotation

Codecov / codecov/patch

internal/directives/copy_directive.go#L45

Added line #L45 was not covered by tests
}

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