Skip to content
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
45 changes: 44 additions & 1 deletion app/controlplane/pkg/biz/projectversion_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2024 The Chainloop Authors.
// Copyright 2024-2025 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@ package biz_test
import (
"context"
"testing"
"time"

"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz"
"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz/testhelpers"
Expand Down Expand Up @@ -57,6 +58,48 @@ func (s *ProjectVersionIntegrationTestSuite) TestUpdateReleaseStatus() {
require.Error(t, err)
}

func (s *ProjectVersionIntegrationTestSuite) TestReleasedAtTimestampPreserved() {
t := s.T()
ctx := context.Background()

// Create a prerelease version
version, err := s.ProjectVersion.Create(ctx, s.project.ID.String(), "2.0.0", true)
require.NoError(t, err)
require.True(t, version.Prerelease)
require.Nil(t, version.ReleasedAt, "Prerelease version should not have released_at set")

// Update to release status for the first time
releasedVersion, err := s.ProjectVersion.UpdateReleaseStatus(ctx, version.ID.String(), true)
require.NoError(t, err)
require.False(t, releasedVersion.Prerelease)
require.NotNil(t, releasedVersion.ReleasedAt, "Released version should have released_at set")
firstReleasedAt := releasedVersion.ReleasedAt

// Wait a bit to ensure timestamps would differ if reset
time.Sleep(100 * time.Millisecond)

// Update to release status again (should preserve original timestamp)
reReleasedVersion, err := s.ProjectVersion.UpdateReleaseStatus(ctx, version.ID.String(), true)
require.NoError(t, err)
require.False(t, reReleasedVersion.Prerelease)
require.NotNil(t, reReleasedVersion.ReleasedAt, "Released version should still have released_at set")
require.Equal(t, firstReleasedAt, reReleasedVersion.ReleasedAt, "released_at timestamp should be preserved on subsequent release updates")

// Update back to prerelease (should clear released_at)
preReleaseVersion, err := s.ProjectVersion.UpdateReleaseStatus(ctx, version.ID.String(), false)
require.NoError(t, err)
require.True(t, preReleaseVersion.Prerelease)
require.Nil(t, preReleaseVersion.ReleasedAt, "Prerelease version should have released_at cleared")

// Update to release status again (should set a new timestamp)
time.Sleep(100 * time.Millisecond)
newReleasedVersion, err := s.ProjectVersion.UpdateReleaseStatus(ctx, version.ID.String(), true)
require.NoError(t, err)
require.False(t, newReleasedVersion.Prerelease)
require.NotNil(t, newReleasedVersion.ReleasedAt, "Re-released version should have released_at set")
require.NotEqual(t, firstReleasedAt, newReleasedVersion.ReleasedAt, "released_at should be a new timestamp after toggling through prerelease")
}

// 3 orgs, user belongs to org1 and org2 but not org3
func (s *ProjectVersionIntegrationTestSuite) SetupTest() {
t := s.T()
Expand Down
20 changes: 17 additions & 3 deletions app/controlplane/pkg/data/projectversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,30 @@ func (r *ProjectVersionRepo) Update(ctx context.Context, id uuid.UUID, updates *
if updates == nil {
updates = &biz.ProjectVersionUpdateOpts{}
}
// Only set released_at if it's not already set
existing, err := r.data.DB.ProjectVersion.Query().Where(projectversion.IDEQ(id), projectversion.DeletedAtIsNil()).Only(ctx)
if err != nil {
if ent.IsNotFound(err) {
return nil, biz.NewErrNotFound("Version")
}

return nil, err
}

q := r.data.DB.ProjectVersion.UpdateOneID(id).SetNillablePrerelease(updates.Prerelease).SetUpdatedAt(time.Now())
now := time.Now()
q := existing.Update().SetNillablePrerelease(updates.Prerelease).SetUpdatedAt(now)
// we are setting the value either false or true
if updates.Prerelease != nil {
// We are marking it as a release
if !*updates.Prerelease {
q = q.SetReleasedAt(time.Now())
// if not set
if existing.ReleasedAt.IsZero() {
// Only set released_at if it's not already set
q.SetReleasedAt(now)
}
} else {
// We are resetting it to pre-release
q = q.ClearReleasedAt()
q.ClearReleasedAt()
}
}

Expand Down
Loading