Skip to content

Commit

Permalink
Unify proto JS API for tracker and griffin UI (#1253)
Browse files Browse the repository at this point in the history
The PR reimplements finch_tracker and griffin.brave.com using
`protobuf-ts` instead `protobufjs`
Also it reuses the serializer from seed_tools that will result in
changing the format in finch-data-private
  • Loading branch information
atuchin-m authored Nov 22, 2024
1 parent b2cece5 commit 5c7eb50
Show file tree
Hide file tree
Showing 19 changed files with 543 additions and 1,014 deletions.
542 changes: 0 additions & 542 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
"prettier": "3.3.3",
"prettier-plugin-multiline-arrays": "3.0.6",
"prettier-plugin-organize-imports": "3.2.4",
"protobufjs": "7.4.0",
"protobufjs-cli": "1.1.3",
"style-loader": "3.3.4",
"ts-jest": "29.2.5",
"ts-loader": "9.5.1",
Expand Down
71 changes: 0 additions & 71 deletions src/core/serializers.ts

This file was deleted.

54 changes: 30 additions & 24 deletions src/core/study_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
import { variations as proto } from '../proto/generated/proto_bundle';
import {
Study,
Study_Channel,
Study_Experiment,
Study_Filter,
Study_Platform,
} from '../proto/generated/study';
import { type ProcessingOptions } from './base_types';
import { isFeatureBlocklisted, isStudyNameBlocklisted } from './blocklists';
import { matchesMaxVersion, parseVersionPattern } from './version';

const UPSTREAM_SUPPORTED_PLATFORMS: readonly proto.Study.Platform[] = [
proto.Study.Platform.PLATFORM_ANDROID,
proto.Study.Platform.PLATFORM_LINUX,
proto.Study.Platform.PLATFORM_MAC,
proto.Study.Platform.PLATFORM_WINDOWS,
const UPSTREAM_SUPPORTED_PLATFORMS: readonly Study_Platform[] = [
Study_Platform.ANDROID,
Study_Platform.LINUX,
Study_Platform.MAC,
Study_Platform.WINDOWS,
];

const BRAVE_SUPPORTED_PLATFORMS: readonly proto.Study.Platform[] =
UPSTREAM_SUPPORTED_PLATFORMS.concat([proto.Study.Platform.PLATFORM_IOS]);
const BRAVE_SUPPORTED_PLATFORMS: readonly Study_Platform[] =
UPSTREAM_SUPPORTED_PLATFORMS.concat([Study_Platform.IOS]);

export enum StudyChannelTarget {
// filter.channel includes DEV or CANNERY, doesn't include STABLE or BETA.
Expand Down Expand Up @@ -86,14 +92,14 @@ export class StudyFilter {
}
}

// A wrapper over a raw proto.Study that processes it and collects some extra
// A wrapper over a raw Study that processes it and collects some extra
// data.
export class ProcessedStudy {
study: proto.IStudy;
study: Study;
studyDetails: StudyDetails;
affectedFeatures: Set<string>;

constructor(study: proto.IStudy, options: ProcessingOptions) {
constructor(study: Study, options: ProcessingOptions) {
this.study = study;
this.studyDetails = new StudyDetails(study, options);
this.affectedFeatures = getAffectedFeatures(study);
Expand All @@ -106,7 +112,7 @@ export class ProcessedStudy {

stripEmptyFilterGroups(): void {
this.study.experiment = this.study.experiment?.filter(
(e) => e.probability_weight > 0,
(e) => (e.probability_weight ?? 0) > 0,
);
}

Expand Down Expand Up @@ -172,7 +178,7 @@ export class StudyDetails {
maxNonDefaultIndex = -1;
channelTarget = StudyChannelTarget.DEV_OR_CANARY;

constructor(study: proto.IStudy, options: ProcessingOptions) {
constructor(study: Study, options: ProcessingOptions) {
const filter = study.filter;
const experiment = study.experiment;
const maxVersion = filter?.max_version;
Expand Down Expand Up @@ -202,7 +208,7 @@ export class StudyDetails {
endDateSeconds = filter.end_date;
} else {
// Long
endDateSeconds = filter.end_date.toNumber();
endDateSeconds = Number(filter.end_date);
}

if (
Expand All @@ -227,7 +233,8 @@ export class StudyDetails {
this.isBlocklisted ||=
disabledFeatures?.some((n) => isFeatureBlocklisted(n)) ?? false;

this.isKillSwitch ||= e.probability_weight > 0 && isKillSwitch(e.name);
this.isKillSwitch ||=
(e.probability_weight ?? 0) > 0 && isKillSwitch(e.name);

this.onlyDisabledFeatures &&=
e.probability_weight === 0 ||
Expand All @@ -242,7 +249,7 @@ export class StudyDetails {

let index = 0;
for (const e of experiment) {
const weight = e.probability_weight;
const weight = e.probability_weight ?? 0;
this.totalWeight += weight;
if (
!e.name.startsWith('Default') &&
Expand All @@ -259,9 +266,9 @@ export class StudyDetails {
}

const channel = study.filter?.channel;
if (channel?.includes(proto.Study.Channel.BETA))
if (channel?.includes(Study_Channel.BETA))
this.channelTarget = StudyChannelTarget.BETA;
if (channel?.includes(proto.Study.Channel.STABLE))
if (channel?.includes(Study_Channel.STABLE))
this.channelTarget = StudyChannelTarget.STABLE;
}

Expand Down Expand Up @@ -293,7 +300,7 @@ export class StudyDetails {
}
}

function getAffectedFeatures(study: proto.IStudy): Set<string> {
function getAffectedFeatures(study: Study): Set<string> {
const features = new Set<string>();
const experiment = study.experiment;
if (experiment == null) {
Expand All @@ -306,7 +313,7 @@ function getAffectedFeatures(study: proto.IStudy): Set<string> {
return features;
}

function areFeaturesInDefaultStates(e: proto.Study.IExperiment): boolean {
function areFeaturesInDefaultStates(e: Study_Experiment): boolean {
const enableFeature = e.feature_association?.enable_feature;
const disableFeature = e.feature_association?.disable_feature;
if (enableFeature != null && enableFeature.length > 0) return false;
Expand All @@ -315,11 +322,10 @@ function areFeaturesInDefaultStates(e: proto.Study.IExperiment): boolean {
}

function filterPlatforms(
f: proto.Study.IFilter | undefined | null,
f: Study_Filter,
isBraveSeed: boolean,
): proto.Study.Platform[] | undefined {
): Study_Platform[] {
const platform = f?.platform;
if (platform == null) return undefined;
const supportedPlatforms = isBraveSeed
? BRAVE_SUPPORTED_PLATFORMS
: UPSTREAM_SUPPORTED_PLATFORMS;
Expand All @@ -328,7 +334,7 @@ function filterPlatforms(

// Processes a list of studies and groups it according to study.name.
export function processStudyList(
list: proto.IStudy[],
list: Study[],
minPriority: StudyPriority,
options: ProcessingOptions,
): Map<string, ProcessedStudy[]> {
Expand Down
8 changes: 4 additions & 4 deletions src/core/summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// You can obtain one at https://mozilla.org/MPL/2.0/.
import { createHash } from 'node:crypto';

import { type variations as proto } from '../proto/generated/proto_bundle';
import { SeedType, type ProcessingOptions } from './base_types';
import {
StudyPriority,
Expand All @@ -14,6 +13,7 @@ import {
} from './study_processor';

import * as config from '../config';
import { VariationsSeed } from '../proto/generated/variations_seed';
import * as url_utils from './url_utils';

export enum ItemAction {
Expand Down Expand Up @@ -115,8 +115,8 @@ function getOverallAudience(
}

export function makeSummary(
oldSeed: proto.VariationsSeed,
newSeed: proto.VariationsSeed,
oldSeed: VariationsSeed,
newSeed: VariationsSeed,
options: ProcessingOptions,
minPriority: StudyPriority,
): Map<StudyPriority, SummaryItem[]> {
Expand Down Expand Up @@ -215,7 +215,7 @@ function getGitHubDiffUrl(
oldPriority: StudyPriority,
commit: string,
): string {
const path = `study/all-by-name/${study}`;
const path = `study/all-by-name/${study}.json5`;
const pathHash = sha256(path);
return `${url_utils.getGitHubStorageUrl()}/commit/${commit}#diff-${pathHash}`;
}
Expand Down
10 changes: 6 additions & 4 deletions src/core/url_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ export function getStudyRawConfigUrl(
study: string,
seedType: SeedType,
): string {
if (seedType === SeedType.UPSTREAM)
return `${getGitHubStorageUrl()}/blob/main/study/all-by-name/${study}`;
if (seedType === SeedType.UPSTREAM) {
return (
getGitHubStorageUrl() + `/blob/main/study/all-by-name/${study}.json5`
);
}
return (
'https://github.com/search?type=code' +
'&q=repo%3Abrave%2Fbrave-variations' +
'+path%3A%2F%5Eseed%5C%2Fseed.json%7C%5Estudies%5C%2F*.json5%2F+' +
`"%5C"name%5C"%3A+%5C"${encodeURIComponent(study)}%5C""`
`+path%3Astudies%2F+%22name%3A+%27${encodeURIComponent(study)}%27%22`
);
}

Expand Down
8 changes: 4 additions & 4 deletions src/finch_tracker/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { type ProcessingOptions } from '../core/base_types';
import { StudyPriority } from '../core/study_processor';
import { makeSummary, summaryToJson } from '../core/summary';
import * as url_utils from '../core/url_utils';
import { variations as proto } from '../proto/generated/proto_bundle';
import { VariationsSeed } from '../proto/generated/variations_seed';
import { downloadUrl, getSeedPath } from './node_utils';
import {
commitAllChanges,
Expand Down Expand Up @@ -86,7 +86,7 @@ async function main(): Promise<void> {
seedFile !== undefined
? fs.readFileSync(seedFile)
: await fetchChromeSeedData();
const seed = proto.VariationsSeed.decode(seedData);
const seed = VariationsSeed.fromBinary(seedData);
let previousSeedData: Buffer | undefined;
let newGitSha1: string | undefined;

Expand All @@ -98,14 +98,14 @@ async function main(): Promise<void> {
}

if (updateData) {
storeDataToDirectory(seedData, storageDir, options);
await storeDataToDirectory(seedData, storageDir, options);
if (commitData) {
newGitSha1 = commitAllChanges(storageDir);
}
}

if (createSummary && previousSeedData !== undefined) {
const previousSeed = proto.VariationsSeed.decode(previousSeedData);
const previousSeed = VariationsSeed.fromBinary(previousSeedData);
const summary = makeSummary(
previousSeed,
seed,
Expand Down
Loading

0 comments on commit 5c7eb50

Please sign in to comment.