Skip to content
Open
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
47 changes: 24 additions & 23 deletions services/cd-service/pkg/repository/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,8 @@ func (c *CreateApplicationVersion) Transform(
return "", err
}
t.AddAppEnv(c.Application, env, teamOwner)
envIsConfiguredLatest:=hasUpstream && config.Upstream.Latest && isLatest
downstreamDeploymentRequested := slices.Contains(c.DeployToDownstreamEnvironments, env)
envIsConfiguredLatest := hasUpstream && config.Upstream.Latest && isLatest
downstreamDeploymentRequested := slices.Contains(c.DeployToDownstreamEnvironments, env)
if (envIsConfiguredLatest || downstreamDeploymentRequested) && !c.IsPrepublish {
d := &DeployApplicationVersion{
SourceTrain: nil,
Expand Down Expand Up @@ -1112,7 +1112,7 @@ func (u *UndeployApplication) Transform(
return "", fmt.Errorf("UndeployApplication(db): error cannot un-deploy application '%v' the release '%v' cannot be found", u.Application, env)
}

var isUndeploy bool
isUndeploy := false
if deployment != nil && deployment.ReleaseNumbers.Version != nil {
release, err := state.DBHandler.DBSelectReleaseByVersion(ctx, transaction, u.Application, deployment.ReleaseNumbers, true)
if err != nil {
Expand All @@ -1135,30 +1135,31 @@ func (u *UndeployApplication) Transform(
return "", err
}
}
if deployment == nil || deployment.ReleaseNumbers.Version == nil || isUndeploy {
locks, err := state.DBHandler.DBSelectAllAppLocks(ctx, transaction, env, u.Application)
if err != nil {
return "", err
}
if locks == nil {
continue
}
user, err := auth.ReadUserFromContext(ctx)
if deployment != nil && deployment.ReleaseNumbers.Version != nil && !isUndeploy {

return "", fmt.Errorf("UndeployApplication(db): error cannot un-deploy application '%v' the release '%v' is not un-deployed", u.Application, env)

}
locks, err := state.DBHandler.DBSelectAllAppLocks(ctx, transaction, env, u.Application)
if err != nil {
return "", err
}
if locks == nil {
continue
}
user, err := auth.ReadUserFromContext(ctx)
if err != nil {
return "", err
}
for _, currentLockID := range locks {
err := state.DBHandler.DBDeleteApplicationLock(ctx, transaction, env, u.Application, currentLockID, db.LockDeletionMetadata{
DeletedByUser: user.Name,
DeletedByEmail: user.Email,
})
if err != nil {
return "", err
}
for _, currentLockID := range locks {
err := state.DBHandler.DBDeleteApplicationLock(ctx, transaction, env, u.Application, currentLockID, db.LockDeletionMetadata{
DeletedByUser: user.Name,
DeletedByEmail: user.Email,
})
if err != nil {
return "", err
}
}
continue
}
return "", fmt.Errorf("UndeployApplication(db): error cannot un-deploy application '%v' the release '%v' is not un-deployed", u.Application, env)
}
dbApp, err := state.DBHandler.DBSelectExistingApp(ctx, transaction, u.Application)
if err != nil {
Expand Down
126 changes: 75 additions & 51 deletions services/manifest-repo-export-service/pkg/repository/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -1711,7 +1711,7 @@ func (c *DeleteEnvFromApp) Transform(
ctx context.Context,
state *State,
tCtx TransformerContext,
_ *sql.Tx,
transaction *sql.Tx,
) (string, error) {
envName := types.EnvName(c.Environment)
fs := state.Filesystem
Expand All @@ -1720,33 +1720,38 @@ func (c *DeleteEnvFromApp) Transform(
return fmt.Sprintf("DeleteEnvFromApp app '%s' on env '%s': %s", c.Application, c.Environment, fmt.Sprintf(format, a...))
}

if c.Application == "" {
return "", fmt.Errorf("DeleteEnvFromApp app '%s' on env '%s': Need to provide the application", c.Application, c.Environment)
thisErrorf := func(format string, a ...any) error {
return fmt.Errorf("DeleteEnvFromApp app '%s' on env '%s': %s", c.Application, c.Environment, fmt.Sprintf(format, a...))
}

if c.Application == "" {
return "", thisErrorf("Need to provide the application")
}
if c.Environment == "" {
return "", fmt.Errorf("DeleteEnvFromApp app '%s' on env '%s': Need to provide the environment", c.Application, c.Environment)
return "", thisErrorf("Need to provide the environment")
}

envAppDir := environmentApplicationDirectory(fs, envName, c.Application)
entries, err := fs.ReadDir(envAppDir)
msg := fmt.Sprintf("Attempted to remove environment '%v' from application '%v' but it did not exist", c.Environment, c.Application)
if err != nil {
if entries, err := fs.ReadDir(envAppDir); err != nil {
return "", wrapFileError(err, envAppDir, thisSprintf("Could not open application directory"))
}

if entries == nil {
} else if entries == nil {
// app was never deployed on this env, so that's unusual - but for idempotency we treat it just like a success case:
msg := thisSprintf("environment does not exist.")
logger.FromContext(ctx).Warn(msg)
return msg, nil
}

err = fs.Remove(envAppDir)
if err != nil {
return "", wrapFileError(err, envAppDir, thisSprintf("Cannot delete app.'"))
appLocksDir := fs.Join(envAppDir, "locks")
if err := fs.Remove(appLocksDir); err != nil {
return "", thisErrorf("cannot delete app locks '%v'", appLocksDir)
}

if err := fs.Remove(envAppDir); err != nil {
return "", wrapFileError(err, envAppDir, thisSprintf("cannot delete app."))
}

tCtx.DeleteEnvFromApp(c.Application, types.EnvName(c.Environment))

return fmt.Sprintf("Environment '%v' was removed from application '%v' successfully.", c.Environment, c.Application), nil
}

Expand Down Expand Up @@ -1918,6 +1923,51 @@ func (u *UndeployApplication) SetEslVersion(id db.TransformerID) {
u.TransformerEslVersion = id
}

func removeApplication(fs billy.Filesystem, application string) error {
appDir := applicationDirectory(fs, application)
releasesDir := fs.Join(appDir, "releases")
files, err := fs.ReadDir(releasesDir)
if err != nil {
return fmt.Errorf("could not read the releases directory %s %w", releasesDir, err)
}
for _, file := range files {
if file.IsDir() {
releaseDir := fs.Join(releasesDir, file.Name())
commitIDFile := fs.Join(releaseDir, "source_commit_id")
content, err := util.ReadFile(fs, commitIDFile)
if err != nil {
// release does not have a corresponding commit, which might be the case if it's an undeploy release, no prob
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's a not-found error, this is fine.
But if it's not a not-found error, we should return an error, not continue.

if errors.Is(err, os.ErrNotExist) {
continue
} else {
return err
}
}
if commitID := string(content); valid.SHA1CommitID(commitID) {
if err := removeCommit(fs, commitID, application); err != nil {
return fmt.Errorf("could not remove the commit: %w", err)
}
}
}
}
if err = fs.Remove(appDir); err != nil && !errors.Is(err, os.ErrNotExist) {
return wrapFileError(err, appDir, "could not remove application directory")
}
return nil
}

func removeApplicationFromEnvs(fs billy.Filesystem, application string, configs *map[types.EnvName]config.EnvironmentConfig) ([]types.EnvName, error) {
result := make([]types.EnvName, 0)
for env := range *configs {
appDir := environmentApplicationDirectory(fs, env, application)
result := append(result, env)
if err := fs.Remove(appDir); err != nil && !errors.Is(err, os.ErrNotExist) {
return result, fmt.Errorf("unexpected error application '%v' environment '%v': '%w'", application, env, err)
}
}
return result, nil
}

func (u *UndeployApplication) Transform(
ctx context.Context,
state *State,
Expand All @@ -1926,8 +1976,6 @@ func (u *UndeployApplication) Transform(
) (string, error) {
//All verifications were already done by the cd-service. This transformer should just blindly delete the affected files
fs := state.Filesystem

appDir := applicationDirectory(fs, u.Application)
configs, err := state.GetAllEnvironmentConfigsFromDB(ctx, transaction) // we use ALL envs, to be sure
if err != nil {
return "", fmt.Errorf("could not get environment configs: %w", err)
Expand Down Expand Up @@ -1965,50 +2013,26 @@ func (u *UndeployApplication) Transform(
logger.FromContext(ctx).Sugar().Warnf("Maximize git data is enabled but could not find undeploy file %q for application %q on environment %q.", undeployFile, u.Application, env)
}
} else {
return "", fmt.Errorf("UndeployApplication(repo): error cannot un-deploy application '%v' the release on '%v' is not un-deployed: '%v'. Error: %w", u.Application, env, undeployFile, err)
return "", fmt.Errorf("UndeployApplication: Error while checking for undeploy file: %v", err)
}
}

}
// remove application
releasesDir := fs.Join(appDir, "releases")
files, err := fs.ReadDir(releasesDir)
if err != nil {
return "", fmt.Errorf("could not read the releases directory %s %w", releasesDir, err)
}
for _, file := range files {
if file.IsDir() {
releaseDir := fs.Join(releasesDir, file.Name())
commitIDFile := fs.Join(releaseDir, "source_commit_id")
var commitID string
dat, err := util.ReadFile(fs, commitIDFile)
if err != nil {
// release does not have a corresponding commit, which might be the case if it's an undeploy release, no prob
continue
}
commitID = string(dat)
if valid.SHA1CommitID(commitID) {
if err := removeCommit(fs, commitID, u.Application); err != nil {
return "", fmt.Errorf("could not remove the commit: %w", err)
}
}
}

if err := removeApplication(fs, u.Application); err != nil {
return "", err
}

if err = fs.Remove(appDir); err != nil && !errors.Is(err, os.ErrNotExist) {
return "", wrapFileError(err, appDir, "UndeployApplication: could not remove application directory")
teamOwner, err := state.GetApplicationTeamOwner(ctx, transaction, u.Application)
if err != nil {
return "", fmt.Errorf("could not find team for app %s: %w", u.Application, err)
}
for env := range configs {
appDir := environmentApplicationDirectory(fs, env, u.Application)
teamOwner, err := state.GetApplicationTeamOwner(ctx, transaction, u.Application)
if err != nil {
return "", fmt.Errorf("could not find team for app %s: %w", u.Application, err)
}
t.AddAppEnv(u.Application, env, teamOwner)
// remove environment application
if err := fs.Remove(appDir); err != nil && !errors.Is(err, os.ErrNotExist) {
return "", fmt.Errorf("UndeployApplication: unexpected error application '%v' environment '%v': '%w'", u.Application, env, err)
if envs, err := removeApplicationFromEnvs(fs, u.Application, &configs); err == nil {
for _, env := range envs {
t.AddAppEnv(u.Application, env, teamOwner)
}
} else {
return "", err
}
return fmt.Sprintf("application '%v' was deleted successfully", u.Application), nil
}
Expand Down
Loading