Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/settings.py b/settings.py
index 0759364..1d08454 100644
--- a/settings.py
+++ b/settings.py
@@ -1,7 +1,6 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 """Defines settings for the avm99963 bugs monorail instance."""
 from __future__ import print_function
@@ -9,13 +8,13 @@
 from __future__ import absolute_import
 
 import os
-import re
+import six
 
 from google.appengine.api import app_identity
 
 from framework import framework_constants
-from proto import project_pb2
-from proto import site_pb2
+from mrproto import project_pb2
+from mrproto import site_pb2
 
 
 # This file is divided into the following parts:
@@ -172,8 +171,8 @@
 
 # local_mode makes the server slower and more dynamic for easier debugging.
 # E.g., template files are reloaded on each request.
-local_mode = os.environ['SERVER_SOFTWARE'].startswith('Development')
 unit_test_mode = os.environ['SERVER_SOFTWARE'].startswith('test')
+local_mode = not (os.getenv('GAE_ENV') == 'standard' or unit_test_mode)
 
 # If we assume 1KB each, then this would be 400 MB for this cache in frontends
 # that have only 1024 MB total.
@@ -286,8 +285,14 @@
 ####
 # Part 5:  Instance-specific settings that override lines above.
 # This ID is for -staging and other misc deployments. Prod is defined below.
+
+# IDs of the project for which label freezing should happen
+label_freeze_project_ids = set()
 analytics_id = ''
 
+# Project IDs which have opted into freezing project configs.
+config_freeze_project_ids = set()
+
 if unit_test_mode:
   db_cloud_project = ''  # No real database is used during unit testing.
   app_id = ''
@@ -302,6 +307,10 @@
     branded_domains = branded_domains_prod
     domain_to_default_project = domain_to_default_project_prod
 
+    label_freeze_project_ids = {}
+    config_freeze_project_ids = {}
+    config_freeze_override_users = {}
+
   elif app_id == 'monorail-staging':
     site_name = 'Monorail Staging'
     banner_message = 'This staging site does not send emails.'
@@ -310,6 +319,16 @@
     branded_domains = branded_domains_staging
     domain_to_default_project = domain_to_default_project_staging
 
+    label_freeze_project_ids = {16}
+    config_freeze_project_ids = {16}
+    config_freeze_override_users = {
+        16:
+            {
+                'benhenry@google.com', 'zhangtiff@google.com',
+                'summermcdonald@google.com', 'example@example.com'
+            }
+    }
+
   elif app_id == 'monorail-dev':
     site_name = 'Monorail Dev'
     banner_message = 'This dev site does not send emails.'
@@ -320,6 +339,17 @@
     # Use replicas created when testing the restore procedures on 2021-02-24
     db_replica_prefix = 'replica-2'
 
+    label_freeze_project_ids = {16, 36}
+    config_freeze_project_ids = {16, 36}
+    config_freeze_override_users = {
+        16:
+            {
+                'benhenry@google.com', 'zhangtiff@google.com',
+                'summermcdonald@google.com', 'example@example.com'
+            },
+        36: {'viccontreras@google.com', 'nmulcahey@google.com'}
+    }
+
 if local_mode:
   site_name = 'Monorail Local'
   num_logical_shards = 10
@@ -348,7 +378,7 @@
 classifier_project_id = 'project-id-testing-only'
 
 # Necessary for tests.
-if 'APPLICATION_ID' not in os.environ:
+if six.PY2 and 'APPLICATION_ID' not in os.environ:
   os.environ['APPLICATION_ID'] = 'testing-app'
 
 if local_mode:
@@ -428,7 +458,7 @@
 # domain name.  E.g., 'monorail@bugs.chromium.org'.
 date_action_ping_author = 'monorail'
 
-# Hard-coding this so that we don't rely on sys.maxint, which could
+# Hard-coding this so that we don't rely on sys.maxsize, which could
 # potentially differ. It is equal to the maximum unsigned 32 bit integer,
 # because the `int(10) unsigned` column type in MySQL is 32 bits.
 maximum_snapshot_period_end = 4294967295
@@ -454,3 +484,32 @@
 # All users in the following domains will have API access.
 # Important: the @ symbol must be included.
 api_allowed_email_domains = ('@avm99963.com', '@avm99963-bugs.iam.gserviceaccount.com')
+
+label_prefix_allowlist = [
+    'CVE-',
+    'reward_to-',
+    'merge-merge-',
+    'migrated-to-b-',
+    'copybara-migration-complete-',
+    'cob-migrated-to-b-',
+    'incident-id-',
+    'version-',
+    'copybara-migrate-c-',
+    'reward-',
+    'b-',
+]
+
+
+def is_label_allowed(project_id, label):
+  # Only allowlist label prefixes for 'Chromium' project.
+  if project_id == 16:
+    return any(label.startswith(prefix) for prefix in label_prefix_allowlist)
+
+
+# This list should stay in sync with MIGRATED_BUGANIZER_ISSUE_PREFIXES in
+# `appengine/monorail/static_src/reducers/issueV0.js`.
+migrated_buganizer_issue_prefixes = [
+    'migrated-to-b-',
+    'copybara-migration-complete-',
+    'cob-migrated-to-b-',
+]