Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Gitar] Cleaning up stale flag: archiveProjects with value true #8201

Merged
merged 4 commits into from
Sep 23, 2024
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
4 changes: 1 addition & 3 deletions frontend/src/component/project/Project/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -192,7 +190,7 @@ export const Project = () => {
</Box>
);

if (archiveProjectsEnabled && Boolean(project.archivedAt)) {
if (project.archivedAt) {
return <ProjectArchived name={project.name} />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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;
Expand All @@ -52,19 +49,7 @@ const EditProject = () => {
condition={isEnterprise()}
show={<UpdateEnterpriseSettings project={project} />}
/>
<ConditionallyRender
condition={archiveProjectsEnabled}
show={
<ArchiveProjectForm
featureCount={featuresCount(project)}
/>
}
elseShow={
<DeleteProjectForm
featureCount={featuresCount(project)}
/>
}
/>
<ArchiveProjectForm featureCount={featuresCount(project)} />
</StyledFormContainer>
</>
);
Expand Down
25 changes: 9 additions & 16 deletions frontend/src/component/project/ProjectList/LegacyProjectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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 || []);

Expand Down Expand Up @@ -200,20 +198,15 @@ export const ProjectList = () => {
</>
}
/>
<ConditionallyRender
condition={Boolean(archiveProjectsEnabled)}
show={
<>
<Link
component={RouterLink}
to='/projects-archive'
>
Archived projects
</Link>
<PageHeader.Divider />
</>
}
/>
<>
<Link
component={RouterLink}
to='/projects-archive'
>
Archived projects
</Link>
<PageHeader.Divider />
</>

<ProjectCreationButton />
</>
Expand Down
6 changes: 1 addition & 5 deletions frontend/src/component/project/ProjectList/ProjectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 || []);

Expand Down Expand Up @@ -78,10 +77,7 @@ const NewProjectList = () => {
}
/>

<ConditionallyRender
condition={Boolean(archiveProjectsEnabled)}
show={<ProjectArchiveLink />}
/>
<ProjectArchiveLink />
<ProjectCreationButton
isDialogOpen={Boolean(state.create)}
setIsDialogOpen={(create) =>
Expand Down
1 change: 0 additions & 1 deletion frontend/src/interfaces/uiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ export type UiFlags = {
enableLegacyVariants?: boolean;
navigationSidebar?: boolean;
flagCreator?: boolean;
archiveProjects?: boolean;
projectListImprovements?: boolean;
onboardingUI?: boolean;
eventTimeline?: boolean;
Expand Down
22 changes: 8 additions & 14 deletions src/lib/features/feature-toggle/feature-toggle-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
);
}
}

Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand All @@ -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',
Expand All @@ -77,7 +76,6 @@ beforeEach(async () => {
});
test('Should create feature flag strategy configuration', async () => {
const projectId = 'default';
const username = 'feature-flag';
const config: Omit<FeatureStrategySchema, 'id'> = {
name: 'default',
constraints: [],
Expand All @@ -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<FeatureStrategySchema, 'id'> = {
name: 'default',
Expand Down Expand Up @@ -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<FeatureStrategySchema, 'id'> = {
name: 'default',
constraints: [],
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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,
{
Expand Down Expand Up @@ -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: '[email protected]', username: 'test-user' } as User;
const project = await stores.projectStore.create({
id: 'crOnVariantsProject',
name: 'crOnVariantsProject',
Expand Down Expand Up @@ -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<FeatureStrategySchema, 'id'> = {
name: 'default',
constraints: [],
Expand Down Expand Up @@ -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,
{
Expand Down Expand Up @@ -856,7 +844,7 @@ test('Should enable disabled strategies on feature environment enabled', async (
true,
TEST_AUDIT_USER,
{ email: '[email protected]' } as User,
shouldActivateDisabledStrategies,
true,
);

const strategy = await service.getStrategy(createdConfig.id);
Expand Down
30 changes: 10 additions & 20 deletions src/lib/features/project/project-read-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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<any>)[];

if (this.flagResolver.isEnabled('archiveProjects')) {
selectColumns.push(`${TABLE}.archived_at`);
}

let groupByColumns = ['projects.id', 'project_settings.project_mode'];

if (userId) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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<any>)[];

if (this.flagResolver.isEnabled('archiveProjects')) {
selectColumns.push(`${TABLE}.archived_at`);
}

const groupByColumns = [
'projects.id',
'project_stats.avg_time_to_prod_current_window',
Expand Down
2 changes: 1 addition & 1 deletion src/lib/features/project/project-service.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ beforeAll(async () => {
const config = createTestConfig({
getLogger,
experimental: {
flags: { archiveProjects: true, useProjectReadModel: true },
flags: { useProjectReadModel: true },
},
});
eventService = createEventsService(db.rawDatabase, config);
Expand Down
18 changes: 7 additions & 11 deletions src/lib/features/project/project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,14 +500,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`,
);
}
}

Expand Down Expand Up @@ -1552,9 +1550,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,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/features/project/project-store.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading