mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-13 13:48:59 +02:00
[Gitar] Cleaning up stale flag: archiveProjects with value true (#8201)
This commit is contained in:
parent
b3ecb92edf
commit
1296327c03
@ -44,7 +44,6 @@ import { ProjectApplications } from '../ProjectApplications/ProjectApplications'
|
|||||||
import { ProjectInsights } from './ProjectInsights/ProjectInsights';
|
import { ProjectInsights } from './ProjectInsights/ProjectInsights';
|
||||||
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
import { ProjectArchived } from './ArchiveProject/ProjectArchived';
|
import { ProjectArchived } from './ArchiveProject/ProjectArchived';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const StyledBadge = styled(Badge)(({ theme }) => ({
|
const StyledBadge = styled(Badge)(({ theme }) => ({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -77,7 +76,6 @@ export const Project = () => {
|
|||||||
const basePath = `/projects/${projectId}`;
|
const basePath = `/projects/${projectId}`;
|
||||||
const projectName = project?.name || projectId;
|
const projectName = project?.name || projectId;
|
||||||
const { favorite, unfavorite } = useFavoriteProjectsApi();
|
const { favorite, unfavorite } = useFavoriteProjectsApi();
|
||||||
const archiveProjectsEnabled = useUiFlag('archiveProjects');
|
|
||||||
|
|
||||||
const [showDelDialog, setShowDelDialog] = useState(false);
|
const [showDelDialog, setShowDelDialog] = useState(false);
|
||||||
|
|
||||||
@ -192,7 +190,7 @@ export const Project = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (archiveProjectsEnabled && Boolean(project.archivedAt)) {
|
if (project.archivedAt) {
|
||||||
return <ProjectArchived name={project.name} />;
|
return <ProjectArchived name={project.name} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,12 +10,10 @@ import { Alert, styled } from '@mui/material';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { UpdateEnterpriseSettings } from './UpdateEnterpriseSettings';
|
import { UpdateEnterpriseSettings } from './UpdateEnterpriseSettings';
|
||||||
import { UpdateProject } from './UpdateProject';
|
import { UpdateProject } from './UpdateProject';
|
||||||
import { DeleteProjectForm } from './DeleteProjectForm';
|
|
||||||
import useProjectOverview, {
|
import useProjectOverview, {
|
||||||
featuresCount,
|
featuresCount,
|
||||||
} from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
} from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
import { ArchiveProjectForm } from './ArchiveProjectForm';
|
import { ArchiveProjectForm } from './ArchiveProjectForm';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const StyledFormContainer = styled('div')(({ theme }) => ({
|
const StyledFormContainer = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -28,7 +26,6 @@ const EditProject = () => {
|
|||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const id = useRequiredPathParam('projectId');
|
const id = useRequiredPathParam('projectId');
|
||||||
const { project } = useProjectOverview(id);
|
const { project } = useProjectOverview(id);
|
||||||
const archiveProjectsEnabled = useUiFlag('archiveProjects');
|
|
||||||
|
|
||||||
if (!project.name) {
|
if (!project.name) {
|
||||||
return null;
|
return null;
|
||||||
@ -52,19 +49,7 @@ const EditProject = () => {
|
|||||||
condition={isEnterprise()}
|
condition={isEnterprise()}
|
||||||
show={<UpdateEnterpriseSettings project={project} />}
|
show={<UpdateEnterpriseSettings project={project} />}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
<ArchiveProjectForm featureCount={featuresCount(project)} />
|
||||||
condition={archiveProjectsEnabled}
|
|
||||||
show={
|
|
||||||
<ArchiveProjectForm
|
|
||||||
featureCount={featuresCount(project)}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<DeleteProjectForm
|
|
||||||
featureCount={featuresCount(project)}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StyledFormContainer>
|
</StyledFormContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -25,7 +25,6 @@ import { useProfile } from 'hooks/api/getters/useProfile/useProfile';
|
|||||||
import { groupProjects } from './group-projects';
|
import { groupProjects } from './group-projects';
|
||||||
import { ProjectGroup } from './ProjectGroup';
|
import { ProjectGroup } from './ProjectGroup';
|
||||||
import { CreateProjectDialog } from '../Project/CreateProject/NewCreateProjectForm/CreateProjectDialog';
|
import { CreateProjectDialog } from '../Project/CreateProject/NewCreateProjectForm/CreateProjectDialog';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const StyledApiError = styled(ApiError)(({ theme }) => ({
|
const StyledApiError = styled(ApiError)(({ theme }) => ({
|
||||||
maxWidth: '500px',
|
maxWidth: '500px',
|
||||||
@ -126,7 +125,6 @@ export const ProjectList = () => {
|
|||||||
const [searchValue, setSearchValue] = useState(
|
const [searchValue, setSearchValue] = useState(
|
||||||
searchParams.get('search') || '',
|
searchParams.get('search') || '',
|
||||||
);
|
);
|
||||||
const archiveProjectsEnabled = useUiFlag('archiveProjects');
|
|
||||||
|
|
||||||
const myProjects = new Set(useProfile().profile?.projects || []);
|
const myProjects = new Set(useProfile().profile?.projects || []);
|
||||||
|
|
||||||
@ -200,9 +198,6 @@ export const ProjectList = () => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(archiveProjectsEnabled)}
|
|
||||||
show={
|
|
||||||
<>
|
<>
|
||||||
<Link
|
<Link
|
||||||
component={RouterLink}
|
component={RouterLink}
|
||||||
@ -212,8 +207,6 @@ export const ProjectList = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
<PageHeader.Divider />
|
<PageHeader.Divider />
|
||||||
</>
|
</>
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ProjectCreationButton />
|
<ProjectCreationButton />
|
||||||
</>
|
</>
|
||||||
|
@ -36,7 +36,6 @@ const NewProjectList = () => {
|
|||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
const [state, setState] = useProjectsListState();
|
const [state, setState] = useProjectsListState();
|
||||||
const archiveProjectsEnabled = useUiFlag('archiveProjects');
|
|
||||||
|
|
||||||
const myProjects = new Set(useProfile().profile?.projects || []);
|
const myProjects = new Set(useProfile().profile?.projects || []);
|
||||||
|
|
||||||
@ -78,10 +77,7 @@ const NewProjectList = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConditionallyRender
|
<ProjectArchiveLink />
|
||||||
condition={Boolean(archiveProjectsEnabled)}
|
|
||||||
show={<ProjectArchiveLink />}
|
|
||||||
/>
|
|
||||||
<ProjectCreationButton
|
<ProjectCreationButton
|
||||||
isDialogOpen={Boolean(state.create)}
|
isDialogOpen={Boolean(state.create)}
|
||||||
setIsDialogOpen={(create) =>
|
setIsDialogOpen={(create) =>
|
||||||
|
@ -86,7 +86,6 @@ export type UiFlags = {
|
|||||||
enableLegacyVariants?: boolean;
|
enableLegacyVariants?: boolean;
|
||||||
navigationSidebar?: boolean;
|
navigationSidebar?: boolean;
|
||||||
flagCreator?: boolean;
|
flagCreator?: boolean;
|
||||||
archiveProjects?: boolean;
|
|
||||||
projectListImprovements?: boolean;
|
projectListImprovements?: boolean;
|
||||||
onboardingUI?: boolean;
|
onboardingUI?: boolean;
|
||||||
eventTimeline?: boolean;
|
eventTimeline?: boolean;
|
||||||
|
@ -1230,7 +1230,6 @@ class FeatureToggleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async validateActiveProject(projectId: string) {
|
private async validateActiveProject(projectId: string) {
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
const hasActiveProject =
|
const hasActiveProject =
|
||||||
await this.projectStore.hasActiveProject(projectId);
|
await this.projectStore.hasActiveProject(projectId);
|
||||||
if (!hasActiveProject) {
|
if (!hasActiveProject) {
|
||||||
@ -1239,7 +1238,6 @@ class FeatureToggleService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async createFeatureToggle(
|
async createFeatureToggle(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
@ -1253,12 +1251,8 @@ class FeatureToggleService {
|
|||||||
await this.validateName(value.name);
|
await this.validateName(value.name);
|
||||||
await this.validateFeatureFlagNameAgainstPattern(value.name, projectId);
|
await this.validateFeatureFlagNameAgainstPattern(value.name, projectId);
|
||||||
|
|
||||||
let projectExists: boolean;
|
const projectExists =
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
await this.projectStore.hasActiveProject(projectId);
|
||||||
projectExists = await this.projectStore.hasActiveProject(projectId);
|
|
||||||
} else {
|
|
||||||
projectExists = await this.projectStore.hasProject(projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await this.projectStore.isFeatureLimitReached(projectId)) {
|
if (await this.projectStore.isFeatureLimitReached(projectId)) {
|
||||||
throw new InvalidOperationError(
|
throw new InvalidOperationError(
|
||||||
|
@ -38,7 +38,6 @@ let segmentService: ISegmentService;
|
|||||||
let eventService: EventService;
|
let eventService: EventService;
|
||||||
let environmentService: EnvironmentService;
|
let environmentService: EnvironmentService;
|
||||||
let unleashConfig: IUnleashConfig;
|
let unleashConfig: IUnleashConfig;
|
||||||
const TEST_USER_ID = -9999;
|
|
||||||
const mockConstraints = (): IConstraint[] => {
|
const mockConstraints = (): IConstraint[] => {
|
||||||
return Array.from({ length: 5 }).map(() => ({
|
return Array.from({ length: 5 }).map(() => ({
|
||||||
values: ['x', 'y', 'z'],
|
values: ['x', 'y', 'z'],
|
||||||
@ -51,7 +50,7 @@ const irrelevantDate = new Date();
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const config = createTestConfig({
|
const config = createTestConfig({
|
||||||
experimental: { flags: { archiveProjects: true } },
|
experimental: { flags: {} },
|
||||||
});
|
});
|
||||||
db = await dbInit(
|
db = await dbInit(
|
||||||
'feature_toggle_service_v2_service_serial',
|
'feature_toggle_service_v2_service_serial',
|
||||||
@ -77,7 +76,6 @@ beforeEach(async () => {
|
|||||||
});
|
});
|
||||||
test('Should create feature flag strategy configuration', async () => {
|
test('Should create feature flag strategy configuration', async () => {
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
const username = 'feature-flag';
|
|
||||||
const config: Omit<FeatureStrategySchema, 'id'> = {
|
const config: Omit<FeatureStrategySchema, 'id'> = {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
constraints: [],
|
constraints: [],
|
||||||
@ -104,7 +102,6 @@ test('Should create feature flag strategy configuration', async () => {
|
|||||||
|
|
||||||
test('Should be able to update existing strategy configuration', async () => {
|
test('Should be able to update existing strategy configuration', async () => {
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
const username = 'existing-strategy';
|
|
||||||
const featureName = 'update-existing-strategy';
|
const featureName = 'update-existing-strategy';
|
||||||
const config: Omit<FeatureStrategySchema, 'id'> = {
|
const config: Omit<FeatureStrategySchema, 'id'> = {
|
||||||
name: 'default',
|
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 () => {
|
test('Should be able to get strategy by id', async () => {
|
||||||
const featureName = 'get-strategy-by-id';
|
const featureName = 'get-strategy-by-id';
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
|
|
||||||
const userName = 'strategy';
|
|
||||||
const config: Omit<FeatureStrategySchema, 'id'> = {
|
const config: Omit<FeatureStrategySchema, 'id'> = {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
constraints: [],
|
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 () => {
|
test('should ignore name in the body when updating feature flag', async () => {
|
||||||
const featureName = 'body-name-update';
|
const featureName = 'body-name-update';
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
|
|
||||||
const userName = 'strategy';
|
|
||||||
const secondFeatureName = 'body-name-update2';
|
const secondFeatureName = 'body-name-update2';
|
||||||
|
|
||||||
await service.createFeatureToggle(
|
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 () => {
|
test('should not get empty rows as features', async () => {
|
||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
|
|
||||||
const userName = 'strategy';
|
|
||||||
|
|
||||||
await service.createFeatureToggle(
|
await service.createFeatureToggle(
|
||||||
projectId,
|
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 () => {
|
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({
|
const project = await stores.projectStore.create({
|
||||||
id: 'crOnVariantsProject',
|
id: 'crOnVariantsProject',
|
||||||
name: 'crOnVariantsProject',
|
name: 'crOnVariantsProject',
|
||||||
@ -599,7 +589,6 @@ test('getPlaygroundFeatures should return ids and titles (if they exist) on clie
|
|||||||
const projectId = 'default';
|
const projectId = 'default';
|
||||||
|
|
||||||
const title = 'custom strategy title';
|
const title = 'custom strategy title';
|
||||||
const userName = 'strategy';
|
|
||||||
const config: Omit<FeatureStrategySchema, 'id'> = {
|
const config: Omit<FeatureStrategySchema, 'id'> = {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
constraints: [],
|
constraints: [],
|
||||||
@ -819,7 +808,6 @@ test('Should enable disabled strategies on feature environment enabled', async (
|
|||||||
const flagName = 'enableThisFlag';
|
const flagName = 'enableThisFlag';
|
||||||
const project = 'default';
|
const project = 'default';
|
||||||
const environment = 'default';
|
const environment = 'default';
|
||||||
const shouldActivateDisabledStrategies = true;
|
|
||||||
await service.createFeatureToggle(
|
await service.createFeatureToggle(
|
||||||
project,
|
project,
|
||||||
{
|
{
|
||||||
@ -856,7 +844,7 @@ test('Should enable disabled strategies on feature environment enabled', async (
|
|||||||
true,
|
true,
|
||||||
TEST_AUDIT_USER,
|
TEST_AUDIT_USER,
|
||||||
{ email: 'test@example.com' } as User,
|
{ email: 'test@example.com' } as User,
|
||||||
shouldActivateDisabledStrategies,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
const strategy = await service.getStrategy(createdConfig.id);
|
const strategy = await service.getStrategy(createdConfig.id);
|
||||||
|
@ -104,13 +104,11 @@ export class ProjectReadModel implements IProjectReadModel {
|
|||||||
})
|
})
|
||||||
.orderBy('projects.name', 'asc');
|
.orderBy('projects.name', 'asc');
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
if (query?.archived === true) {
|
if (query?.archived === true) {
|
||||||
projects = projects.whereNot(`${TABLE}.archived_at`, null);
|
projects = projects.whereNot(`${TABLE}.archived_at`, null);
|
||||||
} else {
|
} else {
|
||||||
projects = projects.where(`${TABLE}.archived_at`, null);
|
projects = projects.where(`${TABLE}.archived_at`, null);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (query?.id) {
|
if (query?.id) {
|
||||||
projects = projects.where(`${TABLE}.id`, query.id);
|
projects = projects.where(`${TABLE}.id`, query.id);
|
||||||
@ -124,12 +122,9 @@ export class ProjectReadModel implements IProjectReadModel {
|
|||||||
'MAX(events.created_at) AS last_updated',
|
'MAX(events.created_at) AS last_updated',
|
||||||
),
|
),
|
||||||
'project_settings.project_mode',
|
'project_settings.project_mode',
|
||||||
|
'projects.archived_at',
|
||||||
] as (string | Raw<any>)[];
|
] as (string | Raw<any>)[];
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
selectColumns.push(`${TABLE}.archived_at`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let groupByColumns = ['projects.id', 'project_settings.project_mode'];
|
let groupByColumns = ['projects.id', 'project_settings.project_mode'];
|
||||||
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
@ -179,13 +174,11 @@ export class ProjectReadModel implements IProjectReadModel {
|
|||||||
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
|
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
|
||||||
.orderBy('projects.name', 'asc');
|
.orderBy('projects.name', 'asc');
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
if (query?.archived === true) {
|
if (query?.archived === true) {
|
||||||
projects = projects.whereNot(`${TABLE}.archived_at`, null);
|
projects = projects.whereNot(`${TABLE}.archived_at`, null);
|
||||||
} else {
|
} else {
|
||||||
projects = projects.where(`${TABLE}.archived_at`, null);
|
projects = projects.where(`${TABLE}.archived_at`, null);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (query?.id) {
|
if (query?.id) {
|
||||||
projects = projects.where(`${TABLE}.id`, query.id);
|
projects = projects.where(`${TABLE}.id`, 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',
|
'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',
|
'project_stats.avg_time_to_prod_current_window',
|
||||||
|
'projects.archived_at',
|
||||||
] as (string | Raw<any>)[];
|
] as (string | Raw<any>)[];
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
selectColumns.push(`${TABLE}.archived_at`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupByColumns = [
|
const groupByColumns = [
|
||||||
'projects.id',
|
'projects.id',
|
||||||
'project_stats.avg_time_to_prod_current_window',
|
'project_stats.avg_time_to_prod_current_window',
|
||||||
|
@ -83,7 +83,7 @@ beforeAll(async () => {
|
|||||||
const config = createTestConfig({
|
const config = createTestConfig({
|
||||||
getLogger,
|
getLogger,
|
||||||
experimental: {
|
experimental: {
|
||||||
flags: { archiveProjects: true, useProjectReadModel: true },
|
flags: { useProjectReadModel: true },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
eventService = createEventsService(db.rawDatabase, config);
|
eventService = createEventsService(db.rawDatabase, config);
|
||||||
|
@ -500,7 +500,6 @@ export default class ProjectService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async validateActiveProject(projectId: string) {
|
private async validateActiveProject(projectId: string) {
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
const hasActiveProject =
|
const hasActiveProject =
|
||||||
await this.projectStore.hasActiveProject(projectId);
|
await this.projectStore.hasActiveProject(projectId);
|
||||||
if (!hasActiveProject) {
|
if (!hasActiveProject) {
|
||||||
@ -509,7 +508,6 @@ export default class ProjectService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async changeProject(
|
async changeProject(
|
||||||
newProjectId: string,
|
newProjectId: string,
|
||||||
@ -1552,9 +1550,7 @@ export default class ProjectService {
|
|||||||
health: project.health || 0,
|
health: project.health || 0,
|
||||||
favorite: favorite,
|
favorite: favorite,
|
||||||
updatedAt: project.updatedAt,
|
updatedAt: project.updatedAt,
|
||||||
...(this.flagResolver.isEnabled('archiveProjects')
|
archivedAt: project.archivedAt,
|
||||||
? { archivedAt: project.archivedAt }
|
|
||||||
: {}),
|
|
||||||
createdAt: project.createdAt,
|
createdAt: project.createdAt,
|
||||||
onboardingStatus,
|
onboardingStatus,
|
||||||
environments,
|
environments,
|
||||||
|
@ -12,7 +12,7 @@ let environmentStore: IEnvironmentStore;
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('project_store_serial', getLogger, {
|
db = await dbInit('project_store_serial', getLogger, {
|
||||||
experimental: { flags: { archiveProjects: true } },
|
experimental: { flags: {} },
|
||||||
});
|
});
|
||||||
stores = db.stores;
|
stores = db.stores;
|
||||||
projectStore = stores.projectStore;
|
projectStore = stores.projectStore;
|
||||||
|
@ -132,13 +132,11 @@ class ProjectStore implements IProjectStore {
|
|||||||
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
|
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
|
||||||
.orderBy('projects.name', 'asc');
|
.orderBy('projects.name', 'asc');
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
if (query?.archived === true) {
|
if (query?.archived === true) {
|
||||||
projects = projects.whereNot(`${TABLE}.archived_at`, null);
|
projects = projects.whereNot(`${TABLE}.archived_at`, null);
|
||||||
} else {
|
} else {
|
||||||
projects = projects.where(`${TABLE}.archived_at`, null);
|
projects = projects.where(`${TABLE}.archived_at`, null);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (query?.id) {
|
if (query?.id) {
|
||||||
projects = projects.where(`${TABLE}.id`, query.id);
|
projects = projects.where(`${TABLE}.id`, query.id);
|
||||||
@ -154,12 +152,9 @@ class ProjectStore implements IProjectStore {
|
|||||||
'project_settings.default_stickiness',
|
'project_settings.default_stickiness',
|
||||||
'project_settings.project_mode',
|
'project_settings.project_mode',
|
||||||
'project_stats.avg_time_to_prod_current_window',
|
'project_stats.avg_time_to_prod_current_window',
|
||||||
|
'projects.archived_at',
|
||||||
] as (string | Raw<any>)[];
|
] as (string | Raw<any>)[];
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
selectColumns.push(`${TABLE}.archived_at`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let groupByColumns = [
|
let groupByColumns = [
|
||||||
'projects.id',
|
'projects.id',
|
||||||
'project_settings.default_stickiness',
|
'project_settings.default_stickiness',
|
||||||
@ -237,9 +232,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
.where(query)
|
.where(query)
|
||||||
.orderBy('name', 'asc');
|
.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;
|
const rows = await projects;
|
||||||
|
|
||||||
@ -247,10 +240,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async get(id: string): Promise<IProject> {
|
async get(id: string): Promise<IProject> {
|
||||||
let extraColumns: string[] = [];
|
const extraColumns: string[] = ['archived_at'];
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
|
||||||
extraColumns = ['archived_at'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.db
|
return this.db
|
||||||
.first([...COLUMNS, ...SETTINGS_COLUMNS, ...extraColumns])
|
.first([...COLUMNS, ...SETTINGS_COLUMNS, ...extraColumns])
|
||||||
@ -634,8 +624,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
async getApplicationsByProject(
|
async getApplicationsByProject(
|
||||||
params: IProjectApplicationsSearchParams,
|
params: IProjectApplicationsSearchParams,
|
||||||
): Promise<IProjectApplications> {
|
): Promise<IProjectApplications> {
|
||||||
const { project, limit, sortOrder, sortBy, searchParams, offset } =
|
const { project, limit, sortOrder, searchParams, offset } = params;
|
||||||
params;
|
|
||||||
const validatedSortOrder =
|
const validatedSortOrder =
|
||||||
sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : 'asc';
|
sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : 'asc';
|
||||||
const query = this.db
|
const query = this.db
|
||||||
@ -741,9 +730,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
async count(): Promise<number> {
|
async count(): Promise<number> {
|
||||||
let count = this.db.from(TABLE).count('*');
|
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));
|
return count.then((res) => Number(res[0].count));
|
||||||
}
|
}
|
||||||
@ -766,9 +753,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
this.db.raw(`COALESCE(${SETTINGS_TABLE}.project_mode, 'open')`),
|
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;
|
const result: ProjectModeCount[] = await query;
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ export type IFlagKey =
|
|||||||
| 'extendedMetrics'
|
| 'extendedMetrics'
|
||||||
| 'removeUnsafeInlineStyleSrc'
|
| 'removeUnsafeInlineStyleSrc'
|
||||||
| 'originMiddleware'
|
| 'originMiddleware'
|
||||||
| 'archiveProjects'
|
|
||||||
| 'projectListImprovements'
|
| 'projectListImprovements'
|
||||||
| 'useProjectReadModel'
|
| 'useProjectReadModel'
|
||||||
| 'addonUsageMetrics'
|
| 'addonUsageMetrics'
|
||||||
@ -281,10 +280,6 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_ORIGIN_MIDDLEWARE,
|
process.env.UNLEASH_EXPERIMENTAL_ORIGIN_MIDDLEWARE,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
archiveProjects: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_ARCHIVE_PROJECTS,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
projectListImprovements: parseEnvVarBoolean(
|
projectListImprovements: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_PROJECT_LIST_IMPROVEMENTS,
|
process.env.UNLEASH_EXPERIMENTAL_PROJECT_LIST_IMPROVEMENTS,
|
||||||
false,
|
false,
|
||||||
|
Loading…
Reference in New Issue
Block a user