diff --git a/frontend/src/component/project/Project/Project.tsx b/frontend/src/component/project/Project/Project.tsx
index e7b8084b1eb5..2db8712c5fe6 100644
--- a/frontend/src/component/project/Project/Project.tsx
+++ b/frontend/src/component/project/Project/Project.tsx
@@ -44,7 +44,6 @@ import { ProjectApplications } from '../ProjectApplications/ProjectApplications'
import { ProjectInsights } from './ProjectInsights/ProjectInsights';
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
import { ProjectArchived } from './ArchiveProject/ProjectArchived';
-import { useUiFlag } from 'hooks/useUiFlag';
const StyledBadge = styled(Badge)(({ theme }) => ({
position: 'absolute',
@@ -77,7 +76,6 @@ export const Project = () => {
const basePath = `/projects/${projectId}`;
const projectName = project?.name || projectId;
const { favorite, unfavorite } = useFavoriteProjectsApi();
- const archiveProjectsEnabled = useUiFlag('archiveProjects');
const [showDelDialog, setShowDelDialog] = useState(false);
@@ -192,7 +190,7 @@ export const Project = () => {
);
- if (archiveProjectsEnabled && Boolean(project.archivedAt)) {
+ if (project.archivedAt) {
return ;
}
diff --git a/frontend/src/component/project/Project/ProjectSettings/Settings/EditProject/EditProject.tsx b/frontend/src/component/project/Project/ProjectSettings/Settings/EditProject/EditProject.tsx
index 01a277b16db7..56d13e2b3615 100644
--- a/frontend/src/component/project/Project/ProjectSettings/Settings/EditProject/EditProject.tsx
+++ b/frontend/src/component/project/Project/ProjectSettings/Settings/EditProject/EditProject.tsx
@@ -10,12 +10,10 @@ import { Alert, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { UpdateEnterpriseSettings } from './UpdateEnterpriseSettings';
import { UpdateProject } from './UpdateProject';
-import { DeleteProjectForm } from './DeleteProjectForm';
import useProjectOverview, {
featuresCount,
} from 'hooks/api/getters/useProjectOverview/useProjectOverview';
import { ArchiveProjectForm } from './ArchiveProjectForm';
-import { useUiFlag } from 'hooks/useUiFlag';
const StyledFormContainer = styled('div')(({ theme }) => ({
display: 'flex',
@@ -28,7 +26,6 @@ const EditProject = () => {
const { hasAccess } = useContext(AccessContext);
const id = useRequiredPathParam('projectId');
const { project } = useProjectOverview(id);
- const archiveProjectsEnabled = useUiFlag('archiveProjects');
if (!project.name) {
return null;
@@ -52,19 +49,7 @@ const EditProject = () => {
condition={isEnterprise()}
show={}
/>
-
- }
- elseShow={
-
- }
- />
+
>
);
diff --git a/frontend/src/component/project/ProjectList/LegacyProjectList.tsx b/frontend/src/component/project/ProjectList/LegacyProjectList.tsx
index deb87431fcbe..68f34b485769 100644
--- a/frontend/src/component/project/ProjectList/LegacyProjectList.tsx
+++ b/frontend/src/component/project/ProjectList/LegacyProjectList.tsx
@@ -25,7 +25,6 @@ import { useProfile } from 'hooks/api/getters/useProfile/useProfile';
import { groupProjects } from './group-projects';
import { ProjectGroup } from './ProjectGroup';
import { CreateProjectDialog } from '../Project/CreateProject/NewCreateProjectForm/CreateProjectDialog';
-import { useUiFlag } from 'hooks/useUiFlag';
const StyledApiError = styled(ApiError)(({ theme }) => ({
maxWidth: '500px',
@@ -126,7 +125,6 @@ export const ProjectList = () => {
const [searchValue, setSearchValue] = useState(
searchParams.get('search') || '',
);
- const archiveProjectsEnabled = useUiFlag('archiveProjects');
const myProjects = new Set(useProfile().profile?.projects || []);
@@ -200,20 +198,15 @@ export const ProjectList = () => {
>
}
/>
-
-
- Archived projects
-
-
- >
- }
- />
+ <>
+
+ Archived projects
+
+
+ >
>
diff --git a/frontend/src/component/project/ProjectList/ProjectList.tsx b/frontend/src/component/project/ProjectList/ProjectList.tsx
index 4c3acbb40fb3..801f59039f03 100644
--- a/frontend/src/component/project/ProjectList/ProjectList.tsx
+++ b/frontend/src/component/project/ProjectList/ProjectList.tsx
@@ -36,7 +36,6 @@ const NewProjectList = () => {
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const [state, setState] = useProjectsListState();
- const archiveProjectsEnabled = useUiFlag('archiveProjects');
const myProjects = new Set(useProfile().profile?.projects || []);
@@ -78,10 +77,7 @@ const NewProjectList = () => {
}
/>
- }
- />
+
diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts
index 7fcb3fb32722..784192cf63a6 100644
--- a/frontend/src/interfaces/uiConfig.ts
+++ b/frontend/src/interfaces/uiConfig.ts
@@ -86,7 +86,6 @@ export type UiFlags = {
enableLegacyVariants?: boolean;
navigationSidebar?: boolean;
flagCreator?: boolean;
- archiveProjects?: boolean;
projectListImprovements?: boolean;
onboardingUI?: boolean;
eventTimeline?: boolean;
diff --git a/src/lib/features/feature-toggle/feature-toggle-service.ts b/src/lib/features/feature-toggle/feature-toggle-service.ts
index 99c06a39ac99..d34a4b3f6f16 100644
--- a/src/lib/features/feature-toggle/feature-toggle-service.ts
+++ b/src/lib/features/feature-toggle/feature-toggle-service.ts
@@ -1230,14 +1230,12 @@ class FeatureToggleService {
}
private async validateActiveProject(projectId: string) {
- if (this.flagResolver.isEnabled('archiveProjects')) {
- const hasActiveProject =
- await this.projectStore.hasActiveProject(projectId);
- if (!hasActiveProject) {
- throw new NotFoundError(
- `Active project with id ${projectId} does not exist`,
- );
- }
+ const hasActiveProject =
+ await this.projectStore.hasActiveProject(projectId);
+ if (!hasActiveProject) {
+ throw new NotFoundError(
+ `Active project with id ${projectId} does not exist`,
+ );
}
}
@@ -1253,12 +1251,8 @@ class FeatureToggleService {
await this.validateName(value.name);
await this.validateFeatureFlagNameAgainstPattern(value.name, projectId);
- let projectExists: boolean;
- if (this.flagResolver.isEnabled('archiveProjects')) {
- projectExists = await this.projectStore.hasActiveProject(projectId);
- } else {
- projectExists = await this.projectStore.hasProject(projectId);
- }
+ const projectExists =
+ await this.projectStore.hasActiveProject(projectId);
if (await this.projectStore.isFeatureLimitReached(projectId)) {
throw new InvalidOperationError(
diff --git a/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts b/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts
index 5fd0b835b2a0..fb93c96dab4b 100644
--- a/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts
+++ b/src/lib/features/feature-toggle/tests/feature-toggle-service.e2e.test.ts
@@ -38,7 +38,6 @@ let segmentService: ISegmentService;
let eventService: EventService;
let environmentService: EnvironmentService;
let unleashConfig: IUnleashConfig;
-const TEST_USER_ID = -9999;
const mockConstraints = (): IConstraint[] => {
return Array.from({ length: 5 }).map(() => ({
values: ['x', 'y', 'z'],
@@ -51,7 +50,7 @@ const irrelevantDate = new Date();
beforeAll(async () => {
const config = createTestConfig({
- experimental: { flags: { archiveProjects: true } },
+ experimental: { flags: {} },
});
db = await dbInit(
'feature_toggle_service_v2_service_serial',
@@ -77,7 +76,6 @@ beforeEach(async () => {
});
test('Should create feature flag strategy configuration', async () => {
const projectId = 'default';
- const username = 'feature-flag';
const config: Omit = {
name: 'default',
constraints: [],
@@ -104,7 +102,6 @@ test('Should create feature flag strategy configuration', async () => {
test('Should be able to update existing strategy configuration', async () => {
const projectId = 'default';
- const username = 'existing-strategy';
const featureName = 'update-existing-strategy';
const config: Omit = {
name: 'default',
@@ -139,8 +136,6 @@ test('Should be able to update existing strategy configuration', async () => {
test('Should be able to get strategy by id', async () => {
const featureName = 'get-strategy-by-id';
const projectId = 'default';
-
- const userName = 'strategy';
const config: Omit = {
name: 'default',
constraints: [],
@@ -168,8 +163,6 @@ test('Should be able to get strategy by id', async () => {
test('should ignore name in the body when updating feature flag', async () => {
const featureName = 'body-name-update';
const projectId = 'default';
-
- const userName = 'strategy';
const secondFeatureName = 'body-name-update2';
await service.createFeatureToggle(
@@ -213,8 +206,6 @@ test('should ignore name in the body when updating feature flag', async () => {
test('should not get empty rows as features', async () => {
const projectId = 'default';
- const userName = 'strategy';
-
await service.createFeatureToggle(
projectId,
{
@@ -505,7 +496,6 @@ test('If change requests are enabled, cannot change variants without going via C
});
test('If CRs are protected for any environment in the project stops bulk update of variants', async () => {
- const user = { email: 'test@example.com', username: 'test-user' } as User;
const project = await stores.projectStore.create({
id: 'crOnVariantsProject',
name: 'crOnVariantsProject',
@@ -599,7 +589,6 @@ test('getPlaygroundFeatures should return ids and titles (if they exist) on clie
const projectId = 'default';
const title = 'custom strategy title';
- const userName = 'strategy';
const config: Omit = {
name: 'default',
constraints: [],
@@ -819,7 +808,6 @@ test('Should enable disabled strategies on feature environment enabled', async (
const flagName = 'enableThisFlag';
const project = 'default';
const environment = 'default';
- const shouldActivateDisabledStrategies = true;
await service.createFeatureToggle(
project,
{
@@ -856,7 +844,7 @@ test('Should enable disabled strategies on feature environment enabled', async (
true,
TEST_AUDIT_USER,
{ email: 'test@example.com' } as User,
- shouldActivateDisabledStrategies,
+ true,
);
const strategy = await service.getStrategy(createdConfig.id);
diff --git a/src/lib/features/project/project-read-model.ts b/src/lib/features/project/project-read-model.ts
index c793543d81ba..b8b12d60cf87 100644
--- a/src/lib/features/project/project-read-model.ts
+++ b/src/lib/features/project/project-read-model.ts
@@ -104,12 +104,10 @@ export class ProjectReadModel implements IProjectReadModel {
})
.orderBy('projects.name', 'asc');
- if (this.flagResolver.isEnabled('archiveProjects')) {
- if (query?.archived === true) {
- projects = projects.whereNot(`${TABLE}.archived_at`, null);
- } else {
- projects = projects.where(`${TABLE}.archived_at`, null);
- }
+ if (query?.archived === true) {
+ projects = projects.whereNot(`${TABLE}.archived_at`, null);
+ } else {
+ projects = projects.where(`${TABLE}.archived_at`, null);
}
if (query?.id) {
@@ -124,12 +122,9 @@ export class ProjectReadModel implements IProjectReadModel {
'MAX(events.created_at) AS last_updated',
),
'project_settings.project_mode',
+ 'projects.archived_at',
] as (string | Raw)[];
- if (this.flagResolver.isEnabled('archiveProjects')) {
- selectColumns.push(`${TABLE}.archived_at`);
- }
-
let groupByColumns = ['projects.id', 'project_settings.project_mode'];
if (userId) {
@@ -179,12 +174,10 @@ export class ProjectReadModel implements IProjectReadModel {
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
.orderBy('projects.name', 'asc');
- if (this.flagResolver.isEnabled('archiveProjects')) {
- if (query?.archived === true) {
- projects = projects.whereNot(`${TABLE}.archived_at`, null);
- } else {
- projects = projects.where(`${TABLE}.archived_at`, null);
- }
+ if (query?.archived === true) {
+ projects = projects.whereNot(`${TABLE}.archived_at`, null);
+ } else {
+ projects = projects.where(`${TABLE}.archived_at`, null);
}
if (query?.id) {
@@ -199,12 +192,9 @@ export class ProjectReadModel implements IProjectReadModel {
'count(features.name) FILTER (WHERE features.archived_at is null and features.potentially_stale IS TRUE) AS potentially_stale_feature_count',
),
'project_stats.avg_time_to_prod_current_window',
+ 'projects.archived_at',
] as (string | Raw)[];
- if (this.flagResolver.isEnabled('archiveProjects')) {
- selectColumns.push(`${TABLE}.archived_at`);
- }
-
const groupByColumns = [
'projects.id',
'project_stats.avg_time_to_prod_current_window',
diff --git a/src/lib/features/project/project-service.e2e.test.ts b/src/lib/features/project/project-service.e2e.test.ts
index 10fa6b02e180..1171f78ee5cf 100644
--- a/src/lib/features/project/project-service.e2e.test.ts
+++ b/src/lib/features/project/project-service.e2e.test.ts
@@ -82,9 +82,7 @@ beforeAll(async () => {
await stores.accessStore.addUserToRole(opsUser.id, 1, '');
const config = createTestConfig({
getLogger,
- experimental: {
- flags: { archiveProjects: true },
- },
+ experimental: {},
});
eventService = createEventsService(db.rawDatabase, config);
accessService = createAccessService(db.rawDatabase, config);
diff --git a/src/lib/features/project/project-service.ts b/src/lib/features/project/project-service.ts
index f68e4af19356..fbcec958bcba 100644
--- a/src/lib/features/project/project-service.ts
+++ b/src/lib/features/project/project-service.ts
@@ -499,14 +499,12 @@ export default class ProjectService {
}
private async validateActiveProject(projectId: string) {
- if (this.flagResolver.isEnabled('archiveProjects')) {
- const hasActiveProject =
- await this.projectStore.hasActiveProject(projectId);
- if (!hasActiveProject) {
- throw new NotFoundError(
- `Active project with id ${projectId} does not exist`,
- );
- }
+ const hasActiveProject =
+ await this.projectStore.hasActiveProject(projectId);
+ if (!hasActiveProject) {
+ throw new NotFoundError(
+ `Active project with id ${projectId} does not exist`,
+ );
}
}
@@ -1551,9 +1549,7 @@ export default class ProjectService {
health: project.health || 0,
favorite: favorite,
updatedAt: project.updatedAt,
- ...(this.flagResolver.isEnabled('archiveProjects')
- ? { archivedAt: project.archivedAt }
- : {}),
+ archivedAt: project.archivedAt,
createdAt: project.createdAt,
onboardingStatus,
environments,
diff --git a/src/lib/features/project/project-store.e2e.test.ts b/src/lib/features/project/project-store.e2e.test.ts
index 4f5c9cbdae22..a338c10f821c 100644
--- a/src/lib/features/project/project-store.e2e.test.ts
+++ b/src/lib/features/project/project-store.e2e.test.ts
@@ -12,7 +12,7 @@ let environmentStore: IEnvironmentStore;
beforeAll(async () => {
db = await dbInit('project_store_serial', getLogger, {
- experimental: { flags: { archiveProjects: true } },
+ experimental: { flags: {} },
});
stores = db.stores;
projectStore = stores.projectStore;
diff --git a/src/lib/features/project/project-store.ts b/src/lib/features/project/project-store.ts
index 83b644125a62..7c0fc2188771 100644
--- a/src/lib/features/project/project-store.ts
+++ b/src/lib/features/project/project-store.ts
@@ -121,9 +121,7 @@ class ProjectStore implements IProjectStore {
.where(query)
.orderBy('name', 'asc');
- if (this.flagResolver.isEnabled('archiveProjects')) {
- projects = projects.where(`${TABLE}.archived_at`, null);
- }
+ projects = projects.where(`${TABLE}.archived_at`, null);
const rows = await projects;
@@ -131,10 +129,7 @@ class ProjectStore implements IProjectStore {
}
async get(id: string): Promise {
- let extraColumns: string[] = [];
- if (this.flagResolver.isEnabled('archiveProjects')) {
- extraColumns = ['archived_at'];
- }
+ const extraColumns: string[] = ['archived_at'];
return this.db
.first([...COLUMNS, ...SETTINGS_COLUMNS, ...extraColumns])
@@ -518,8 +513,7 @@ class ProjectStore implements IProjectStore {
async getApplicationsByProject(
params: IProjectApplicationsSearchParams,
): Promise {
- const { project, limit, sortOrder, sortBy, searchParams, offset } =
- params;
+ const { project, limit, sortOrder, searchParams, offset } = params;
const validatedSortOrder =
sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : 'asc';
const query = this.db
@@ -625,9 +619,7 @@ class ProjectStore implements IProjectStore {
async count(): Promise {
let count = this.db.from(TABLE).count('*');
- if (this.flagResolver.isEnabled('archiveProjects')) {
- count = count.where(`${TABLE}.archived_at`, null);
- }
+ count = count.where(`${TABLE}.archived_at`, null);
return count.then((res) => Number(res[0].count));
}
@@ -650,9 +642,7 @@ class ProjectStore implements IProjectStore {
this.db.raw(`COALESCE(${SETTINGS_TABLE}.project_mode, 'open')`),
);
- if (this.flagResolver.isEnabled('archiveProjects')) {
- query = query.where(`${TABLE}.archived_at`, null);
- }
+ query = query.where(`${TABLE}.archived_at`, null);
const result: ProjectModeCount[] = await query;
diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts
index efc2d83618ba..864639592743 100644
--- a/src/lib/types/experimental.ts
+++ b/src/lib/types/experimental.ts
@@ -56,7 +56,6 @@ export type IFlagKey =
| 'extendedMetrics'
| 'removeUnsafeInlineStyleSrc'
| 'originMiddleware'
- | 'archiveProjects'
| 'projectListImprovements'
| 'addonUsageMetrics'
| 'onboardingMetrics'
@@ -280,10 +279,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_ORIGIN_MIDDLEWARE,
false,
),
- archiveProjects: parseEnvVarBoolean(
- process.env.UNLEASH_EXPERIMENTAL_ARCHIVE_PROJECTS,
- false,
- ),
projectListImprovements: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_PROJECT_LIST_IMPROVEMENTS,
false,