Skip to content

Commit

Permalink
Add initial structures for entity checkpoints (#4049)
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Antonio Osorio <[email protected]>
  • Loading branch information
JAORMX authored Jul 31, 2024
1 parent 0fda086 commit 9ef39af
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
82 changes: 82 additions & 0 deletions internal/entities/checkpoints/checkpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2024 Stacklok, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package checkpoints contains logic relating to checkpoint management for entities
package checkpoints

import "time"

// V1 is the version string for the v1 format.
const V1 = "v1"

// CheckpointEnvelopeV1 is the top-level structure for a checkpoint
// in the v1 format.
type CheckpointEnvelopeV1 struct {
Version string `json:"version" yaml:"version"`
Checkpoint CheckpointV1 `json:"checkpoint" yaml:"checkpoint"`
}

// CheckpointV1 is the structure for a checkpoint in the v1 format.
type CheckpointV1 struct {
// Timestamp is the time that the checkpoint was verified.
Timestamp time.Time `json:"timestamp" yaml:"timestamp"`

// CommitHash is the hash of the commit that the checkpoint is for.
CommitHash *string `json:"commitHash,omitempty" yaml:"commitHash,omitempty"`

// Branch is the branch of the commit that the checkpoint is for.
Branch *string `json:"branch,omitempty" yaml:"branch,omitempty"`

// Version is the version of the entity that the checkpoint is for.
// This may be a container image tag, a git tag, or some other version.
Version *string `json:"version,omitempty" yaml:"version,omitempty"`

// Digest is the digest of the entity that the checkpoint is for.
// This may be a container image digest, or some other digest.
Digest *string `json:"digest,omitempty" yaml:"digest,omitempty"`
}

// NewCheckpointV1 creates a new CheckpointV1 with the given timestamp.
func NewCheckpointV1(timestamp time.Time) *CheckpointEnvelopeV1 {
return &CheckpointEnvelopeV1{
Version: V1,
Checkpoint: CheckpointV1{
Timestamp: timestamp,
},
}
}

// WithCommitHash sets the commit hash on the checkpoint.
func (c *CheckpointEnvelopeV1) WithCommitHash(commitHash string) *CheckpointEnvelopeV1 {
c.Checkpoint.CommitHash = &commitHash
return c
}

// WithBranch sets the branch on the checkpoint.
func (c *CheckpointEnvelopeV1) WithBranch(branch string) *CheckpointEnvelopeV1 {
c.Checkpoint.Branch = &branch
return c
}

// WithVersion sets the version on the checkpoint.
func (c *CheckpointEnvelopeV1) WithVersion(version string) *CheckpointEnvelopeV1 {
c.Checkpoint.Version = &version
return c
}

// WithDigest sets the digest on the checkpoint.
func (c *CheckpointEnvelopeV1) WithDigest(digest string) *CheckpointEnvelopeV1 {
c.Checkpoint.Digest = &digest
return c
}
122 changes: 122 additions & 0 deletions internal/entities/checkpoints/checkpoints_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2024 Stacklok, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package checkpoints contains logic relating to checkpoint management for entities
package checkpoints

import (
"encoding/json"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestCheckpointEnvelopeV1_MarshalJSON(t *testing.T) {
t.Parallel()

// Create a fixed timestamp for consistent test results
timestamp := time.Date(2023, 7, 31, 12, 0, 0, 0, time.UTC)

// Test cases
tests := []struct {
name string
input *CheckpointEnvelopeV1
expected string
}{
{
name: "all fields set",
input: NewCheckpointV1(timestamp).
WithCommitHash("abc123").
WithBranch("main").
WithVersion("v1.0.0").
WithDigest("sha256:xyz"),
expected: `{"version":"v1","checkpoint":{"timestamp":"2023-07-31T12:00:00Z","commitHash":"abc123","branch":"main","version":"v1.0.0","digest":"sha256:xyz"}}`,
},
{
name: "optional fields omitted",
input: NewCheckpointV1(timestamp),
expected: `{"version":"v1","checkpoint":{"timestamp":"2023-07-31T12:00:00Z"}}`,
},
{
name: "commit-related fields set",
input: NewCheckpointV1(timestamp).
WithCommitHash("abc123").
WithBranch("main"),
expected: `{"version":"v1","checkpoint":{"timestamp":"2023-07-31T12:00:00Z","commitHash":"abc123","branch":"main"}}`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

// Marshal the input to JSON
output, err := json.Marshal(tt.input)
require.NoError(t, err)

assert.Equal(t, string(output), tt.expected)
})
}
}

func TestCheckpointEnvelopeV1_UnmarshalJson(t *testing.T) {
t.Parallel()

// Create a fixed timestamp for consistent test results
timestamp := time.Date(2023, 7, 31, 12, 0, 0, 0, time.UTC)

// Test cases
tests := []struct {
name string
input string
expected *CheckpointEnvelopeV1
}{
{
name: "all fields set",
input: `{"version":"v1","checkpoint":{"timestamp":"2023-07-31T12:00:00Z","commitHash":"abc123","branch":"main","version":"v1.0.0","digest":"sha256:xyz"}}`,
expected: NewCheckpointV1(timestamp).
WithCommitHash("abc123").
WithBranch("main").
WithVersion("v1.0.0").
WithDigest("sha256:xyz"),
},
{
name: "optional fields omitted",
input: `{"version":"v1","checkpoint":{"timestamp":"2023-07-31T12:00:00Z"}}`,
expected: NewCheckpointV1(timestamp),
},
{
name: "commit-related fields set",
input: `{"version":"v1","checkpoint":{"timestamp":"2023-07-31T12:00:00Z","commitHash":"abc123","branch":"main"}}`,
expected: NewCheckpointV1(timestamp).
WithCommitHash("abc123").
WithBranch("main"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

// Unmarshal the input to a CheckpointEnvelopeV1
var output CheckpointEnvelopeV1
err := json.Unmarshal([]byte(tt.input), &output)
require.NoError(t, err)

assert.Equal(t, output, *tt.expected)
})
}
}

0 comments on commit 9ef39af

Please sign in to comment.