├── .babelrc ├── .coveragerc ├── .devcontainer ├── Dockerfile ├── README.md ├── db-docker-compose.yml ├── devcontainer.json ├── docker-compose.yml └── post_attach.sh ├── .dockerignore ├── .editorconfig ├── .gcloudignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── process-and-guide-ux-feedback.md ├── dependabot.yml └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ ├── playwright.yml │ ├── scorecards.yml │ └── web_tests.yml ├── .gitignore ├── .prettierrc.js ├── .vscode ├── extensions.json └── launch.json ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── LICENSE ├── README.md ├── api ├── __init__.py ├── accounts_api.py ├── accounts_api_test.py ├── api_specs.py ├── attachments_api.py ├── attachments_api_test.py ├── blink_components_api.py ├── blink_components_api_test.py ├── channels_api.py ├── channels_api_test.py ├── comments_api.py ├── comments_api_test.py ├── component_users.py ├── component_users_test.py ├── components_users.py ├── components_users_test.py ├── converters.py ├── converters_test.py ├── cues_api.py ├── cues_api_test.py ├── external_reviews_api.py ├── external_reviews_api_test.py ├── feature_latency_api.py ├── feature_latency_api_test.py ├── feature_links_api.py ├── features_api.py ├── features_api_test.py ├── intents_api.py ├── intents_api_test.py ├── legacy_converters.py ├── login_api.py ├── login_api_test.py ├── logout_api.py ├── logout_api_test.py ├── metricsdata.py ├── metricsdata_test.py ├── origin_trials_api.py ├── origin_trials_api_test.py ├── permissions_api.py ├── permissions_api_test.py ├── processes_api.py ├── processes_api_test.py ├── review_latency_api.py ├── review_latency_api_test.py ├── reviews_api.py ├── reviews_api_test.py ├── settings_api.py ├── settings_api_test.py ├── shipping_features_api.py ├── shipping_features_api_test.py ├── spec_mentors_api.py ├── spec_mentors_api_test.py ├── stages_api.py ├── stages_api_test.py ├── stale_features_api.py ├── stale_features_api_test.py ├── stars_api.py ├── stars_api_test.py ├── token_refresh_api.py ├── token_refresh_api_test.py ├── webdx_feature_api.py └── webdx_feature_api_test.py ├── app.staging.yaml ├── app.yaml ├── appengine_config.py ├── client-src ├── components.js ├── css │ ├── _flexbox-css.js │ ├── _layout-css.js │ ├── _reset-css.js │ ├── _vars-css.js │ ├── elements │ │ └── chromedash-roadmap-milestone-card-css.js │ ├── forms-css.js │ └── shared-css.js ├── elements │ ├── autolink.ts │ ├── chromeash-stale-features-page_test.ts │ ├── chromedash-activity-log.ts │ ├── chromedash-activity-log_test.ts │ ├── chromedash-activity-page.ts │ ├── chromedash-activity-page_test.ts │ ├── chromedash-add-stage-dialog.ts │ ├── chromedash-admin-blink-component-listing.ts │ ├── chromedash-admin-blink-component-listing_test.ts │ ├── chromedash-admin-blink-page.ts │ ├── chromedash-admin-blink-page_test.ts │ ├── chromedash-admin-feature-links-page.ts │ ├── chromedash-all-features-page.ts │ ├── chromedash-all-features-page_test.ts │ ├── chromedash-app.ts │ ├── chromedash-attachments.ts │ ├── chromedash-attachments_test.ts │ ├── chromedash-banner.ts │ ├── chromedash-bulk-edit-page.ts │ ├── chromedash-bulk-edit-page_test.ts │ ├── chromedash-callout.ts │ ├── chromedash-continuity-id-dialog.ts │ ├── chromedash-continuity-id-dialog_test.ts │ ├── chromedash-drawer.ts │ ├── chromedash-drawer_test.ts │ ├── chromedash-enterprise-page.ts │ ├── chromedash-enterprise-page_test.ts │ ├── chromedash-enterprise-release-notes-page.ts │ ├── chromedash-enterprise-release-notes-page_test.ts │ ├── chromedash-feature-detail.ts │ ├── chromedash-feature-detail_test.ts │ ├── chromedash-feature-filter.ts │ ├── chromedash-feature-highlights.ts │ ├── chromedash-feature-page.ts │ ├── chromedash-feature-page_test.ts │ ├── chromedash-feature-pagination.ts │ ├── chromedash-feature-pagination_test.ts │ ├── chromedash-feature-row.ts │ ├── chromedash-feature-table.ts │ ├── chromedash-footer.ts │ ├── chromedash-footer_test.ts │ ├── chromedash-form-field.ts │ ├── chromedash-form-field_test.ts │ ├── chromedash-form-table.ts │ ├── chromedash-form-table_test.ts │ ├── chromedash-gantt.ts │ ├── chromedash-gantt_test.ts │ ├── chromedash-gate-chip.ts │ ├── chromedash-gate-column.ts │ ├── chromedash-gate-column_test.ts │ ├── chromedash-guide-editall-page.ts │ ├── chromedash-guide-editall-page_test.ts │ ├── chromedash-guide-metadata-page.ts │ ├── chromedash-guide-new-page.ts │ ├── chromedash-guide-new-page_test.ts │ ├── chromedash-guide-stage-page.ts │ ├── chromedash-guide-stage-page_test.ts │ ├── chromedash-guide-verify-accuracy-page.ts │ ├── chromedash-guide-verify-accuracy-page_test.ts │ ├── chromedash-header.ts │ ├── chromedash-header_test.ts │ ├── chromedash-intent-content.ts │ ├── chromedash-intent-preview-page.ts │ ├── chromedash-intent-template_test.ts │ ├── chromedash-link.ts │ ├── chromedash-link_test.ts │ ├── chromedash-login-required-page.ts │ ├── chromedash-metadata.ts │ ├── chromedash-myfeatures-page.ts │ ├── chromedash-myfeatures-page_test.ts │ ├── chromedash-na-rationale-dialog.ts │ ├── chromedash-ot-creation-page.ts │ ├── chromedash-ot-extension-page.ts │ ├── chromedash-ot-prereqs-dialog.ts │ ├── chromedash-post-intent-dialog.ts │ ├── chromedash-preflight-dialog.ts │ ├── chromedash-preflight-dialog_test.ts │ ├── chromedash-prevote-dialog.ts │ ├── chromedash-prevote-dialog_test.ts │ ├── chromedash-report-external-reviews-dispatch-page.ts │ ├── chromedash-report-external-reviews-page.ts │ ├── chromedash-report-feature-latency-page.ts │ ├── chromedash-report-review-latency-page.ts │ ├── chromedash-report-spec-mentor.ts │ ├── chromedash-report-spec-mentors-page.ts │ ├── chromedash-review-status-icon.ts │ ├── chromedash-review-status-icon_test.ts │ ├── chromedash-roadmap-help-dialog.ts │ ├── chromedash-roadmap-milestone-card.ts │ ├── chromedash-roadmap-milestone-card_test.ts │ ├── chromedash-roadmap-page.ts │ ├── chromedash-roadmap-page_test.ts │ ├── chromedash-roadmap.ts │ ├── chromedash-search-help-dialog.ts │ ├── chromedash-self-certify-dialog.ts │ ├── chromedash-settings-page.ts │ ├── chromedash-settings-page_test.ts │ ├── chromedash-stack-rank-page.ts │ ├── chromedash-stack-rank-page_test.ts │ ├── chromedash-stack-rank.ts │ ├── chromedash-stale-features-page.ts │ ├── chromedash-survey-questions.ts │ ├── chromedash-survey-questions_test.ts │ ├── chromedash-textarea.ts │ ├── chromedash-textarea_test.ts │ ├── chromedash-timeline-page.ts │ ├── chromedash-timeline-page_test.ts │ ├── chromedash-timeline.ts │ ├── chromedash-toast.ts │ ├── chromedash-typeahead.ts │ ├── chromedash-typeahead_test.ts │ ├── chromedash-userlist.ts │ ├── chromedash-vendor-views.ts │ ├── chromedash-vendor-views_test.ts │ ├── chromedash-x-meter.ts │ ├── external-reviewers.ts │ ├── form-definition.ts │ ├── form-field-enums.ts │ ├── form-field-specs.ts │ ├── gate-details.ts │ ├── queriable-fields.ts │ ├── utils.ts │ └── utils_test.ts └── js-src │ ├── cs-client.js │ ├── metric.js │ ├── openapi-client.js │ ├── openapi-client_test.js │ ├── shared.js │ └── types.d.ts ├── config.rb ├── cron.yaml ├── data └── devrel_team.yaml ├── developer-documentation.md ├── dispatch.yaml ├── eslint.config.js ├── framework ├── __init__.py ├── basehandlers.py ├── basehandlers_test.py ├── cloud_tasks_helpers.py ├── cloud_tasks_helpers_test.py ├── constants.py ├── csp.py ├── csp_test.py ├── gemini_client.py ├── gemini_client_test.py ├── origin_trials_client.py ├── origin_trials_client_test.py ├── permissions.py ├── permissions_test.py ├── rediscache.py ├── rediscache_test.py ├── secrets.py ├── secrets_test.py ├── sendemail.py ├── sendemail_test.py ├── users.py ├── users_test.py ├── utils.py ├── utils_test.py ├── xsrf.py └── xsrf_test.py ├── gen ├── js │ └── chromestatus-openapi │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── .openapi-generator-ignore │ │ ├── .openapi-generator │ │ ├── FILES │ │ └── VERSION │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ ├── apis │ │ │ ├── DefaultApi.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── AccountResponse.ts │ │ │ ├── Action.ts │ │ │ ├── Activity.ts │ │ │ ├── AddAttachmentResponse.ts │ │ │ ├── Amendment.ts │ │ │ ├── ArrayFieldInfoValue.ts │ │ │ ├── BooleanFieldInfoValue.ts │ │ │ ├── CommentsRequest.ts │ │ │ ├── ComponentUsersRequest.ts │ │ │ ├── ComponentsUser.ts │ │ │ ├── ComponentsUsersResponse.ts │ │ │ ├── CounterEntry.ts │ │ │ ├── CreateAccountRequest.ts │ │ │ ├── CreateLaunchIssueRequest.ts │ │ │ ├── CreateOriginTrialRequest.ts │ │ │ ├── DeleteAccount200Response.ts │ │ │ ├── DismissCueRequest.ts │ │ │ ├── ErrorMessage.ts │ │ │ ├── ExternalReviewsResponse.ts │ │ │ ├── FeatureLatency.ts │ │ │ ├── FeatureLink.ts │ │ │ ├── FeatureLinksResponse.ts │ │ │ ├── FeatureLinksSample.ts │ │ │ ├── FeatureLinksSummaryResponse.ts │ │ │ ├── FieldInfo.ts │ │ │ ├── Gate.ts │ │ │ ├── GateInfo.ts │ │ │ ├── GateLatency.ts │ │ │ ├── GetCommentsResponse.ts │ │ │ ├── GetDismissedCues400Response.ts │ │ │ ├── GetGateResponse.ts │ │ │ ├── GetIntentResponse.ts │ │ │ ├── GetOriginTrialsResponse.ts │ │ │ ├── GetSettingsResponse.ts │ │ │ ├── GetStarsResponse.ts │ │ │ ├── GetVotesResponse.ts │ │ │ ├── IntegerFieldInfoValue.ts │ │ │ ├── LinkPreview.ts │ │ │ ├── LinkPreviewBase.ts │ │ │ ├── LinkPreviewGithubIssue.ts │ │ │ ├── LinkPreviewGithubIssueAllOfInformation.ts │ │ │ ├── LinkPreviewGithubMarkdown.ts │ │ │ ├── LinkPreviewGithubMarkdownAllOfInformation.ts │ │ │ ├── LinkPreviewGithubPullRequest.ts │ │ │ ├── LinkPreviewGoogleDocs.ts │ │ │ ├── LinkPreviewMdnDocs.ts │ │ │ ├── LinkPreviewMozillaBug.ts │ │ │ ├── LinkPreviewOpenGraph.ts │ │ │ ├── LinkPreviewOpenGraphAllOfInformation.ts │ │ │ ├── LinkPreviewSpecs.ts │ │ │ ├── LinkPreviewWebkitBug.ts │ │ │ ├── MessageResponse.ts │ │ │ ├── MilestoneSetField.ts │ │ │ ├── OriginTrialsInfo.ts │ │ │ ├── OutstandingReview.ts │ │ │ ├── OwnersAndSubscribersOfComponent.ts │ │ │ ├── PatchCommentRequest.ts │ │ │ ├── PatchGateRequest.ts │ │ │ ├── PermissionsResponse.ts │ │ │ ├── PostIntentRequest.ts │ │ │ ├── PostSettingsRequest.ts │ │ │ ├── PostStarsRequest.ts │ │ │ ├── PostVoteRequest.ts │ │ │ ├── Process.ts │ │ │ ├── ProcessStage.ts │ │ │ ├── ProgressItem.ts │ │ │ ├── RejectUnneededGetRequest.ts │ │ │ ├── ReviewLatency.ts │ │ │ ├── SetStarRequest.ts │ │ │ ├── SignInRequest.ts │ │ │ ├── SpecMentor.ts │ │ │ ├── StageField.ts │ │ │ ├── StringFieldInfoValue.ts │ │ │ ├── SuccessMessage.ts │ │ │ ├── SurveyAnswers.ts │ │ │ ├── TokenRefreshResponse.ts │ │ │ ├── UserPermissions.ts │ │ │ ├── VerifyContinuityIssueResponse.ts │ │ │ ├── Vote.ts │ │ │ └── index.ts │ │ └── runtime.ts │ │ ├── tsconfig.esm.json │ │ └── tsconfig.json └── py │ ├── chromestatus_openapi │ ├── .dockerignore │ ├── .gitignore │ ├── .openapi-generator-ignore │ ├── .openapi-generator │ │ ├── FILES │ │ └── VERSION │ ├── .travis.yml │ ├── Dockerfile │ ├── README.md │ ├── chromestatus_openapi │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── controllers │ │ │ ├── __init__.py │ │ │ ├── default_controller.py │ │ │ └── security_controller.py │ │ ├── encoder.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── account_response.py │ │ │ ├── action.py │ │ │ ├── activity.py │ │ │ ├── add_attachment_response.py │ │ │ ├── amendment.py │ │ │ ├── array_field_info_value.py │ │ │ ├── base_model.py │ │ │ ├── boolean_field_info_value.py │ │ │ ├── comments_request.py │ │ │ ├── component_users_request.py │ │ │ ├── components_user.py │ │ │ ├── components_users_response.py │ │ │ ├── counter_entry.py │ │ │ ├── create_account_request.py │ │ │ ├── create_launch_issue_request.py │ │ │ ├── create_origin_trial_request.py │ │ │ ├── delete_account200_response.py │ │ │ ├── dismiss_cue_request.py │ │ │ ├── error_message.py │ │ │ ├── external_reviews_response.py │ │ │ ├── feature_latency.py │ │ │ ├── feature_link.py │ │ │ ├── feature_links_response.py │ │ │ ├── feature_links_sample.py │ │ │ ├── feature_links_summary_response.py │ │ │ ├── field_info.py │ │ │ ├── gate.py │ │ │ ├── gate_info.py │ │ │ ├── gate_latency.py │ │ │ ├── get_comments_response.py │ │ │ ├── get_dismissed_cues400_response.py │ │ │ ├── get_gate_response.py │ │ │ ├── get_intent_response.py │ │ │ ├── get_origin_trials_response.py │ │ │ ├── get_settings_response.py │ │ │ ├── get_stars_response.py │ │ │ ├── get_votes_response.py │ │ │ ├── integer_field_info_value.py │ │ │ ├── link_preview.py │ │ │ ├── link_preview_base.py │ │ │ ├── link_preview_github_issue.py │ │ │ ├── link_preview_github_issue_all_of_information.py │ │ │ ├── link_preview_github_markdown.py │ │ │ ├── link_preview_github_markdown_all_of_information.py │ │ │ ├── link_preview_github_pull_request.py │ │ │ ├── link_preview_google_docs.py │ │ │ ├── link_preview_mdn_docs.py │ │ │ ├── link_preview_mozilla_bug.py │ │ │ ├── link_preview_open_graph.py │ │ │ ├── link_preview_open_graph_all_of_information.py │ │ │ ├── link_preview_specs.py │ │ │ ├── link_preview_webkit_bug.py │ │ │ ├── message_response.py │ │ │ ├── milestone_set_field.py │ │ │ ├── origin_trials_info.py │ │ │ ├── outstanding_review.py │ │ │ ├── owners_and_subscribers_of_component.py │ │ │ ├── patch_comment_request.py │ │ │ ├── patch_gate_request.py │ │ │ ├── permissions_response.py │ │ │ ├── post_intent_request.py │ │ │ ├── post_settings_request.py │ │ │ ├── post_stars_request.py │ │ │ ├── post_vote_request.py │ │ │ ├── process.py │ │ │ ├── process_stage.py │ │ │ ├── progress_item.py │ │ │ ├── reject_unneeded_get_request.py │ │ │ ├── review_latency.py │ │ │ ├── set_star_request.py │ │ │ ├── sign_in_request.py │ │ │ ├── spec_mentor.py │ │ │ ├── stage_field.py │ │ │ ├── string_field_info_value.py │ │ │ ├── success_message.py │ │ │ ├── survey_answers.py │ │ │ ├── token_refresh_response.py │ │ │ ├── user_permissions.py │ │ │ ├── verify_continuity_issue_response.py │ │ │ └── vote.py │ │ ├── openapi │ │ │ └── openapi.yaml │ │ ├── test │ │ │ ├── __init__.py │ │ │ └── test_default_controller.py │ │ ├── typing_utils.py │ │ └── util.py │ ├── git_push.sh │ ├── requirements.txt │ ├── setup.py │ ├── test-requirements.txt │ └── tox.ini │ └── webstatus_openapi │ ├── .github │ └── workflows │ │ └── python.yml │ ├── .gitignore │ ├── .gitlab-ci.yml │ ├── .openapi-generator-ignore │ ├── .openapi-generator │ ├── FILES │ └── VERSION │ ├── .travis.yml │ ├── README.md │ ├── docs │ ├── BaselineInfo.md │ ├── BasicErrorModel.md │ ├── BrowserImplementation.md │ ├── BrowserReleaseFeatureMetric.md │ ├── BrowserReleaseFeatureMetricsPage.md │ ├── BrowserUsage.md │ ├── CanIUseInfo.md │ ├── CanIUseItem.md │ ├── ChromiumDailyStatsPage.md │ ├── ChromiumUsageInfo.md │ ├── ChromiumUsageStat.md │ ├── DefaultApi.md │ ├── ExtendedErrorModel.md │ ├── Feature.md │ ├── FeatureMetadata.md │ ├── FeaturePage.md │ ├── FeatureSpecInfo.md │ ├── FeatureWPTSnapshots.md │ ├── GenericUpdatableUniqueModel.md │ ├── PageMetadata.md │ ├── PageMetadataWithTotal.md │ ├── SavedSearch.md │ ├── SavedSearchPage.md │ ├── SavedSearchResponse.md │ ├── SpecLink.md │ ├── SupportedBrowsers.md │ ├── WPTFeatureData.md │ ├── WPTMetricView.md │ ├── WPTRunMetric.md │ └── WPTRunMetricsPage.md │ ├── git_push.sh │ ├── pyproject.toml │ ├── requirements.txt │ ├── setup.cfg │ ├── setup.py │ ├── test-requirements.txt │ ├── test │ ├── __init__.py │ ├── test_baseline_info.py │ ├── test_basic_error_model.py │ ├── test_browser_implementation.py │ ├── test_browser_release_feature_metric.py │ ├── test_browser_release_feature_metrics_page.py │ ├── test_browser_usage.py │ ├── test_can_i_use_info.py │ ├── test_can_i_use_item.py │ ├── test_chromium_daily_stats_page.py │ ├── test_chromium_usage_info.py │ ├── test_chromium_usage_stat.py │ ├── test_default_api.py │ ├── test_extended_error_model.py │ ├── test_feature.py │ ├── test_feature_metadata.py │ ├── test_feature_page.py │ ├── test_feature_spec_info.py │ ├── test_feature_wpt_snapshots.py │ ├── test_generic_updatable_unique_model.py │ ├── test_page_metadata.py │ ├── test_page_metadata_with_total.py │ ├── test_saved_search.py │ ├── test_saved_search_page.py │ ├── test_saved_search_response.py │ ├── test_spec_link.py │ ├── test_supported_browsers.py │ ├── test_wpt_feature_data.py │ ├── test_wpt_metric_view.py │ ├── test_wpt_run_metric.py │ └── test_wpt_run_metrics_page.py │ ├── tox.ini │ ├── webstatus_openapi.egg-info │ ├── PKG-INFO │ ├── SOURCES.txt │ ├── dependency_links.txt │ ├── requires.txt │ └── top_level.txt │ └── webstatus_openapi │ ├── __init__.py │ ├── api │ ├── __init__.py │ └── default_api.py │ ├── api_client.py │ ├── api_response.py │ ├── configuration.py │ ├── exceptions.py │ ├── models │ ├── __init__.py │ ├── baseline_info.py │ ├── basic_error_model.py │ ├── browser_implementation.py │ ├── browser_release_feature_metric.py │ ├── browser_release_feature_metrics_page.py │ ├── browser_usage.py │ ├── can_i_use_info.py │ ├── can_i_use_item.py │ ├── chromium_daily_stats_page.py │ ├── chromium_usage_info.py │ ├── chromium_usage_stat.py │ ├── extended_error_model.py │ ├── feature.py │ ├── feature_metadata.py │ ├── feature_page.py │ ├── feature_spec_info.py │ ├── feature_wpt_snapshots.py │ ├── generic_updatable_unique_model.py │ ├── page_metadata.py │ ├── page_metadata_with_total.py │ ├── saved_search.py │ ├── saved_search_page.py │ ├── saved_search_response.py │ ├── spec_link.py │ ├── supported_browsers.py │ ├── wpt_feature_data.py │ ├── wpt_metric_view.py │ ├── wpt_run_metric.py │ └── wpt_run_metrics_page.py │ ├── py.typed │ └── rest.py ├── gulpfile.babel.js ├── hack_components.py ├── index.yaml ├── internals ├── __init__.py ├── approval_defs.py ├── approval_defs_test.py ├── attachments.py ├── attachments_test.py ├── core_enums.py ├── core_enums_test.py ├── core_models.py ├── data_backup.py ├── data_types.py ├── detect_intent.py ├── detect_intent_test.py ├── enterprise_helpers.py ├── enterprise_helpers_test.py ├── feature_helpers.py ├── feature_helpers_test.py ├── feature_links.py ├── feature_links_test.py ├── fetchchannels.py ├── fetchchannels_test.py ├── fetchmetrics.py ├── fetchmetrics_test.py ├── inactive_users.py ├── inactive_users_test.py ├── link_helpers.py ├── link_helpers_test.py ├── maintenance_scripts.py ├── maintenance_scripts_test.py ├── metrics_models.py ├── notifier.py ├── notifier_helpers.py ├── notifier_helpers_test.py ├── notifier_test.py ├── ot_process_reminders.py ├── ot_process_reminders_test.py ├── processes.py ├── processes_test.py ├── reminders.py ├── reminders_test.py ├── review_models.py ├── review_models_test.py ├── search.py ├── search_fulltext.py ├── search_fulltext_test.py ├── search_queries.py ├── search_queries_test.py ├── search_test.py ├── self_certify.py ├── self_certify_test.py ├── slo.py ├── slo_test.py ├── stage_helpers.py ├── stage_helpers_test.py ├── testdata │ ├── notifier_test │ │ ├── test_format_email_body__new.html │ │ ├── test_format_email_body__update_no_changes.html │ │ ├── test_format_email_body__update_with_changes.html │ │ ├── test_format_email_body__update_with_changes_and_note.html │ │ ├── test_make_activated_email.html │ │ ├── test_make_activation_failed_email.html │ │ ├── test_make_beta_availability_email.html │ │ ├── test_make_creation_approved_email.html │ │ ├── test_make_creation_processed_email.html │ │ ├── test_make_creation_request_failed_email.html │ │ ├── test_make_ending_next_release_email.html │ │ ├── test_make_ending_this_release_email.html │ │ ├── test_make_extended_request_email.html │ │ ├── test_make_extension_approved_email.html │ │ ├── test_make_first_branch_email.html │ │ ├── test_make_intent_email.html │ │ ├── test_make_last_branch_email.html │ │ ├── test_make_ot_process_email.html │ │ └── test_reset_shipping_milestones_email.html │ └── reminders_test │ │ ├── test_build_email_tasks_escalated_feature_accuracy.html │ │ ├── test_build_email_tasks_feature_accuracy.html │ │ ├── test_build_email_tasks_feature_accuracy_enterprise.html │ │ ├── test_build_email_tasks_prepublication.html │ │ ├── test_build_gate_email_tasks__initial_due.html │ │ ├── test_build_gate_email_tasks__initial_overdue.html │ │ ├── test_build_gate_email_tasks__resolution_due.html │ │ └── test_build_gate_email_tasks__resolution_overdue.html ├── user_models.py ├── user_models_test.py ├── webdx_feature_models.py └── webdx_feature_models_test.py ├── main.py ├── main_test.py ├── notifier.staging.yaml ├── notifier.yaml ├── openapi-documentation.md ├── openapi ├── api.yaml └── js-config.yaml ├── openapitools.json ├── package-lock.json ├── package.json ├── packages └── playwright │ ├── .dockerignore │ ├── Dockerfile │ ├── docker-compose.yml │ ├── get-npm-package-version.sh │ ├── tests │ ├── __screenshots__ │ │ ├── chromedash-guide-editall-page_pwtest.js │ │ │ ├── editall-page │ │ │ │ ├── edit-all-fields-chromium-linux.png │ │ │ │ ├── edit-all-fields-chromium-mobile-linux.png │ │ │ │ ├── edit-all-fields-firefox-linux.png │ │ │ │ └── edit-all-fields-firefox-mobile-linux.png │ │ │ └── test-semantic-checks │ │ │ │ ├── shipped-desktop-error-chromium-linux.png │ │ │ │ ├── shipped-desktop-error-chromium-mobile-linux.png │ │ │ │ ├── shipped-desktop-error-firefox-linux.png │ │ │ │ └── shipped-desktop-error-firefox-mobile-linux.png │ │ ├── chromedash-guide-feature-page_pwtest.js │ │ │ └── add-an-origin-trial-stage │ │ │ │ ├── create-origin-trial-stage-dialog-chromium-linux.png │ │ │ │ ├── create-origin-trial-stage-dialog-chromium-mobile-linux.png │ │ │ │ ├── create-origin-trial-stage-dialog-firefox-linux.png │ │ │ │ ├── create-origin-trial-stage-dialog-firefox-mobile-linux.png │ │ │ │ ├── origin-trial-panels-chromium-linux.png │ │ │ │ ├── origin-trial-panels-chromium-mobile-linux.png │ │ │ │ ├── origin-trial-panels-firefox-linux.png │ │ │ │ └── origin-trial-panels-firefox-mobile-linux.png │ │ ├── chromedash-guide-new-page_pwtest.js │ │ │ ├── create-new-feature │ │ │ │ ├── new-feature-created-chromium-linux.png │ │ │ │ ├── new-feature-created-chromium-mobile-linux.png │ │ │ │ ├── new-feature-created-firefox-linux.png │ │ │ │ └── new-feature-created-firefox-mobile-linux.png │ │ │ ├── enter-blink-component │ │ │ │ ├── blink-components-chromium-linux.png │ │ │ │ ├── blink-components-chromium-mobile-linux.png │ │ │ │ ├── blink-components-firefox-linux.png │ │ │ │ └── blink-components-firefox-mobile-linux.png │ │ │ ├── enter-feature-name │ │ │ │ ├── feature-name-chromium-linux.png │ │ │ │ ├── feature-name-chromium-mobile-linux.png │ │ │ │ ├── feature-name-firefox-linux.png │ │ │ │ └── feature-name-firefox-mobile-linux.png │ │ │ ├── enter-web-feature-id │ │ │ │ ├── feature-id-chromium-linux.png │ │ │ │ ├── feature-id-chromium-mobile-linux.png │ │ │ │ ├── feature-id-firefox-linux.png │ │ │ │ └── feature-id-firefox-mobile-linux.png │ │ │ ├── navigate-to-create-feature-page │ │ │ │ ├── new-feature-page-chromium-linux.png │ │ │ │ ├── new-feature-page-chromium-mobile-linux.png │ │ │ │ ├── new-feature-page-firefox-linux.png │ │ │ │ └── new-feature-page-firefox-mobile-linux.png │ │ │ └── test-semantic-checks │ │ │ │ ├── warning-feature-name-and-summary-length-chromium-linux.png │ │ │ │ ├── warning-feature-name-and-summary-length-chromium-mobile-linux.png │ │ │ │ ├── warning-feature-name-and-summary-length-firefox-linux.png │ │ │ │ └── warning-feature-name-and-summary-length-firefox-mobile-linux.png │ │ └── chromedash-guide-stage-page_pwtest.js │ │ │ └── edit-origin-trial-stage │ │ │ ├── semantic-check-origin-trial-chromium-linux.png │ │ │ ├── semantic-check-origin-trial-chromium-mobile-linux.png │ │ │ ├── semantic-check-origin-trial-firefox-linux.png │ │ │ └── semantic-check-origin-trial-firefox-mobile-linux.png │ ├── chromedash-guide-editall-page_pwtest.js │ ├── chromedash-guide-feature-page_pwtest.js │ ├── chromedash-guide-new-page_pwtest.js │ ├── chromedash-guide-stage-page_pwtest.js │ ├── chromedash-new-feature-list.js │ ├── chromedash-report-external-reviews-page_pwtest.js │ ├── chromedash-report-spec-mentors-page_pwtest.js │ ├── external_reviews_api_result.json │ ├── spec_mentor_api_result.json │ └── test_utils.js │ └── wait-for-app.sh ├── pages ├── __init__.py ├── featurelist.py ├── featurelist_test.py ├── guide.py ├── guide_test.py ├── intentpreview.py ├── intentpreview_test.py ├── metrics.py ├── metrics_test.py ├── ot_requests.py ├── ot_requests_test.py ├── testdata │ ├── intentpreview_test │ │ ├── test_html_ot_rendering.html │ │ ├── test_html_prototype_rendering.html │ │ ├── test_html_psa_ship_rendering.html │ │ ├── test_html_rendering.html │ │ ├── test_html_ship_enterprise_rendering.html │ │ └── test_html_ship_rendering.html │ └── users_test │ │ └── test_html_rendering.html ├── users.py └── users_test.py ├── playwright.config.ts ├── pyproject.toml ├── queue.yaml ├── requirements.dev.txt ├── requirements.txt ├── scripts ├── client_secrets.json ├── debug_server.sh ├── fix_data.py ├── playwright.sh ├── seed_datastore.py └── start_server.sh ├── settings.py ├── static ├── css │ ├── base.css │ ├── features │ │ └── launch.css │ ├── forms.css │ ├── main.css │ └── ot_requests.css ├── img │ ├── a2hs_icon_24px.svg │ ├── browsers-logos.png │ ├── chrome_logo.svg │ ├── chrome_logo_canary.svg │ ├── crstatus_128.png │ ├── crstatus_144.png │ ├── crstatus_192.png │ ├── crstatus_48.png │ ├── crstatus_512.png │ ├── crstatus_72.png │ ├── crstatus_96.png │ ├── github-white.png │ ├── google_sign_in │ │ ├── btn_google_signin_light_normal_web@2x.png │ │ └── btn_google_signin_light_pressed_web@2x.png │ └── ring.svg ├── robots.txt └── shoelace │ └── assets │ ├── icons │ ├── arrow-left.svg │ ├── bug.svg │ ├── caret-down-fill.svg │ ├── check-lg.svg │ ├── chevron-right.svg │ ├── copy.svg │ ├── dash-square.svg │ ├── exclamation-circle-fill.svg │ ├── exclamation-triangle-fill.svg │ ├── filter-left.svg │ ├── graph-up.svg │ ├── info-circle.svg │ ├── pencil-fill.svg │ ├── plus-square.svg │ ├── puzzle.svg │ ├── search.svg │ ├── share.svg │ ├── sign-stop.svg │ ├── sliders2.svg │ ├── star-fill.svg │ ├── star.svg │ ├── upload.svg │ ├── x-circle-fill.svg │ └── x.svg │ └── material-icons │ ├── approval.svg │ ├── arrow_circle_right_20px.svg │ ├── autorenew_20px.svg │ ├── blank_20px.svg │ ├── block_20px.svg │ ├── check_circle_20px.svg │ ├── check_circle_filled_20px.svg │ ├── check_circle_outline.svg │ ├── clock_loader_60_20px.svg │ ├── extension.svg │ ├── help_20px.svg │ ├── highlight_off.svg │ ├── link.svg │ ├── menu_20px.svg │ ├── more_vert_24px.svg │ ├── navigate_before.svg │ ├── navigate_next.svg │ ├── pan-tool.svg │ ├── pending_20px.svg │ ├── search.svg │ ├── star.svg │ ├── star_border.svg │ ├── tune.svg │ └── visibility_20px.svg ├── templates ├── _base.html ├── accuracy_notice_email.html ├── admin │ ├── features │ │ ├── launch.html │ │ └── ot_requests.html │ └── users │ │ └── new.html ├── blink │ ├── intent_to_implement.html │ └── launch_bug.html ├── email-styles.html ├── estimated-milestones-table.html ├── farewell-rss.xml ├── farewell-samples.html ├── inactive_user_email.html ├── index.html ├── new-feature-email.html ├── origintrials │ ├── ot-activated-email.html │ ├── ot-activation-failed-email.html │ ├── ot-automated-process-email.html │ ├── ot-beta-availability-email.html │ ├── ot-creation-approved-email.html │ ├── ot-creation-processed-email.html │ ├── ot-creation-request-failed-email.html │ ├── ot-ending-next-release-email.html │ ├── ot-ending-this-release-email.html │ ├── ot-extended-email.html │ ├── ot-extension-approved-email.html │ ├── ot-first-branch-email.html │ ├── ot-last-branch-email.html │ └── ot-process-reminders-ps.html ├── prepublication-notice-email.html ├── prompts │ ├── gap-analysis.html │ ├── spec-synthesis.html │ └── test-analysis.html ├── reset-shipping-milestones-email.html ├── review-assigned-email.html ├── review-comment-email.html ├── review-comment-notification-email.html ├── review-request-email.html ├── slo_overdue_email.html ├── spa.html ├── test_template.html └── update-feature-email.html ├── testing_config.py ├── tsconfig.json ├── util └── deployment │ ├── create-deployment-issue │ ├── deploy-env │ ├── deploy-production │ └── deploy-staging └── web-test-runner.config.mjs /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "modules": false, 7 | "targets": { 8 | "esmodules": true 9 | } 10 | } 11 | ] 12 | ], 13 | "plugins": [ 14 | "@babel/plugin-proposal-class-properties", 15 | ["@babel/plugin-proposal-decorators", {"version": "2023-05"}] 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | include = 3 | ./*.py 4 | omit = 5 | ./lib/* 6 | ./cs-env/* 7 | ./*_test.py 8 | [report] 9 | exclude_lines = 10 | # Have to re-enable the standard pragma 11 | pragma: no cover 12 | 13 | # Don't complain about missing debug-only code: 14 | def __repr__ 15 | if self\.debug 16 | 17 | # Don't complain if tests don't hit defensive assertion code: 18 | raise AssertionError 19 | raise NotImplementedError 20 | 21 | # Don't complain if non-runnable code isn't run: 22 | if 0: 23 | if __name__ == ['"]__main__['"]: 24 | 25 | -------------------------------------------------------------------------------- /.devcontainer/db-docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: google/cloud-sdk:542.0.0-emulators 4 | restart: unless-stopped 5 | command: sh -c "gcloud beta emulators datastore start --project=cr-status-staging --host-port 0.0.0.0:$${DB_PORT} --no-store-on-disk --use-firestore-in-datastore-mode" 6 | environment: 7 | DB_PORT: 15606 8 | ports: 9 | - "15606:15606" 10 | 11 | dsadmin: 12 | image: ghcr.io/remko/dsadmin:v0.21.0 13 | entrypoint: /ko-app/dsadmin -port 8888 14 | depends_on: 15 | - db 16 | environment: 17 | DATASTORE_PROJECT_ID: cr-status-staging 18 | DATASTORE_EMULATOR_HOST: "db:15606" 19 | -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | ide: 3 | build: 4 | context: .. 5 | dockerfile: .devcontainer/Dockerfile 6 | target: ide 7 | volumes: 8 | - ..:/workspace:cached 9 | 10 | # Overrides default command so things don't shut down after the process ends. 11 | command: sleep infinity 12 | 13 | # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. 14 | network_mode: service:db 15 | 16 | environment: 17 | DATASTORE_PROJECT_ID: cr-status-staging 18 | DATASTORE_EMULATOR_HOST: localhost:15606 19 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | cs-env 2 | node_modules 3 | test-results 4 | playwright-report/ 5 | playwright/.cache/ 6 | 7 | # Web test runner coverage report 8 | coverage 9 | 10 | __pycache__ -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | ; Python 13 | [*.py] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | ; YAML 18 | [*.{yaml,yml}] 19 | indent_size = 2 -------------------------------------------------------------------------------- /.gcloudignore: -------------------------------------------------------------------------------- 1 | # This file specifies files that are *not* uploaded to Google Cloud Platform 2 | # using gcloud. It follows the same syntax as .gitignore, with the addition of 3 | # "#!include" directives (which insert the entries of the given .gitignore-style 4 | # file at that point). 5 | # 6 | # For more information, run: 7 | # $ gcloud topic gcloudignore 8 | # 9 | .gcloudignore 10 | # If you would like to upload your .git directory, .gitignore file or files 11 | # from your .gitignore file, remove the corresponding line 12 | # below: 13 | .git 14 | .gitignore 15 | 16 | # Python pycache: 17 | __pycache__/ 18 | # Ignored by the build system 19 | /setup.cfg 20 | 21 | *~ 22 | *.pyc 23 | *.swp 24 | .sass-cache 25 | .vscode 26 | *oauth2.data 27 | .fcm_server_key 28 | *.iml 29 | .idea/* 30 | bulkloader-* 31 | cookie 32 | 33 | # Dependency directories 34 | node_modules 35 | 36 | # Source for generated files 37 | client-src 38 | 39 | # OS files 40 | *.DS_Store 41 | 42 | # Test coverage tool 43 | .coverage 44 | htmlcov 45 | 46 | # Python venv directory 47 | cs-env 48 | tutorial-env 49 | 50 | # Testdata for Python tests 51 | testdata 52 | 53 | # API Key for local development 54 | ot_api_key.txt 55 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thank you for letting us know that something needs to be fixed. This page is for recording bugs on Chrome Status (https://www.chromestatus.com). If you need to report a problem with Chrome or Chromium, please use crbug (http://crbug.com/new). Thank you. 11 | 12 | **Describe the bug** 13 | A clear and concise description of what the bug is. 14 | 15 | **To Reproduce** 16 | Steps to reproduce the behavior: 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error. If applicable, add screenshots to help explain your problem. 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen. 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/process-and-guide-ux-feedback.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Process and Guide UX Feedback 3 | about: Feedback from early access to new Blink launch process and Guide UX 4 | title: '' 5 | labels: Feedback 6 | assignees: '' 7 | 8 | --- 9 | 10 | Use this template to provide feedback on the new Blink launch process and Guide UX for editing features. 11 | 12 | **Process Feedback** 13 | Was anything unclear? Is there something that you need represented in the process? 14 | 15 | **Guide UX Feedback** 16 | Did you encounter any errors? Was something unclear? Did the tool prevent you from doing something that you need to do? Please provide the URL of the page or a screenshot, and indicate the affected part of the page. 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Basic dependabot.yml file with configuration for npm managers 2 | 3 | version: 2 4 | updates: 5 | # Enable version updates for npm 6 | - package-ecosystem: "npm" 7 | # Look for `package.json` and `lock` files in the `root` directory 8 | directory: "/" 9 | # Check the npm registry for updates every day (weekdays) 10 | schedule: 11 | interval: "weekly" 12 | commit-message: 13 | # Prefix all commit messages with "npm" 14 | prefix: "npm" 15 | - package-ecosystem: "docker" 16 | directory: "/" 17 | schedule: 18 | interval: "weekly" 19 | commit-message: 20 | # Prefix all commit messages with "docker" 21 | prefix: "docker" 22 | - package-ecosystem: "github-actions" 23 | directory: "/" 24 | schedule: 25 | interval: "weekly" 26 | groups: 27 | actions-org: 28 | patterns: ["actions/*"] 29 | commit-message: 30 | # Prefix all commit messages with "gh-actions" 31 | prefix: "gh-actions" 32 | - package-ecosystem: "pip" 33 | directory: "/" 34 | schedule: 35 | interval: "weekly" 36 | commit-message: 37 | # Prefix all commit messages with "pip" 38 | prefix: "pip" 39 | -------------------------------------------------------------------------------- /.github/workflows/playwright.yml: -------------------------------------------------------------------------------- 1 | name: Playwright Tests 2 | on: 3 | pull_request: 4 | merge_group: 5 | 6 | jobs: 7 | playwright: 8 | name: 'Playwright Tests' 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v5 12 | 13 | # Steps for Playwright testing with container 14 | - uses: actions/setup-node@v6 15 | with: 16 | node-version: 20 17 | - name: Run your tests 18 | timeout-minutes: 30 19 | run: npm run pwtests-shutdown; npm run pwtests 20 | - uses: actions/upload-artifact@v5 21 | if: failure() 22 | with: 23 | name: test-results 24 | path: packages/playwright/test-results/ 25 | retention-days: 30 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | *.swp 4 | .sass-cache 5 | .vscode/* 6 | !.vscode/launch.json 7 | *oauth2.data 8 | .fcm_server_key 9 | *.iml 10 | .idea/* 11 | bulkloader-* 12 | cookie 13 | lib 14 | 15 | # env variables file 16 | env_vars.yaml 17 | 18 | # Dependency directories 19 | node_modules 20 | 21 | # Generated files 22 | static/css/ 23 | static/dist/ 24 | 25 | # OS files 26 | *.DS_Store 27 | 28 | # Test coverage tool 29 | .coverage 30 | htmlcov 31 | 32 | # Web test runner coverage report 33 | coverage 34 | 35 | # venv directory 36 | cs-env 37 | 38 | # playwright 39 | test-results/ 40 | /playwright-report/ 41 | /playwright/.cache/ 42 | 43 | # API Key for local development 44 | ot_api_key.txt 45 | gemini_api_key.txt 46 | github_token.txt 47 | 48 | # Typescript incremental build 49 | tsconfig.tsbuildinfo 50 | 51 | # rollup cache 52 | .rollup.cache/ 53 | 54 | # build output 55 | build/ 56 | 57 | # Temporary 58 | packages/playwright/playwright.config.ts 59 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | import gts from 'gts/.prettierrc.json' assert { type: "json" }; 2 | 3 | /** @type {import("prettier").Config} */ 4 | export default { 5 | ...gts, 6 | "trailingComma": "es5", 7 | }; 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "42Crunch.vscode-openapi", 8 | "bierner.lit-html", 9 | "charliermarsh.ruff", 10 | "ms-playwright.playwright", 11 | "ms-python.mypy-type-checker", 12 | "ms-python.python", 13 | "EditorConfig.EditorConfig", 14 | ], 15 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 16 | "unwantedRecommendations": [ 17 | 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Remote Attach", 9 | "type": "python", 10 | "request": "attach", 11 | "connect": { 12 | "host": "localhost", 13 | "port": 5678 14 | }, 15 | "pathMappings": [ 16 | { 17 | "localRoot": "${workspaceFolder}", 18 | "remoteRoot": "/workspace" 19 | } 20 | ], 21 | "justMyCode": false 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PYTHON_VARIANT=3.13-bookworm 2 | FROM python:${PYTHON_VARIANT} as app 3 | 4 | RUN groupadd -g 1001 appuser && \ 5 | useradd appuser -u 1001 -g 1001 -m -d /home/appuser -s /bin/bash 6 | 7 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 8 | # openapi-generator-cli dependencies 9 | && apt-get install -y openjdk-17-jre 10 | 11 | USER appuser 12 | 13 | # Install node 14 | ENV NVM_DIR=/home/appuser/.nvm \ 15 | # Need the full major.minor.patch version for NODE_VERISON 16 | # https://nodejs.org/en/download/releases 17 | NODE_VERSION=20.19.2 18 | 19 | RUN mkdir /home/appuser/.nvm && \ 20 | curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash \ 21 | && . $NVM_DIR/nvm.sh \ 22 | && nvm install $NODE_VERSION \ 23 | && nvm alias default $NODE_VERSION \ 24 | && nvm use default \ 25 | && npm config set script-shell bash 26 | 27 | ENV NODE_PATH=$NVM_DIR/v$NODE_VERSION/lib/node_modules \ 28 | PATH="${PATH}:$NVM_DIR/versions/node/v$NODE_VERSION/bin" 29 | 30 | WORKDIR /workspace 31 | # Cache the infrequent but time consuming changes early 32 | COPY --chown=appuser:appuser requirements.txt requirements.dev.txt package.json package-lock.json /workspace/ 33 | COPY --chown=appuser:appuser openapi /workspace/openapi/ 34 | COPY --chown=appuser:appuser gen /workspace/gen/ 35 | RUN npm install -g gulp-cli && npm run setup && cs-env/bin/python -m pip install debugpy==1.6.7.post1 36 | # Copy the rest 37 | COPY --chown=appuser:appuser . /workspace 38 | -------------------------------------------------------------------------------- /api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/api/__init__.py -------------------------------------------------------------------------------- /api/blink_components_api.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2022 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License") 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | from framework import basehandlers 18 | from internals import user_models 19 | 20 | 21 | class BlinkComponentsAPI(basehandlers.APIHandler): 22 | """The list of blink components populates the "Blink component" select field 23 | in the guide form""" 24 | 25 | def do_get(self, **kwargs): 26 | """Returns a dict with blink components as both keys and values.""" 27 | return {x: [x, x] for x in user_models.BlinkComponent.fetch_all_components()} 28 | -------------------------------------------------------------------------------- /api/logout_api.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2021 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License") 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import logging 17 | 18 | from flask import session 19 | 20 | from framework import basehandlers 21 | 22 | 23 | class LogoutAPI(basehandlers.APIHandler): 24 | """Clear the session when the user signs out.""" 25 | 26 | def do_get(self, **kwargs): 27 | """Reject unneeded GET requests without triggering Error Reporting.""" 28 | self.abort(405, valid_methods=['POST']) 29 | 30 | def do_post(self, **kwargs): 31 | session.clear() 32 | return {'message': 'Done'} 33 | -------------------------------------------------------------------------------- /app.staging.yaml: -------------------------------------------------------------------------------- 1 | # This GAE service contains most of the app, including all UI pages. 2 | 3 | runtime: python313 4 | service: default 5 | instance_class: F4_1G 6 | 7 | automatic_scaling: 8 | min_idle_instances: 1 9 | max_pending_latency: 0.2s 10 | 11 | # Use a long HTTP cache expiration time for css and JS, but also 12 | # include the GAE version number as a query string parameter so that on 13 | # each deployment, users get new static files to match the new app version. 14 | default_expiration: "10d" 15 | 16 | # Set up VPC Access Connector for Redis. 17 | vpc_access_connector: 18 | name: projects/cr-status-staging/locations/us-central1/connectors/redis-connector 19 | 20 | handlers: 21 | # Static handlers --------------------------------------------------------------- 22 | - url: /favicon\.ico 23 | static_files: static/img/chromium-128.png 24 | upload: static/img/chromium-128\.png 25 | secure: always 26 | 27 | - url: /robots\.txt 28 | static_files: static/robots.txt 29 | upload: static/robots\.txt 30 | secure: always 31 | 32 | - url: /static 33 | static_dir: static 34 | secure: always 35 | 36 | - url: /.* 37 | script: auto 38 | secure: always 39 | 40 | app_engine_apis: true 41 | 42 | env_variables: 43 | GAE_USE_SOCKETS_HTTPLIB : '' 44 | # Redis envs 45 | REDISHOST: '10.231.56.251' 46 | REDISPORT: '6379' 47 | 48 | inbound_services: 49 | - mail 50 | - mail_bounce 51 | -------------------------------------------------------------------------------- /app.yaml: -------------------------------------------------------------------------------- 1 | # This GAE service contains most of the app, including all UI pages. 2 | 3 | runtime: python313 4 | service: default 5 | instance_class: F4_1G 6 | 7 | automatic_scaling: 8 | min_idle_instances: 1 9 | max_pending_latency: 0.2s 10 | 11 | # Use a long HTTP cache expiration time for css and JS, but also 12 | # include the GAE version number as a query string parameter so that on 13 | # each deployment, users get new static files to match the new app version. 14 | default_expiration: "10d" 15 | 16 | # Set up VPC Access Connector for Redis. 17 | vpc_access_connector: 18 | name: projects/cr-status/locations/us-central1/connectors/redis-connector 19 | 20 | handlers: 21 | # Static handlers --------------------------------------------------------------- 22 | - url: /favicon\.ico 23 | static_files: static/img/chromium-128.png 24 | upload: static/img/chromium-128\.png 25 | secure: always 26 | 27 | - url: /robots\.txt 28 | static_files: static/robots.txt 29 | upload: static/robots\.txt 30 | secure: always 31 | 32 | - url: /static 33 | static_dir: static 34 | secure: always 35 | 36 | - url: /.* 37 | script: auto 38 | secure: always 39 | 40 | app_engine_apis: true 41 | 42 | env_variables: 43 | GAE_USE_SOCKETS_HTTPLIB : '' 44 | # Redis envs 45 | REDISHOST: '10.250.3.187' 46 | REDISPORT: '6379' 47 | 48 | inbound_services: 49 | - mail 50 | - mail_bounce 51 | -------------------------------------------------------------------------------- /appengine_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import importlib 4 | 5 | # Add libraries to pkg_resources working set to find the distribution. 6 | import pkg_resources 7 | pkg_resources.working_set.add_entry(lib_path) 8 | -------------------------------------------------------------------------------- /client-src/css/_flexbox-css.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {css} from 'lit'; 18 | 19 | /** 20 | * Flexbox layout helper classes. 21 | * 22 | * This is a simplified version of the flexbox layout helper classes from 23 | * https://htmlpreview.github.io/?https://raw.githubusercontent.com/dlaliberte/standards-notes/master/flexbox-classes.html 24 | */ 25 | export const FLEX_BOX = css` 26 | .hbox, 27 | .vbox { 28 | display: flex; 29 | align-items: center; 30 | } 31 | 32 | .hbox { 33 | flex-direction: row; 34 | } 35 | .hbox.align-top { 36 | align-items: flex-start; 37 | } 38 | .vbox { 39 | flex-direction: column; 40 | } 41 | 42 | .hbox > .spacer, 43 | .vbox > .spacer { 44 | flex-grow: 1; 45 | visibility: hidden; 46 | } 47 | `; 48 | -------------------------------------------------------------------------------- /client-src/css/_layout-css.js: -------------------------------------------------------------------------------- 1 | import { css } from "lit"; 2 | 3 | export const LAYOUT_CSS = css` 4 | .layout { 5 | display: flex; 6 | } 7 | .layout.wrap { 8 | flex-wrap: wrap; 9 | } 10 | .layout.center { 11 | align-items: center; 12 | } 13 | .layout.center-center { 14 | align-items: center; 15 | justify-content: center; 16 | } 17 | .layout.vertical { 18 | flex-direction: column; 19 | }`; 20 | -------------------------------------------------------------------------------- /client-src/css/_vars-css.js: -------------------------------------------------------------------------------- 1 | import {css} from 'lit'; 2 | 3 | export const VARS = css` 4 | :host { 5 | --default-font-color: #222; 6 | --page-background: #fafafa; 7 | 8 | --light-grey: #eee; 9 | 10 | --gray-1: #e6e6e6; 11 | --gray-2: #a9a9a9; 12 | --gray-3: #797979; 13 | --gray-4: #515151; 14 | 15 | --nav-link-color: #444; 16 | 17 | --bar-shadow-color: rgba(0, 0, 0, .065); 18 | --bar-border-color: #D4D4D4; 19 | --error-border-color: #FF0000; 20 | 21 | --chromium-color-dark: #366597; 22 | --chromium-color-medium: #85b4df; 23 | --chromium-color-light: #bdd6ed; 24 | --chromium-color-center: #4580c0; 25 | 26 | --material-primary-button: #58f; 27 | 28 | --card-background: white; 29 | --card-border: 1px solid #ddd; 30 | --card-box-shadow: rgba(0, 0, 0, 0.067) 1px 1px 4px; 31 | 32 | /* App specific */ 33 | --invalid-color: rgba(255,0,0,0.75); 34 | --content-padding: 16px; 35 | --content-padding-half: 8px; 36 | --content-padding-negative: -16px; 37 | --content-padding-huge: 80px; 38 | --default-border-radius: 3px; 39 | 40 | --max-content-width: 860px; 41 | }`; 42 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-activity-page_test.ts: -------------------------------------------------------------------------------- 1 | import {assert, fixture} from '@open-wc/testing'; 2 | import {html} from 'lit'; 3 | import {ChromedashActivityPage} from './chromedash-activity-page'; 4 | import {ChromeStatusClient} from '../js-src/cs-client'; 5 | import sinon from 'sinon'; 6 | 7 | describe('chromedash-settings-page', () => { 8 | let getCommentsStub: sinon.SinonStub; 9 | /* window.csClient is initialized in spa.html 10 | * which is not available here, so we initialize it before each test. 11 | * We also stub out the API calls here so that they return test data. */ 12 | beforeEach(async () => { 13 | window.csClient = new ChromeStatusClient('fake_token', 1); 14 | getCommentsStub = sinon.stub(window.csClient, 'getComments'); 15 | }); 16 | 17 | afterEach(() => { 18 | getCommentsStub.restore(); 19 | }); 20 | 21 | it('can be added to the page before being opened', async () => { 22 | const component = await fixture( 23 | html`` 24 | ); 25 | assert.exists(component); 26 | assert.instanceOf(component, ChromedashActivityPage); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-banner.ts: -------------------------------------------------------------------------------- 1 | import {LitElement, css, html, nothing} from 'lit'; 2 | import {SHARED_STYLES} from '../css/shared-css.js'; 3 | import {customElement, property} from 'lit/decorators.js'; 4 | 5 | @customElement('chromedash-banner') 6 | class ChromedashBanner extends LitElement { 7 | @property({type: Number}) 8 | timestamp: null | number = null; // Unix timestamp: seconds since 1970-01-01. 9 | @property({type: String}) 10 | message: string = ''; 11 | 12 | static get styles() { 13 | return [ 14 | ...SHARED_STYLES, 15 | css` 16 | div { 17 | display: inline-block; 18 | background: var(--warning-background); 19 | color: var(--warning-color); 20 | border-radius: var(--border-radius); 21 | padding: var(--content-padding); 22 | width: 100%; 23 | } 24 | `, 25 | ]; 26 | } 27 | 28 | computeLocalDateString() { 29 | if (!this.timestamp) { 30 | return nothing; 31 | } 32 | const date = new Date(this.timestamp * 1000); 33 | const formatOptions: Intl.DateTimeFormatOptions = { 34 | weekday: 'long', 35 | year: 'numeric', 36 | month: 'long', 37 | day: 'numeric', 38 | hour: 'numeric', 39 | minute: 'numeric', 40 | }; // No seconds 41 | return date.toLocaleString(undefined, formatOptions); 42 | } 43 | 44 | render() { 45 | if (!this.message) { 46 | return nothing; 47 | } 48 | 49 | return html`
${this.message} ${this.computeLocalDateString()}
`; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-enterprise-page.ts: -------------------------------------------------------------------------------- 1 | import {html} from 'lit'; 2 | import {ChromedashAllFeaturesPage} from './chromedash-all-features-page'; 3 | import {customElement} from 'lit/decorators.js'; 4 | 5 | @customElement('chromedash-enterprise-page') 6 | export class ChromedashEnterprisePage extends ChromedashAllFeaturesPage { 7 | renderBox(query) { 8 | return html` 9 | 19 | 20 | `; 21 | } 22 | 23 | renderEnterpriseFeatures() { 24 | return this.renderBox( 25 | 'feature_type="New Feature or removal affecting enterprises" ' + 26 | 'OR enterprise_impact>1' 27 | ); 28 | } 29 | 30 | render() { 31 | return html` 32 |

Enterprise features and breaking changes

33 | ${this.renderEnterpriseFeatures()} 34 | `; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-footer_test.ts: -------------------------------------------------------------------------------- 1 | import {html} from 'lit'; 2 | import {assert, fixture} from '@open-wc/testing'; 3 | import {ChromedashFooter} from './chromedash-footer'; 4 | 5 | describe('chromedash-footer', () => { 6 | it('renders with no data', async () => { 7 | const component = await fixture( 8 | html`` 9 | ); 10 | assert.exists(component); 11 | assert.instanceOf(component, ChromedashFooter); 12 | const footer = component.renderRoot.querySelector('footer'); 13 | assert.exists(footer); 14 | 15 | const links = [ 16 | 'https://github.com/GoogleChrome/chromium-dashboard/wiki/', 17 | 'https://groups.google.com/a/chromium.org/forum/#!newtopic/blink-dev', 18 | 'https://github.com/GoogleChrome/chromium-dashboard/issues', 19 | 'https://policies.google.com/privacy', 20 | ]; 21 | 22 | // all footer links exist and are clickable 23 | links.map(link => assert.include(footer.innerHTML, `href="${link}"`)); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-form-table.ts: -------------------------------------------------------------------------------- 1 | import {LitElement, css, html} from 'lit'; 2 | import {customElement, property} from 'lit/decorators.js'; 3 | 4 | @customElement('chromedash-form-table') 5 | export class ChromedashFormTable extends LitElement { 6 | @property({type: String}) 7 | class; 8 | 9 | static get styles() { 10 | return [ 11 | css` 12 | :host { 13 | display: table; 14 | max-width: 80em; 15 | } 16 | `, 17 | ]; 18 | } 19 | 20 | render() { 21 | return html` fallback content `; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-form-table_test.ts: -------------------------------------------------------------------------------- 1 | import {assert, fixture} from '@open-wc/testing'; 2 | import {html} from 'lit'; 3 | import {ChromedashFormTable} from './chromedash-form-table'; 4 | import {slotAssignedElements} from './utils'; 5 | 6 | describe('chromedash-form-table', () => { 7 | it('renders with no data', async () => { 8 | const component = await fixture( 9 | html`` 10 | ); 11 | assert.exists(component); 12 | assert.instanceOf(component, ChromedashFormTable); 13 | const formContents = component.renderRoot.querySelector('*'); 14 | assert.exists(formContents); 15 | }); 16 | 17 | it('renders with array of slots for rows', async () => { 18 | const component: ChromedashFormTable = await fixture( 19 | html` 20 | Row 1 21 | Row 2 22 | ` 23 | ); 24 | assert.exists(component); 25 | await component.updateComplete; 26 | 27 | const children = slotAssignedElements(component, ''); 28 | 29 | const firstRow = children[0]; 30 | assert.exists(firstRow); 31 | assert.include(firstRow.innerHTML, 'Row 1'); 32 | 33 | const secondRow = children[1]; 34 | assert.exists(secondRow); 35 | assert.include(secondRow.innerHTML, 'Row 2'); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-gate-column_test.ts: -------------------------------------------------------------------------------- 1 | import {html} from 'lit'; 2 | import {assert, fixture} from '@open-wc/testing'; 3 | import {ChromedashGateColumn} from './chromedash-gate-column'; 4 | import {ChromeStatusClient} from '../js-src/cs-client'; 5 | import sinon from 'sinon'; 6 | 7 | describe('chromedash-settings-page', () => { 8 | /* window.csClient is initialized in spa.html 9 | * which is not available here, so we initialize it before each test. 10 | * We also stub out the API calls here so that they return test data. */ 11 | beforeEach(async () => { 12 | window.csClient = new ChromeStatusClient('fake_token', 1); 13 | sinon.stub(window.csClient, 'getFeatureProcess'); 14 | sinon.stub(window.csClient, 'getVotes'); 15 | sinon.stub(window.csClient, 'getComments'); 16 | }); 17 | 18 | afterEach(() => { 19 | window.csClient.getFeatureProcess.restore(); 20 | window.csClient.getVotes.restore(); 21 | window.csClient.getComments.restore(); 22 | }); 23 | 24 | it('can be added to the page before being opened', async () => { 25 | const component = await fixture( 26 | html`` 27 | ); 28 | assert.exists(component); 29 | assert.instanceOf(component, ChromedashGateColumn); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-intent-template_test.ts: -------------------------------------------------------------------------------- 1 | import {html} from 'lit'; 2 | import {assert, fixture} from '@open-wc/testing'; 3 | import {ChromedashIntentContent} from './chromedash-intent-content'; 4 | 5 | describe('chromedash-intent-content', () => { 6 | it('renders with fake data', async () => { 7 | const component = await fixture( 8 | html` 13 | ` 14 | ); 15 | assert.exists(component); 16 | assert.instanceOf(component, ChromedashIntentContent); 17 | 18 | const subject = component.renderRoot.querySelector( 19 | '#email-subject-content' 20 | ) as HTMLElement; 21 | const body = component.renderRoot.querySelector( 22 | '#email-body-content' 23 | ) as HTMLElement; 24 | 25 | assert.equal(body.innerText, 'A basic intent body'); 26 | assert.equal(subject.innerText, 'A fake subject'); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-login-required-page.ts: -------------------------------------------------------------------------------- 1 | import {LitElement, html} from 'lit'; 2 | import {customElement} from 'lit/decorators.js'; 3 | 4 | @customElement('chromedash-login-required-page') 5 | export class ChromedashLoginRequiredPage extends LitElement { 6 | render() { 7 | return html`
Please login to see the content of this page.
`; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-report-external-reviews-dispatch-page.ts: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import {LitElement, html} from 'lit'; 3 | import {customElement} from 'lit/decorators.js'; 4 | import {SHARED_STYLES} from '../css/shared-css.js'; 5 | 6 | @customElement('chromedash-report-external-reviews-dispatch-page') 7 | export class ChromedashReportExternalReviewsDispatchPage extends LitElement { 8 | static get styles() { 9 | return SHARED_STYLES; 10 | } 11 | 12 | render() { 13 | return html` 14 |
Which group's reviews do you want to see?
15 | 26 | `; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-report-spec-mentor.ts: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import {SpecMentor} from 'chromestatus-openapi'; 3 | import {LitElement, css, html} from 'lit'; 4 | import {customElement, property} from 'lit/decorators.js'; 5 | import {SHARED_STYLES} from '../css/shared-css.js'; 6 | import './chromedash-feature-row.js'; 7 | 8 | @customElement('chromedash-report-spec-mentor') 9 | export class ChromedashReportSpecMentor extends LitElement { 10 | static get styles() { 11 | return [...SHARED_STYLES, css``]; 12 | } 13 | 14 | @property({attribute: false}) 15 | mentor!: SpecMentor; 16 | 17 | render() { 18 | return html` 19 | 20 | 21 | ${this.mentor.mentored_features.map( 22 | feature => html` 23 | 26 | ` 27 | )} 28 |
29 |
30 | `; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /client-src/elements/chromedash-vendor-views.ts: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import {LitElement, html} from 'lit'; 4 | import {customElement, property} from 'lit/decorators.js'; 5 | import {FeatureLink} from '../js-src/cs-client'; 6 | 7 | /** 8 | * Use like `Text description of the view` 10 | */ 11 | @customElement('chromedash-vendor-views') 12 | export class ChromedashVendorViews extends LitElement { 13 | /** URL of the evidence for this view.*/ 14 | @property({type: String}) 15 | href; 16 | @property({attribute: false}) 17 | featureLinks: FeatureLink[] = []; 18 | 19 | urlIsStandardsPosition(url: string): boolean { 20 | return /github.com\/(mozilla|WebKit)\/standards-positions\/issues/.test( 21 | url 22 | ); 23 | } 24 | 25 | render() { 26 | if (this.href) { 27 | return html``; 33 | } else { 34 | return html``; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /client-src/js-src/shared.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | // Google Analytics 20 | // Global site tag (gtag.js) - Google Analytics 21 | window.dataLayer = window.dataLayer || []; 22 | function gtag() { 23 | dataLayer.push(arguments); 24 | } 25 | gtag('js', new Date()); 26 | 27 | gtag('config', 'UA-179341418-1'); 28 | // End Google Analytics 29 | -------------------------------------------------------------------------------- /client-src/js-src/types.d.ts: -------------------------------------------------------------------------------- 1 | import {DefaultApiInterface} from 'chromestatus-openapi'; 2 | import {ChromeStatusClient} from './chrome-status-client'; 3 | 4 | declare global { 5 | interface Window { 6 | csClient: ChromeStatusClient; 7 | csOpenApiClient: DefaultApiInterface; 8 | scrollToElement: (hash: string) => void; 9 | } 10 | } 11 | 12 | declare class ChromeStatusHttpError extends Error { 13 | resource: string; 14 | method: string; 15 | status: number; 16 | constructor( 17 | message: string, 18 | resource: string, 19 | method: string, 20 | status: number 21 | ); 22 | } 23 | 24 | declare class FeatureNotFoundError extends Error { 25 | featureID: number; 26 | constructor(featureID: number); 27 | } 28 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | 3 | # Set this to the root of your project when deployed: 4 | http_path = "/" 5 | css_dir = "static/css" 6 | sass_dir = "client-src/sass" 7 | images_dir = "static/img" 8 | javascripts_dir = "static/js" 9 | 10 | # You can select your preferred output style here (can be overridden via the command line): 11 | output_style = :compressed #:expanded or :nested or :compact or :compressed 12 | 13 | # To enable relative paths to assets via compass helper functions. Uncomment: 14 | # relative_assets = true 15 | 16 | # To disable debugging comments that display the original location of your selectors. Uncomment: 17 | # line_comments = false 18 | 19 | 20 | # If you prefer the indented syntax, you might want to regenerate this 21 | # project again passing --syntax sass, or you can uncomment this: 22 | # preferred_syntax = :sass 23 | # and then run: 24 | # sass-convert -R --from scss --to sass static/sass scss && rm -rf sass && mv scss sass 25 | -------------------------------------------------------------------------------- /dispatch.yaml: -------------------------------------------------------------------------------- 1 | dispatch: 2 | 3 | # Note that inbound email and bounces are processed by the default service, 4 | # because /_ah/ requests are not routed by dispatch.yaml. 5 | # https://cloud.google.com/appengine/docs/standard/python/reference/dispatch-yaml 6 | 7 | - url: "*/tasks/detect-intent" 8 | service: notifier 9 | 10 | - url: "*/tasks/email-subscribers" 11 | service: notifier 12 | 13 | - url: "*/tasks/email-reviewers" 14 | service: notifier 15 | 16 | - url: "*/tasks/email-comments" 17 | service: notifier 18 | 19 | - url: "*/*" 20 | service: default 21 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import eslintConfigPrettier from "eslint-config-prettier"; 3 | import gts from "./node_modules/gts/build/src/index.js"; 4 | 5 | 6 | export default [ 7 | js.configs.recommended, 8 | eslintConfigPrettier, 9 | { 10 | rules: gts.rules, 11 | }, 12 | { 13 | languageOptions: { 14 | ecmaVersion: 2022, 15 | sourceType: "module", 16 | globals: { 17 | "ga": true, 18 | "Metric": true 19 | }, 20 | }, 21 | rules: { 22 | "no-warning-comments": "off", 23 | "no-unused-vars": ["error", { 24 | "vars": "all", 25 | "args": "after-used", 26 | "argsIgnorePattern": "^var_args$" 27 | }], 28 | "require-jsdoc": 0, 29 | "valid-jsdoc": "off", 30 | "no-var": 1, 31 | "prettier/prettier": "off", 32 | // TODO: Re-enable these rules from gts. 33 | "eqeqeq": "off", 34 | "no-const-assign": "off", 35 | "no-dupe-class-members": "off", 36 | "no-dupe-keys": "off", 37 | "no-empty-pattern": "off", 38 | "no-prototype-builtins": "off", 39 | "no-self-assign": "off", 40 | "no-undef": "off", 41 | "no-unreachable": "off", 42 | "no-useless-escape": "off", 43 | "node/no-extraneous-import": "off", 44 | "node/no-missing-import": "off", 45 | "node/no-unpublished-import": "off", 46 | }, 47 | ignores: [ 48 | "**/node_modules/**", 49 | "static/dist/", 50 | ] 51 | } 52 | ]; 53 | -------------------------------------------------------------------------------- /framework/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/framework/__init__.py -------------------------------------------------------------------------------- /framework/constants.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2021 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License") 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | 18 | 19 | 20 | # Number of seconds in various periods. 21 | SECS_PER_MINUTE = 60 22 | SECS_PER_HOUR = SECS_PER_MINUTE * 60 23 | SECS_PER_DAY = SECS_PER_HOUR * 24 24 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/.gitignore: -------------------------------------------------------------------------------- 1 | wwwroot/*.js 2 | node_modules 3 | typings 4 | dist 5 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/.npmignore: -------------------------------------------------------------------------------- 1 | README.md -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.6.0 2 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/README.md: -------------------------------------------------------------------------------- 1 | ## chromestatus-openapi@1.0.0 2 | 3 | This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments: 4 | 5 | Environment 6 | * Node.js 7 | * Webpack 8 | * Browserify 9 | 10 | Language level 11 | * ES5 - you must have a Promises/A+ library installed 12 | * ES6 13 | 14 | Module system 15 | * CommonJS 16 | * ES6 module system 17 | 18 | It can be used in both TypeScript and JavaScript. In TypeScript, the definition will be automatically resolved via `package.json`. ([Reference](https://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html)) 19 | 20 | ### Building 21 | 22 | To build and compile the typescript sources to javascript use: 23 | ``` 24 | npm install 25 | npm run build 26 | ``` 27 | 28 | ### Publishing 29 | 30 | First build the package then run `npm publish` 31 | 32 | ### Consuming 33 | 34 | navigate to the folder of your consuming project and run one of the following commands. 35 | 36 | _published:_ 37 | 38 | ``` 39 | npm install chromestatus-openapi@1.0.0 --save 40 | ``` 41 | 42 | _unPublished (not recommended):_ 43 | 44 | ``` 45 | npm install PATH_TO_GENERATED_PACKAGE --save 46 | ``` 47 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chromestatus-openapi", 3 | "version": "1.0.0", 4 | "description": "OpenAPI client for chromestatus-openapi", 5 | "author": "OpenAPI-Generator", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/GIT_USER_ID/GIT_REPO_ID.git" 9 | }, 10 | "main": "./dist/index.js", 11 | "typings": "./dist/index.d.ts", 12 | "module": "./dist/esm/index.js", 13 | "sideEffects": false, 14 | "scripts": { 15 | "build": "tsc && tsc -p tsconfig.esm.json", 16 | "prepare": "npm run build" 17 | }, 18 | "devDependencies": { 19 | "typescript": "^5.9" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/src/apis/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from './DefaultApi'; 4 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/src/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from './runtime'; 4 | export * from './apis/index'; 5 | export * from './models/index'; 6 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "esnext", 5 | "outDir": "dist/esm" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /gen/js/chromestatus-openapi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "target": "es6", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "outDir": "dist", 8 | "typeRoots": [ 9 | "node_modules/@types" 10 | ] 11 | }, 12 | "exclude": [ 13 | "dist", 14 | "node_modules" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/.dockerignore: -------------------------------------------------------------------------------- 1 | .travis.yaml 2 | .openapi-generator-ignore 3 | README.md 4 | tox.ini 5 | git_push.sh 6 | test-requirements.txt 7 | setup.py 8 | 9 | # Byte-compiled / optimized / DLL files 10 | __pycache__/ 11 | *.py[cod] 12 | *$py.class 13 | 14 | # C extensions 15 | *.so 16 | 17 | # Distribution / packaging 18 | .Python 19 | env/ 20 | build/ 21 | develop-eggs/ 22 | dist/ 23 | downloads/ 24 | eggs/ 25 | .eggs/ 26 | lib/ 27 | lib64/ 28 | parts/ 29 | sdist/ 30 | var/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *,cover 54 | .hypothesis/ 55 | venv/ 56 | .python-version 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | #Ipython Notebook 72 | .ipynb_checkpoints 73 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | venv/ 48 | .venv/ 49 | .python-version 50 | .pytest_cache 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # PyBuilder 63 | target/ 64 | 65 | #Ipython Notebook 66 | .ipynb_checkpoints 67 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.6.0 2 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/.travis.yml: -------------------------------------------------------------------------------- 1 | # ref: https://docs.travis-ci.com/user/languages/python 2 | language: python 3 | python: 4 | - "3.2" 5 | - "3.3" 6 | - "3.4" 7 | - "3.5" 8 | - "3.6" 9 | - "3.7" 10 | - "3.8" 11 | # command to install dependencies 12 | install: "pip install -r requirements.txt" 13 | # command to run tests 14 | script: nosetests 15 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-alpine 2 | 3 | RUN mkdir -p /usr/src/app 4 | WORKDIR /usr/src/app 5 | 6 | COPY requirements.txt /usr/src/app/ 7 | 8 | RUN pip3 install --no-cache-dir -r requirements.txt 9 | 10 | COPY . /usr/src/app 11 | 12 | EXPOSE 8080 13 | 14 | ENTRYPOINT ["python3"] 15 | 16 | CMD ["-m", "chromestatus_openapi"] -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/README.md: -------------------------------------------------------------------------------- 1 | # OpenAPI generated server 2 | 3 | ## Overview 4 | This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the 5 | [OpenAPI-Spec](https://openapis.org) from a remote server, you can easily generate a server stub. This 6 | is an example of building a OpenAPI-enabled Flask server. 7 | 8 | This example uses the [Connexion](https://github.com/zalando/connexion) library on top of Flask. 9 | 10 | ## Requirements 11 | Python 3.5.2+ 12 | 13 | ## Usage 14 | To run the server, please execute the following from the root directory: 15 | 16 | ``` 17 | pip3 install -r requirements.txt 18 | python3 -m chromestatus_openapi 19 | ``` 20 | 21 | and open your browser to here: 22 | 23 | ``` 24 | http://localhost:8080/api/v0/ui/ 25 | ``` 26 | 27 | Your OpenAPI definition lives here: 28 | 29 | ``` 30 | http://localhost:8080/api/v0/openapi.json 31 | ``` 32 | 33 | To launch the integration tests, use tox: 34 | ``` 35 | sudo pip install tox 36 | tox 37 | ``` 38 | 39 | ## Running with Docker 40 | 41 | To run the server on a Docker container, please execute the following from the root directory: 42 | 43 | ```bash 44 | # building the image 45 | docker build -t chromestatus_openapi . 46 | 47 | # starting up a container 48 | docker run -p 8080:8080 chromestatus_openapi 49 | ``` -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/gen/py/chromestatus_openapi/chromestatus_openapi/__init__.py -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import connexion 4 | 5 | from chromestatus_openapi import encoder 6 | 7 | 8 | def main(): 9 | app = connexion.App(__name__, specification_dir='./openapi/') 10 | app.app.json_encoder = encoder.JSONEncoder 11 | app.add_api('openapi.yaml', 12 | arguments={'title': 'chomestatus API'}, 13 | pythonic_params=True) 14 | 15 | app.run(port=8080) 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/gen/py/chromestatus_openapi/chromestatus_openapi/controllers/__init__.py -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/controllers/security_controller.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | def info_from_XsrfToken(api_key, required_scopes): 5 | """ 6 | Check and retrieve authentication information from api_key. 7 | Returned value will be passed in 'token_info' parameter of your operation function, if there is one. 8 | 'sub' or 'uid' will be set in 'user' parameter of your operation function, if there is one. 9 | 10 | :param api_key API key provided by Authorization header 11 | :type api_key: str 12 | :param required_scopes Always None. Used for other authentication method 13 | :type required_scopes: None 14 | :return: Information attached to provided api_key or None if api_key is invalid or does not allow access to called API 15 | :rtype: dict | None 16 | """ 17 | return {'uid': 'user_id'} 18 | 19 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/encoder.py: -------------------------------------------------------------------------------- 1 | from connexion.apps.flask_app import FlaskJSONEncoder 2 | 3 | from chromestatus_openapi.models.base_model import Model 4 | 5 | 6 | class JSONEncoder(FlaskJSONEncoder): 7 | include_nulls = False 8 | 9 | def default(self, o): 10 | if isinstance(o, Model): 11 | dikt = {} 12 | for attr in o.openapi_types: 13 | value = getattr(o, attr) 14 | if value is None and not self.include_nulls: 15 | continue 16 | attr = o.attribute_map[attr] 17 | dikt[attr] = value 18 | return dikt 19 | return FlaskJSONEncoder.default(self, o) 20 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/test/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import connexion 4 | from flask_testing import TestCase 5 | 6 | from chromestatus_openapi.encoder import JSONEncoder 7 | 8 | 9 | class BaseTestCase(TestCase): 10 | 11 | def create_app(self): 12 | logging.getLogger('connexion.operation').setLevel('ERROR') 13 | app = connexion.App(__name__, specification_dir='../openapi/') 14 | app.app.json_encoder = JSONEncoder 15 | app.add_api('openapi.yaml', pythonic_params=True) 16 | return app.app 17 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/chromestatus_openapi/typing_utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if sys.version_info < (3, 7): 4 | import typing 5 | 6 | def is_generic(klass): 7 | """ Determine whether klass is a generic class """ 8 | return type(klass) == typing.GenericMeta 9 | 10 | def is_dict(klass): 11 | """ Determine whether klass is a Dict """ 12 | return klass.__extra__ == dict 13 | 14 | def is_list(klass): 15 | """ Determine whether klass is a List """ 16 | return klass.__extra__ == list 17 | 18 | else: 19 | 20 | def is_generic(klass): 21 | """ Determine whether klass is a generic class """ 22 | return hasattr(klass, '__origin__') 23 | 24 | def is_dict(klass): 25 | """ Determine whether klass is a Dict """ 26 | return klass.__origin__ == dict 27 | 28 | def is_list(klass): 29 | """ Determine whether klass is a List """ 30 | return klass.__origin__ == list 31 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/requirements.txt: -------------------------------------------------------------------------------- 1 | connexion[swagger-ui] >= 2.6.0; python_version>="3.6" 2 | # 2.3 is the last version that supports python 3.4-3.5 3 | connexion[swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=="3.4" 4 | # prevent breaking dependencies from advent of connexion>=3.0 5 | connexion[swagger-ui] <= 2.14.2; python_version>"3.4" 6 | # connexion requires werkzeug but connexion < 2.4.0 does not install werkzeug 7 | # we must peg werkzeug versions below to fix connexion 8 | # https://github.com/zalando/connexion/pull/1044 9 | werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4" 10 | swagger-ui-bundle >= 0.0.2 11 | python_dateutil >= 2.6.0 12 | setuptools >= 21.0.0 13 | Flask == 2.1.1 14 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/setup.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from setuptools import setup, find_packages 3 | 4 | NAME = "chromestatus_openapi" 5 | VERSION = "1.0.0" 6 | 7 | # To install the library, run the following 8 | # 9 | # python setup.py install 10 | # 11 | # prerequisite: setuptools 12 | # http://pypi.python.org/pypi/setuptools 13 | 14 | REQUIRES = [ 15 | "connexion>=2.0.2", 16 | "swagger-ui-bundle>=0.0.2", 17 | "python_dateutil>=2.6.0" 18 | ] 19 | 20 | setup( 21 | name=NAME, 22 | version=VERSION, 23 | description="chomestatus API", 24 | author_email="", 25 | url="", 26 | keywords=["OpenAPI", "chomestatus API"], 27 | install_requires=REQUIRES, 28 | packages=find_packages(), 29 | package_data={'': ['openapi/openapi.yaml']}, 30 | include_package_data=True, 31 | entry_points={ 32 | 'console_scripts': ['chromestatus_openapi=chromestatus_openapi.__main__:main']}, 33 | long_description="""\ 34 | The API for chromestatus.com. chromestatus.com is the official tool used for tracking feature launches in Blink (the browser engine that powers Chrome and many other web browsers). This tool guides feature owners through our launch process and serves as a primary source for developer information that then ripples throughout the web developer ecosystem. More details at: https://github.com/GoogleChrome/chromium-dashboard 35 | """ 36 | ) 37 | 38 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/test-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest~=7.1.0 2 | pytest-cov>=2.8.1 3 | pytest-randomly>=1.2.3 4 | Flask-Testing==0.8.1 5 | -------------------------------------------------------------------------------- /gen/py/chromestatus_openapi/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py3 3 | skipsdist=True 4 | 5 | [testenv] 6 | deps=-r{toxinidir}/requirements.txt 7 | -r{toxinidir}/test-requirements.txt 8 | {toxinidir} 9 | 10 | commands= 11 | pytest --cov=chromestatus_openapi 12 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/.github/workflows/python.yml: -------------------------------------------------------------------------------- 1 | # NOTE: This file is auto generated by OpenAPI Generator. 2 | # URL: https://openapi-generator.tech 3 | # 4 | # ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python 5 | 6 | name: webstatus_openapi Python package 7 | 8 | on: [push, pull_request] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Set up Python ${{ matrix.python-version }} 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: ${{ matrix.python-version }} 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install flake8 pytest 28 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 29 | if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi 30 | - name: Lint with flake8 31 | run: | 32 | # stop the build if there are Python syntax errors or undefined names 33 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 34 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 35 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 36 | - name: Test with pytest 37 | run: | 38 | pytest 39 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | venv/ 48 | .venv/ 49 | .python-version 50 | .pytest_cache 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # PyBuilder 63 | target/ 64 | 65 | #Ipython Notebook 66 | .ipynb_checkpoints 67 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # NOTE: This file is auto generated by OpenAPI Generator. 2 | # URL: https://openapi-generator.tech 3 | # 4 | # ref: https://docs.gitlab.com/ee/ci/README.html 5 | # ref: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml 6 | 7 | stages: 8 | - test 9 | 10 | .pytest: 11 | stage: test 12 | script: 13 | - pip install -r requirements.txt 14 | - pip install -r test-requirements.txt 15 | - pytest --cov=webstatus_openapi 16 | 17 | pytest-3.7: 18 | extends: .pytest 19 | image: python:3.7-alpine 20 | pytest-3.8: 21 | extends: .pytest 22 | image: python:3.8-alpine 23 | pytest-3.9: 24 | extends: .pytest 25 | image: python:3.9-alpine 26 | pytest-3.10: 27 | extends: .pytest 28 | image: python:3.10-alpine 29 | pytest-3.11: 30 | extends: .pytest 31 | image: python:3.11-alpine 32 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.6.0 2 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/.travis.yml: -------------------------------------------------------------------------------- 1 | # ref: https://docs.travis-ci.com/user/languages/python 2 | language: python 3 | python: 4 | - "3.7" 5 | - "3.8" 6 | - "3.9" 7 | - "3.10" 8 | - "3.11" 9 | # uncomment the following if needed 10 | #- "3.11-dev" # 3.11 development branch 11 | #- "nightly" # nightly build 12 | # command to install dependencies 13 | install: 14 | - "pip install -r requirements.txt" 15 | - "pip install -r test-requirements.txt" 16 | # command to run tests 17 | script: pytest --cov=webstatus_openapi 18 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/BaselineInfo.md: -------------------------------------------------------------------------------- 1 | # BaselineInfo 2 | 3 | Contains baseline information for a feature. 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | **status** | **str** | | [optional] 10 | **low_date** | **date** | | [optional] 11 | **high_date** | **date** | | [optional] 12 | 13 | ## Example 14 | 15 | ```python 16 | from webstatus_openapi.models.baseline_info import BaselineInfo 17 | 18 | # TODO update the JSON string below 19 | json = "{}" 20 | # create an instance of BaselineInfo from a JSON string 21 | baseline_info_instance = BaselineInfo.from_json(json) 22 | # print the JSON string representation of the object 23 | print(BaselineInfo.to_json()) 24 | 25 | # convert the object into a dict 26 | baseline_info_dict = baseline_info_instance.to_dict() 27 | # create an instance of BaselineInfo from a dict 28 | baseline_info_from_dict = BaselineInfo.from_dict(baseline_info_dict) 29 | ``` 30 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 31 | 32 | 33 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/BasicErrorModel.md: -------------------------------------------------------------------------------- 1 | # BasicErrorModel 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **message** | **str** | | 9 | **code** | **int** | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.basic_error_model import BasicErrorModel 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of BasicErrorModel from a JSON string 19 | basic_error_model_instance = BasicErrorModel.from_json(json) 20 | # print the JSON string representation of the object 21 | print(BasicErrorModel.to_json()) 22 | 23 | # convert the object into a dict 24 | basic_error_model_dict = basic_error_model_instance.to_dict() 25 | # create an instance of BasicErrorModel from a dict 26 | basic_error_model_from_dict = BasicErrorModel.from_dict(basic_error_model_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/BrowserImplementation.md: -------------------------------------------------------------------------------- 1 | # BrowserImplementation 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **status** | **str** | | [optional] 9 | **var_date** | **date** | The date on which the feature was implemented in a browser. (RFC 3339, section 5.6, for example, 2017-07-21) | [optional] 10 | **version** | **str** | The browser version in which the feature became available. | [optional] 11 | 12 | ## Example 13 | 14 | ```python 15 | from webstatus_openapi.models.browser_implementation import BrowserImplementation 16 | 17 | # TODO update the JSON string below 18 | json = "{}" 19 | # create an instance of BrowserImplementation from a JSON string 20 | browser_implementation_instance = BrowserImplementation.from_json(json) 21 | # print the JSON string representation of the object 22 | print(BrowserImplementation.to_json()) 23 | 24 | # convert the object into a dict 25 | browser_implementation_dict = browser_implementation_instance.to_dict() 26 | # create an instance of BrowserImplementation from a dict 27 | browser_implementation_from_dict = BrowserImplementation.from_dict(browser_implementation_dict) 28 | ``` 29 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 30 | 31 | 32 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/BrowserReleaseFeatureMetricsPage.md: -------------------------------------------------------------------------------- 1 | # BrowserReleaseFeatureMetricsPage 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **metadata** | [**PageMetadata**](PageMetadata.md) | | [optional] 9 | **data** | [**List[BrowserReleaseFeatureMetric]**](BrowserReleaseFeatureMetric.md) | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.browser_release_feature_metrics_page import BrowserReleaseFeatureMetricsPage 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of BrowserReleaseFeatureMetricsPage from a JSON string 19 | browser_release_feature_metrics_page_instance = BrowserReleaseFeatureMetricsPage.from_json(json) 20 | # print the JSON string representation of the object 21 | print(BrowserReleaseFeatureMetricsPage.to_json()) 22 | 23 | # convert the object into a dict 24 | browser_release_feature_metrics_page_dict = browser_release_feature_metrics_page_instance.to_dict() 25 | # create an instance of BrowserReleaseFeatureMetricsPage from a dict 26 | browser_release_feature_metrics_page_from_dict = BrowserReleaseFeatureMetricsPage.from_dict(browser_release_feature_metrics_page_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/BrowserUsage.md: -------------------------------------------------------------------------------- 1 | # BrowserUsage 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **chromium** | [**ChromiumUsageInfo**](ChromiumUsageInfo.md) | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.browser_usage import BrowserUsage 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of BrowserUsage from a JSON string 18 | browser_usage_instance = BrowserUsage.from_json(json) 19 | # print the JSON string representation of the object 20 | print(BrowserUsage.to_json()) 21 | 22 | # convert the object into a dict 23 | browser_usage_dict = browser_usage_instance.to_dict() 24 | # create an instance of BrowserUsage from a dict 25 | browser_usage_from_dict = BrowserUsage.from_dict(browser_usage_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/CanIUseInfo.md: -------------------------------------------------------------------------------- 1 | # CanIUseInfo 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **items** | [**List[CanIUseItem]**](CanIUseItem.md) | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.can_i_use_info import CanIUseInfo 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of CanIUseInfo from a JSON string 18 | can_i_use_info_instance = CanIUseInfo.from_json(json) 19 | # print the JSON string representation of the object 20 | print(CanIUseInfo.to_json()) 21 | 22 | # convert the object into a dict 23 | can_i_use_info_dict = can_i_use_info_instance.to_dict() 24 | # create an instance of CanIUseInfo from a dict 25 | can_i_use_info_from_dict = CanIUseInfo.from_dict(can_i_use_info_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/CanIUseItem.md: -------------------------------------------------------------------------------- 1 | # CanIUseItem 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **id** | **str** | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.can_i_use_item import CanIUseItem 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of CanIUseItem from a JSON string 18 | can_i_use_item_instance = CanIUseItem.from_json(json) 19 | # print the JSON string representation of the object 20 | print(CanIUseItem.to_json()) 21 | 22 | # convert the object into a dict 23 | can_i_use_item_dict = can_i_use_item_instance.to_dict() 24 | # create an instance of CanIUseItem from a dict 25 | can_i_use_item_from_dict = CanIUseItem.from_dict(can_i_use_item_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/ChromiumDailyStatsPage.md: -------------------------------------------------------------------------------- 1 | # ChromiumDailyStatsPage 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **metadata** | [**PageMetadata**](PageMetadata.md) | | [optional] 9 | **data** | [**List[ChromiumUsageStat]**](ChromiumUsageStat.md) | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.chromium_daily_stats_page import ChromiumDailyStatsPage 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of ChromiumDailyStatsPage from a JSON string 19 | chromium_daily_stats_page_instance = ChromiumDailyStatsPage.from_json(json) 20 | # print the JSON string representation of the object 21 | print(ChromiumDailyStatsPage.to_json()) 22 | 23 | # convert the object into a dict 24 | chromium_daily_stats_page_dict = chromium_daily_stats_page_instance.to_dict() 25 | # create an instance of ChromiumDailyStatsPage from a dict 26 | chromium_daily_stats_page_from_dict = ChromiumDailyStatsPage.from_dict(chromium_daily_stats_page_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/ChromiumUsageInfo.md: -------------------------------------------------------------------------------- 1 | # ChromiumUsageInfo 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **daily** | **float** | Latest snapshot of the usage metric for the given feature. | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.chromium_usage_info import ChromiumUsageInfo 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of ChromiumUsageInfo from a JSON string 18 | chromium_usage_info_instance = ChromiumUsageInfo.from_json(json) 19 | # print the JSON string representation of the object 20 | print(ChromiumUsageInfo.to_json()) 21 | 22 | # convert the object into a dict 23 | chromium_usage_info_dict = chromium_usage_info_instance.to_dict() 24 | # create an instance of ChromiumUsageInfo from a dict 25 | chromium_usage_info_from_dict = ChromiumUsageInfo.from_dict(chromium_usage_info_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/ChromiumUsageStat.md: -------------------------------------------------------------------------------- 1 | # ChromiumUsageStat 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **timestamp** | **datetime** | The usage timestamp | 9 | **usage** | **float** | Snapshot of the usage metric for the given feature | [optional] 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.chromium_usage_stat import ChromiumUsageStat 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of ChromiumUsageStat from a JSON string 19 | chromium_usage_stat_instance = ChromiumUsageStat.from_json(json) 20 | # print the JSON string representation of the object 21 | print(ChromiumUsageStat.to_json()) 22 | 23 | # convert the object into a dict 24 | chromium_usage_stat_dict = chromium_usage_stat_instance.to_dict() 25 | # create an instance of ChromiumUsageStat from a dict 26 | chromium_usage_stat_from_dict = ChromiumUsageStat.from_dict(chromium_usage_stat_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/ExtendedErrorModel.md: -------------------------------------------------------------------------------- 1 | # ExtendedErrorModel 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **message** | **str** | | 9 | **code** | **int** | | 10 | **root_cause** | **str** | | 11 | 12 | ## Example 13 | 14 | ```python 15 | from webstatus_openapi.models.extended_error_model import ExtendedErrorModel 16 | 17 | # TODO update the JSON string below 18 | json = "{}" 19 | # create an instance of ExtendedErrorModel from a JSON string 20 | extended_error_model_instance = ExtendedErrorModel.from_json(json) 21 | # print the JSON string representation of the object 22 | print(ExtendedErrorModel.to_json()) 23 | 24 | # convert the object into a dict 25 | extended_error_model_dict = extended_error_model_instance.to_dict() 26 | # create an instance of ExtendedErrorModel from a dict 27 | extended_error_model_from_dict = ExtendedErrorModel.from_dict(extended_error_model_dict) 28 | ``` 29 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 30 | 31 | 32 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/FeatureMetadata.md: -------------------------------------------------------------------------------- 1 | # FeatureMetadata 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **can_i_use** | [**CanIUseInfo**](CanIUseInfo.md) | | [optional] 9 | **description** | **str** | | [optional] 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.feature_metadata import FeatureMetadata 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of FeatureMetadata from a JSON string 19 | feature_metadata_instance = FeatureMetadata.from_json(json) 20 | # print the JSON string representation of the object 21 | print(FeatureMetadata.to_json()) 22 | 23 | # convert the object into a dict 24 | feature_metadata_dict = feature_metadata_instance.to_dict() 25 | # create an instance of FeatureMetadata from a dict 26 | feature_metadata_from_dict = FeatureMetadata.from_dict(feature_metadata_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/FeaturePage.md: -------------------------------------------------------------------------------- 1 | # FeaturePage 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **metadata** | [**PageMetadataWithTotal**](PageMetadataWithTotal.md) | | 9 | **data** | [**List[Feature]**](Feature.md) | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.feature_page import FeaturePage 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of FeaturePage from a JSON string 19 | feature_page_instance = FeaturePage.from_json(json) 20 | # print the JSON string representation of the object 21 | print(FeaturePage.to_json()) 22 | 23 | # convert the object into a dict 24 | feature_page_dict = feature_page_instance.to_dict() 25 | # create an instance of FeaturePage from a dict 26 | feature_page_from_dict = FeaturePage.from_dict(feature_page_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/FeatureSpecInfo.md: -------------------------------------------------------------------------------- 1 | # FeatureSpecInfo 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **links** | [**List[SpecLink]**](SpecLink.md) | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.feature_spec_info import FeatureSpecInfo 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of FeatureSpecInfo from a JSON string 18 | feature_spec_info_instance = FeatureSpecInfo.from_json(json) 19 | # print the JSON string representation of the object 20 | print(FeatureSpecInfo.to_json()) 21 | 22 | # convert the object into a dict 23 | feature_spec_info_dict = feature_spec_info_instance.to_dict() 24 | # create an instance of FeatureSpecInfo from a dict 25 | feature_spec_info_from_dict = FeatureSpecInfo.from_dict(feature_spec_info_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/GenericUpdatableUniqueModel.md: -------------------------------------------------------------------------------- 1 | # GenericUpdatableUniqueModel 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **id** | **str** | | 9 | **updated_at** | **datetime** | | [optional] 10 | **created_at** | **datetime** | | 11 | 12 | ## Example 13 | 14 | ```python 15 | from webstatus_openapi.models.generic_updatable_unique_model import GenericUpdatableUniqueModel 16 | 17 | # TODO update the JSON string below 18 | json = "{}" 19 | # create an instance of GenericUpdatableUniqueModel from a JSON string 20 | generic_updatable_unique_model_instance = GenericUpdatableUniqueModel.from_json(json) 21 | # print the JSON string representation of the object 22 | print(GenericUpdatableUniqueModel.to_json()) 23 | 24 | # convert the object into a dict 25 | generic_updatable_unique_model_dict = generic_updatable_unique_model_instance.to_dict() 26 | # create an instance of GenericUpdatableUniqueModel from a dict 27 | generic_updatable_unique_model_from_dict = GenericUpdatableUniqueModel.from_dict(generic_updatable_unique_model_dict) 28 | ``` 29 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 30 | 31 | 32 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/PageMetadata.md: -------------------------------------------------------------------------------- 1 | # PageMetadata 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **next_page_token** | **str** | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.page_metadata import PageMetadata 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of PageMetadata from a JSON string 18 | page_metadata_instance = PageMetadata.from_json(json) 19 | # print the JSON string representation of the object 20 | print(PageMetadata.to_json()) 21 | 22 | # convert the object into a dict 23 | page_metadata_dict = page_metadata_instance.to_dict() 24 | # create an instance of PageMetadata from a dict 25 | page_metadata_from_dict = PageMetadata.from_dict(page_metadata_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/PageMetadataWithTotal.md: -------------------------------------------------------------------------------- 1 | # PageMetadataWithTotal 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **next_page_token** | **str** | | [optional] 9 | **total** | **int** | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.page_metadata_with_total import PageMetadataWithTotal 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of PageMetadataWithTotal from a JSON string 19 | page_metadata_with_total_instance = PageMetadataWithTotal.from_json(json) 20 | # print the JSON string representation of the object 21 | print(PageMetadataWithTotal.to_json()) 22 | 23 | # convert the object into a dict 24 | page_metadata_with_total_dict = page_metadata_with_total_instance.to_dict() 25 | # create an instance of PageMetadataWithTotal from a dict 26 | page_metadata_with_total_from_dict = PageMetadataWithTotal.from_dict(page_metadata_with_total_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/SavedSearch.md: -------------------------------------------------------------------------------- 1 | # SavedSearch 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **name** | **str** | | 9 | **query** | **str** | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.saved_search import SavedSearch 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of SavedSearch from a JSON string 19 | saved_search_instance = SavedSearch.from_json(json) 20 | # print the JSON string representation of the object 21 | print(SavedSearch.to_json()) 22 | 23 | # convert the object into a dict 24 | saved_search_dict = saved_search_instance.to_dict() 25 | # create an instance of SavedSearch from a dict 26 | saved_search_from_dict = SavedSearch.from_dict(saved_search_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/SavedSearchPage.md: -------------------------------------------------------------------------------- 1 | # SavedSearchPage 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **metadata** | [**PageMetadata**](PageMetadata.md) | | [optional] 9 | **data** | [**List[SavedSearchResponse]**](SavedSearchResponse.md) | | [optional] 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.saved_search_page import SavedSearchPage 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of SavedSearchPage from a JSON string 19 | saved_search_page_instance = SavedSearchPage.from_json(json) 20 | # print the JSON string representation of the object 21 | print(SavedSearchPage.to_json()) 22 | 23 | # convert the object into a dict 24 | saved_search_page_dict = saved_search_page_instance.to_dict() 25 | # create an instance of SavedSearchPage from a dict 26 | saved_search_page_from_dict = SavedSearchPage.from_dict(saved_search_page_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/SpecLink.md: -------------------------------------------------------------------------------- 1 | # SpecLink 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **link** | **str** | | [optional] 9 | 10 | ## Example 11 | 12 | ```python 13 | from webstatus_openapi.models.spec_link import SpecLink 14 | 15 | # TODO update the JSON string below 16 | json = "{}" 17 | # create an instance of SpecLink from a JSON string 18 | spec_link_instance = SpecLink.from_json(json) 19 | # print the JSON string representation of the object 20 | print(SpecLink.to_json()) 21 | 22 | # convert the object into a dict 23 | spec_link_dict = spec_link_instance.to_dict() 24 | # create an instance of SpecLink from a dict 25 | spec_link_from_dict = SpecLink.from_dict(spec_link_dict) 26 | ``` 27 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 28 | 29 | 30 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/SupportedBrowsers.md: -------------------------------------------------------------------------------- 1 | # SupportedBrowsers 2 | 3 | List of supported browsers that webstatus.dev currently ingests 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | 10 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 11 | 12 | 13 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/WPTFeatureData.md: -------------------------------------------------------------------------------- 1 | # WPTFeatureData 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **score** | **float** | | [optional] 9 | **metadata** | **Dict[str, object]** | Contains optional metadata about the metric. This key-value pair is to be considered unstable and can change at any moment. If a field here becomes mature, we can add it to the main WPTFeatureData definition. | [optional] 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.wpt_feature_data import WPTFeatureData 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of WPTFeatureData from a JSON string 19 | wpt_feature_data_instance = WPTFeatureData.from_json(json) 20 | # print the JSON string representation of the object 21 | print(WPTFeatureData.to_json()) 22 | 23 | # convert the object into a dict 24 | wpt_feature_data_dict = wpt_feature_data_instance.to_dict() 25 | # create an instance of WPTFeatureData from a dict 26 | wpt_feature_data_from_dict = WPTFeatureData.from_dict(wpt_feature_data_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/WPTMetricView.md: -------------------------------------------------------------------------------- 1 | # WPTMetricView 2 | 3 | The desired view of the WPT Data 4 | 5 | ## Properties 6 | 7 | Name | Type | Description | Notes 8 | ------------ | ------------- | ------------- | ------------- 9 | 10 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 11 | 12 | 13 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/WPTRunMetric.md: -------------------------------------------------------------------------------- 1 | # WPTRunMetric 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **run_timestamp** | **datetime** | The start timestamp of the run. | 9 | **total_tests_count** | **int** | Total number of tests | [optional] 10 | **test_pass_count** | **int** | Number of passing tests | [optional] 11 | 12 | ## Example 13 | 14 | ```python 15 | from webstatus_openapi.models.wpt_run_metric import WPTRunMetric 16 | 17 | # TODO update the JSON string below 18 | json = "{}" 19 | # create an instance of WPTRunMetric from a JSON string 20 | wpt_run_metric_instance = WPTRunMetric.from_json(json) 21 | # print the JSON string representation of the object 22 | print(WPTRunMetric.to_json()) 23 | 24 | # convert the object into a dict 25 | wpt_run_metric_dict = wpt_run_metric_instance.to_dict() 26 | # create an instance of WPTRunMetric from a dict 27 | wpt_run_metric_from_dict = WPTRunMetric.from_dict(wpt_run_metric_dict) 28 | ``` 29 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 30 | 31 | 32 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/docs/WPTRunMetricsPage.md: -------------------------------------------------------------------------------- 1 | # WPTRunMetricsPage 2 | 3 | 4 | ## Properties 5 | 6 | Name | Type | Description | Notes 7 | ------------ | ------------- | ------------- | ------------- 8 | **metadata** | [**PageMetadata**](PageMetadata.md) | | [optional] 9 | **data** | [**List[WPTRunMetric]**](WPTRunMetric.md) | | 10 | 11 | ## Example 12 | 13 | ```python 14 | from webstatus_openapi.models.wpt_run_metrics_page import WPTRunMetricsPage 15 | 16 | # TODO update the JSON string below 17 | json = "{}" 18 | # create an instance of WPTRunMetricsPage from a JSON string 19 | wpt_run_metrics_page_instance = WPTRunMetricsPage.from_json(json) 20 | # print the JSON string representation of the object 21 | print(WPTRunMetricsPage.to_json()) 22 | 23 | # convert the object into a dict 24 | wpt_run_metrics_page_dict = wpt_run_metrics_page_instance.to_dict() 25 | # create an instance of WPTRunMetricsPage from a dict 26 | wpt_run_metrics_page_from_dict = WPTRunMetricsPage.from_dict(wpt_run_metrics_page_dict) 27 | ``` 28 | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) 29 | 30 | 31 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/requirements.txt: -------------------------------------------------------------------------------- 1 | python_dateutil >= 2.5.3 2 | setuptools >= 21.0.0 3 | urllib3 >= 1.25.3, < 2.1.0 4 | pydantic >= 2 5 | typing-extensions >= 4.7.1 6 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length=99 3 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/test-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest~=7.1.3 2 | pytest-cov>=2.8.1 3 | pytest-randomly>=3.12.0 4 | mypy>=1.4.1 5 | types-python-dateutil>=2.8.19 6 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/gen/py/webstatus_openapi/test/__init__.py -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/test/test_supported_browsers.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | webstatus.dev API 5 | 6 | A tool to monitor and track the status of all Web Platform features across dimensions that are related to availability and implementation quality across browsers, and adoption by web developers. 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from webstatus_openapi.models.supported_browsers import SupportedBrowsers 18 | 19 | class TestSupportedBrowsers(unittest.TestCase): 20 | """SupportedBrowsers unit test stubs""" 21 | 22 | def setUp(self): 23 | pass 24 | 25 | def tearDown(self): 26 | pass 27 | 28 | def testSupportedBrowsers(self): 29 | """Test SupportedBrowsers""" 30 | # inst = SupportedBrowsers() 31 | 32 | if __name__ == '__main__': 33 | unittest.main() 34 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/test/test_wpt_metric_view.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | webstatus.dev API 5 | 6 | A tool to monitor and track the status of all Web Platform features across dimensions that are related to availability and implementation quality across browsers, and adoption by web developers. 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | import unittest 16 | 17 | from webstatus_openapi.models.wpt_metric_view import WPTMetricView 18 | 19 | class TestWPTMetricView(unittest.TestCase): 20 | """WPTMetricView unit test stubs""" 21 | 22 | def setUp(self): 23 | pass 24 | 25 | def tearDown(self): 26 | pass 27 | 28 | def testWPTMetricView(self): 29 | """Test WPTMetricView""" 30 | # inst = WPTMetricView() 31 | 32 | if __name__ == '__main__': 33 | unittest.main() 34 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py3 3 | 4 | [testenv] 5 | deps=-r{toxinidir}/requirements.txt 6 | -r{toxinidir}/test-requirements.txt 7 | 8 | commands= 9 | pytest --cov=webstatus_openapi 10 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.4 2 | Name: webstatus-openapi 3 | Version: 1.0.0 4 | Summary: webstatus.dev API 5 | Home-page: 6 | Author: OpenAPI Generator community 7 | Author-email: team@openapitools.org 8 | Keywords: OpenAPI,OpenAPI-Generator,webstatus.dev API 9 | Description-Content-Type: text/markdown 10 | Requires-Dist: urllib3<2.1.0,>=1.25.3 11 | Requires-Dist: python-dateutil 12 | Requires-Dist: pydantic>=2 13 | Requires-Dist: typing-extensions>=4.7.1 14 | Dynamic: author 15 | Dynamic: author-email 16 | Dynamic: description 17 | Dynamic: description-content-type 18 | Dynamic: keywords 19 | Dynamic: requires-dist 20 | Dynamic: summary 21 | 22 | A tool to monitor and track the status of all Web Platform features across dimensions that are related to availability and implementation quality across browsers, and adoption by web developers. 23 | 24 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi.egg-info/requires.txt: -------------------------------------------------------------------------------- 1 | urllib3<2.1.0,>=1.25.3 2 | python-dateutil 3 | pydantic>=2 4 | typing-extensions>=4.7.1 5 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | webstatus_openapi 2 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi/api/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | 3 | # import apis into api package 4 | from webstatus_openapi.api.default_api import DefaultApi 5 | 6 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi/api_response.py: -------------------------------------------------------------------------------- 1 | """API response object.""" 2 | 3 | from __future__ import annotations 4 | from typing import Optional, Generic, Mapping, TypeVar 5 | from pydantic import Field, StrictInt, StrictBytes, BaseModel 6 | 7 | T = TypeVar("T") 8 | 9 | class ApiResponse(BaseModel, Generic[T]): 10 | """ 11 | API response object 12 | """ 13 | 14 | status_code: StrictInt = Field(description="HTTP status code") 15 | headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers") 16 | data: T = Field(description="Deserialized data given the data type") 17 | raw_data: StrictBytes = Field(description="Raw data (HTTP response body)") 18 | 19 | model_config = { 20 | "arbitrary_types_allowed": True 21 | } 22 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi/models/supported_browsers.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | webstatus.dev API 5 | 6 | A tool to monitor and track the status of all Web Platform features across dimensions that are related to availability and implementation quality across browsers, and adoption by web developers. 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | from __future__ import annotations 16 | import json 17 | from enum import Enum 18 | from typing_extensions import Self 19 | 20 | 21 | class SupportedBrowsers(str, Enum): 22 | """ 23 | List of supported browsers that webstatus.dev currently ingests 24 | """ 25 | 26 | """ 27 | allowed enum values 28 | """ 29 | CHROME = 'chrome' 30 | FIREFOX = 'firefox' 31 | SAFARI = 'safari' 32 | EDGE = 'edge' 33 | 34 | @classmethod 35 | def from_json(cls, json_str: str) -> Self: 36 | """Create an instance of SupportedBrowsers from a JSON string""" 37 | return cls(json.loads(json_str)) 38 | 39 | 40 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi/models/wpt_metric_view.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | webstatus.dev API 5 | 6 | A tool to monitor and track the status of all Web Platform features across dimensions that are related to availability and implementation quality across browsers, and adoption by web developers. 7 | 8 | The version of the OpenAPI document: 0.1.0 9 | Generated by OpenAPI Generator (https://openapi-generator.tech) 10 | 11 | Do not edit the class manually. 12 | """ # noqa: E501 13 | 14 | 15 | from __future__ import annotations 16 | import json 17 | from enum import Enum 18 | from typing_extensions import Self 19 | 20 | 21 | class WPTMetricView(str, Enum): 22 | """ 23 | The desired view of the WPT Data 24 | """ 25 | 26 | """ 27 | allowed enum values 28 | """ 29 | TEST_COUNTS = 'test_counts' 30 | SUBTEST_COUNTS = 'subtest_counts' 31 | 32 | @classmethod 33 | def from_json(cls, json_str: str) -> Self: 34 | """Create an instance of WPTMetricView from a JSON string""" 35 | return cls(json.loads(json_str)) 36 | 37 | 38 | -------------------------------------------------------------------------------- /gen/py/webstatus_openapi/webstatus_openapi/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/gen/py/webstatus_openapi/webstatus_openapi/py.typed -------------------------------------------------------------------------------- /internals/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/internals/__init__.py -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_activated_email.html: -------------------------------------------------------------------------------- 1 |

2 | Your trial creation request for Example Trial has been approved 3 | and processed. The setup is now complete and the trial can be seen in the 4 | OT console at: https://origintrials-staging.corp.google.com/origintrials/#/view_trial/111222333 5 |
6 | These changes have also been applied to the trial entry at: https://chromestatus.com/feature/1 7 |

8 | Thanks,
9 | Origin Trials team 10 |

-------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_activation_failed_email.html: -------------------------------------------------------------------------------- 1 |

An automated origin trial activation has failed to process

2 |

3 | Trial Name: Example Trial 4 |
5 | Trial ID: 111222333 6 |
7 | Chromestatus URL: https://chromestatus.com/feature/1 8 |
9 | Scheduled activation date: 2030-01-01 10 |

-------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_beta_availability_email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome 126 will soon arrive on the 2 | beta channel.

3 | Check that your feature (Some feature) shows up correctly under the origin trials 4 | section of the roadmap https://chromestatus.com/roadmap. This will automatically 5 | get it included in the blog post about Chrome 126 beta, which 6 | will go live on https://developer.chrome.com/tags/beta/. If you previously 7 | published a blog post allowing developers to sign up for tokens for your 8 | feature, this will be linked in the beta blog post. 9 |

P.S. This email was generated automatically (for 10 | details, see go/running-an-origin-trial). 11 | Please contact origin-trials-support@google.com if this email is incorrect or not useful. -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_creation_approved_email.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 |
7 |

8 | All prerequisite reviews have been completed and you can now submit a 9 | request to create your origin trial. Click the "Request Trial Creation" 10 | button on the Origin Trial section of your feature's detail page. 12 |

13 |

14 | Note: Only feature owners signed in with a 15 | "chromium.org" or "google.com" domain email address will have access to 16 | the trial creation form, and at least 1 Googler contact is required 17 | during form submission to continue the trial creation process. If you 18 | have any questions or need assistance, reach out to origin-trials-support@google.com. 21 |

22 | Thanks,
23 | Origin Trials team 24 |

25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_creation_processed_email.html: -------------------------------------------------------------------------------- 1 |

2 | Your trial creation request for Example Trial has been approved 3 | and processed. The trial is slated to begin with the Chrome stable release 4 | for 100. We'll notify you again when the 5 | trial has been activated and is available for registration in the 6 | OT Console. 7 |
8 | These changes have also been applied to the trial entry at: 9 | https://chromestatus.com/feature/1 10 |

11 | Thanks,
12 | Origin Trials team 13 |

-------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_creation_request_failed_email.html: -------------------------------------------------------------------------------- 1 |

An automated origin trial request has failed to process

2 |

3 | Error text: Something went pretty wrong 4 |

5 |

6 | Stage ID: 237 7 |
8 | Origin trial ID (if available): -1239058 9 |
10 | Requested by: feature_owner@google.com 11 |
12 | Additional contacts for your team?: [] 13 |
14 | Feature name: Example Trial 15 |
16 | Feature description: OT description 17 |
18 | Start Chrome milestone: 100 19 |
20 | End Chrome milestone: 106 21 |
22 | Chromium trial name: ExampleTrial 23 |
24 | Is this a deprecation trial?: True 25 |
26 | Third party origin support: True 27 |
28 | WebFeature UseCounter value: None 29 |
30 | Documentation link: https://example.com/docs 31 |
32 | Chromestatus link: https://chromestatus.com/feature/1 33 |
34 | Feature feedback link: https://example.com/feedback 35 |
36 | Intent to Experiment link: https://example.com/experiment 37 |
38 | Is this a critical trial?: False 39 |
40 |
41 | Instructions for handling this request can be found at: 42 | https://g3doc.corp.google.com/chrome/origin_trials/g3doc/trial_admin.md?cl=head#setup-a-new-trial 43 |

-------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_ending_next_release_email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome 126 landed on the stable 2 | channel one week ago. The branch point of Chrome 127 occurs 3 | 2030-01-01, which will be the first release after the end of your 4 | trial.

5 | This is the point to be making the decision about what happens at the end of the 6 | trial. Options include: 7 |
    8 |
  1. Ship the feature, which requires an Intent to Ship
  2. 9 |
  3. Continue experimenting with the feature in a new trial, which requires an 10 | Intent to Continue Experimenting
  4. 11 |
  5. 12 | Let the origin trial finish and be disabled in Chrome 127. 13 |
  6. 14 |
15 |

P.S. This email was generated automatically (for 16 | details, see go/running-an-origin-trial). 17 | Please contact origin-trials-support@google.com if this email is incorrect or not useful. -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_ending_this_release_email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome 126 landed on the 2 | stable channel one week ago, so you should have now shared with blink-dev the 3 | things you've learned based on the feedback gathered from developers during 4 | token renewal. 5 | Also, you should share your plans for Chrome 127, which will be 6 | the first release after the end of your trial. 7 |

P.S. This email was generated automatically (for 8 | details, see go/running-an-origin-trial). 9 | Please contact origin-trials-support@google.com if this email is incorrect or not useful. -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_extended_request_email.html: -------------------------------------------------------------------------------- 1 |

2 | A recent extension request was finalized and processed. 3 |
4 | Requested by: user2@example.com 5 |
6 | Feature name: An existing origin trial 7 |
8 | Intent to Extend Experiment URL: https://example.com/intent 9 |
10 | New end milestone: 106 11 |
12 |
13 | No additional action needs to be taken if this information looks correct. 14 |

-------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_first_branch_email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome 126 branch is 2 | 2030-01-01. This release will contain your feature as an origin trial. 3 |

4 | You should aim to post a blog post on https://developer.chrome.com/blog/ as 5 | soon as possible so you can begin to get origin trials sign ups early 6 | (which means you get feedback earlier!). If you are already working with 7 | someone from Chrome Web Developer Relations they can help you with this. 8 | Otherwise, reach out to chrome-devrel-content@google.com for help. 9 |

P.S. This email was generated automatically (for 10 | details, see go/running-an-origin-trial). 11 | Please contact origin-trials-support@google.com if this email is incorrect or not useful. -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_last_branch_email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome 126 is branching 2 | 2030-01-01. This release will be the final one to include your feature as 3 | an origin trial. 4 |

Code you land from here on will land in the first 5 | release after the origin trial is over. 6 |

P.S. This email was generated automatically (for 7 | details, see go/running-an-origin-trial). 8 | Please contact origin-trials-support@google.com if this email is incorrect or not useful. -------------------------------------------------------------------------------- /internals/testdata/notifier_test/test_make_ot_process_email.html: -------------------------------------------------------------------------------- 1 | Hello! This is your friendly neighborhood automated reminder script here. I just ran on 2030-01-01 and 2 | identified the following facts: 3 | 14 | Could you please double check my work and make sure I sent the right emails? 15 | I'm looking forward to slowly replacing you through the 16 | inexorable tide of automation!

17 | <3

18 | -Your future robot overlord -------------------------------------------------------------------------------- /internals/testdata/reminders_test/test_build_gate_email_tasks__initial_due.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

The Enterprise review 5 | of feature one 6 | is now due for an initial response.

7 | 8 | -------------------------------------------------------------------------------- /internals/testdata/reminders_test/test_build_gate_email_tasks__initial_overdue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

The Enterprise review 5 | of feature one 6 | is now overdue for an initial response.

7 | 8 |

All potential reviewers are being notified, 9 | even if the review was previously assigned to one reviewer.

10 | 11 | -------------------------------------------------------------------------------- /internals/testdata/reminders_test/test_build_gate_email_tasks__resolution_due.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

The Enterprise review 5 | of feature one 6 | is now due for a resolution.

7 | 8 | -------------------------------------------------------------------------------- /internals/testdata/reminders_test/test_build_gate_email_tasks__resolution_overdue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

The Enterprise review 5 | of feature one 6 | is now overdue for a resolution.

7 | 8 |

All potential reviewers are being notified, 9 | even if the review was previously assigned to one reviewer.

10 | 11 | -------------------------------------------------------------------------------- /internals/webdx_feature_models.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from google.cloud import ndb # type: ignore 16 | 17 | 18 | class WebdxFeatures(ndb.Model): 19 | """A singleton model to store Webdx feature IDs""" 20 | feature_ids = ndb.StringProperty(repeated=True) 21 | 22 | @classmethod 23 | def get_webdx_feature_id_list(cls): 24 | fetch_results = cls.query().fetch(1) 25 | if not fetch_results: 26 | return None 27 | 28 | return fetch_results[0] 29 | 30 | @classmethod 31 | def store_webdx_feature_id_list(cls, new_list: list[str]): 32 | webdx_features = WebdxFeatures.get_webdx_feature_id_list() 33 | if not webdx_features: 34 | webdx_features = WebdxFeatures(feature_ids=new_list) 35 | else: 36 | webdx_features.feature_ids = new_list 37 | webdx_features.put() 38 | -------------------------------------------------------------------------------- /notifier.staging.yaml: -------------------------------------------------------------------------------- 1 | runtime: python313 2 | service: notifier 3 | instance_class: F4_1G 4 | 5 | handlers: 6 | - url: /tasks/detect-intent 7 | script: auto 8 | # Header checks prevent raw access to this handler. Tasks have headers. 9 | 10 | - url: /tasks/email-subscribers 11 | script: auto 12 | # Header checks prevent raw access to this handler. Tasks have headers. 13 | 14 | - url: /tasks/email-reviewers 15 | script: auto 16 | # Header checks prevent raw access to this handler. Tasks have headers. 17 | 18 | - url: /tasks/email-comments 19 | script: auto 20 | # Header checks prevent raw access to this handler. Tasks have headers. 21 | 22 | app_engine_apis: true 23 | 24 | # Set up VPC Access Connector for Redis. 25 | vpc_access_connector: 26 | name: projects/cr-status-staging/locations/us-central1/connectors/redis-connector 27 | 28 | env_variables: 29 | # Redis envs 30 | REDISHOST: '10.231.56.251' 31 | REDISPORT: '6379' 32 | -------------------------------------------------------------------------------- /notifier.yaml: -------------------------------------------------------------------------------- 1 | runtime: python313 2 | service: notifier 3 | instance_class: F4_1G 4 | 5 | handlers: 6 | - url: /tasks/detect-intent 7 | script: auto 8 | # Header checks prevent raw access to this handler. Tasks have headers. 9 | 10 | - url: /tasks/email-subscribers 11 | script: auto 12 | # Header checks prevent raw access to this handler. Tasks have headers. 13 | 14 | - url: /tasks/email-reviewers 15 | script: auto 16 | # Header checks prevent raw access to this handler. Tasks have headers. 17 | 18 | - url: /tasks/email-comments 19 | script: auto 20 | # Header checks prevent raw access to this handler. Tasks have headers. 21 | 22 | app_engine_apis: true 23 | 24 | # Set up VPC Access Connector for Redis in prod. 25 | vpc_access_connector: 26 | name: projects/cr-status/locations/us-central1/connectors/redis-connector 27 | 28 | env_variables: 29 | # Redis envs for prod 30 | REDISHOST: '10.250.3.187' 31 | REDISPORT: '6379' 32 | -------------------------------------------------------------------------------- /openapi/js-config.yaml: -------------------------------------------------------------------------------- 1 | additionalProperties: 2 | enumPropertyNaming: original 3 | modelPropertyNaming: original 4 | npmName: chromestatus-openapi 5 | paramNaming: camelCase 6 | supportsES6: true 7 | withInterfaces: true 8 | -------------------------------------------------------------------------------- /openapitools.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", 3 | "spaces": 2, 4 | "generator-cli": { 5 | "version": "7.6.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/playwright/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/playwright/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PLAYWRIGHT_VERSION 2 | 3 | FROM mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-jammy 4 | 5 | ARG USERID 6 | ARG GROUPID 7 | 8 | 9 | USER root 10 | # playwright already created this user. Delete it and use the UID & GID from the host 11 | RUN userdel -r pwuser && \ 12 | groupadd -g $GROUPID pwuser && \ 13 | useradd pwuser -u $USERID -g $GROUPID -m -s /bin/bash && \ 14 | mkdir -p /work/tests/__screenshots__ && \ 15 | mkdir -p /work/test-results && \ 16 | chown -R pwuser /work 17 | 18 | RUN npm config set script-shell bash --global 19 | 20 | USER pwuser 21 | WORKDIR /work 22 | 23 | # Set environment variable so we can tell we're performing Playwright tests. 24 | ENV PLAYWRIGHT_MODE=true 25 | 26 | # Install a consistent version of Playwright. The duplicate ARG line is needed to copy the value 27 | # into this build stage. 28 | ARG PLAYWRIGHT_VERSION 29 | RUN npm install @playwright/test@${PLAYWRIGHT_VERSION} 30 | 31 | # Copy the root directory. Subdirectories are mounted in docker-compose.yml. 32 | COPY --chown=pwuser:pwuser wait-for-app.sh playwright.config.ts /work/ 33 | 34 | # The playwright.config.ts file is copied from the repository root, where it is 35 | # needed for VS Code integration. Inside the container, the test directory is 36 | # the root, so we update the path. 37 | RUN sed -i "s|testDir: 'packages/playwright/tests'|testDir: '.'|" /work/playwright.config.ts 38 | -------------------------------------------------------------------------------- /packages/playwright/get-npm-package-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # E.g. ./get-npm-package-version.sh packages/playwright/package.json "@playwright/test" 4 | 5 | # Get the name of the devDependency 6 | devDependency=$2 7 | 8 | # Get the version number of the devDependency ["$devDependency"] 9 | version=$(jq -r '.devDependencies."'${devDependency}'"' $1) 10 | 11 | # Print the version number 12 | echo $version 13 | -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/editall-page/edit-all-fields-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-editall-page_pwtest.js/test-semantic-checks/shipped-desktop-error-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/create-origin-trial-stage-dialog-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-feature-page_pwtest.js/add-an-origin-trial-stage/origin-trial-panels-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/create-new-feature/new-feature-created-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-blink-component/blink-components-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-feature-name/feature-name-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/enter-web-feature-id/feature-id-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/navigate-to-create-feature-page/new-feature-page-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-new-page_pwtest.js/test-semantic-checks/warning-feature-name-and-summary-length-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-chromium-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-chromium-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-chromium-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-firefox-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-firefox-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-firefox-mobile-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/packages/playwright/tests/__screenshots__/chromedash-guide-stage-page_pwtest.js/edit-origin-trial-stage/semantic-check-origin-trial-firefox-mobile-linux.png -------------------------------------------------------------------------------- /packages/playwright/tests/chromedash-new-feature-list.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import { test, expect } from '@playwright/test'; 3 | import { 4 | captureConsoleMessages, delay, login, logout, 5 | gotoNewFeatureList 6 | } from './test_utils'; 7 | 8 | 9 | test.beforeEach(async ({ page }, testInfo) => { 10 | captureConsoleMessages(page); 11 | testInfo.setTimeout(90000); 12 | 13 | // Login before running each test. 14 | await login(page); 15 | }); 16 | 17 | test.afterEach(async ({ page }) => { 18 | // Logout after running each test. 19 | await logout(page); 20 | }); 21 | 22 | test('Typing slash focuses on searchbox', async ({page}) => { 23 | await gotoNewFeatureList(page, 'http://localhost:5555/'); 24 | const searchbox = page.locator('#inputfield'); 25 | await expect(searchbox).toBeVisible(); 26 | await expect(searchbox).toHaveAttribute('value', ''); 27 | await page.keyboard.type('abc/def/ghi'); 28 | // Characters before the first slash go to the page. 29 | // The slash focuses on the searchbox. 30 | // Later characters, including slashes, go in the searchbox. 31 | await expect(searchbox).toHaveAttribute('value', 'def/ghixx'); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/playwright/tests/spec_mentor_api_result.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "email": "expert@example.com", 4 | "mentored_features": [ 5 | {"id": 9009, "name": "First feature"} 6 | ] 7 | }, 8 | { 9 | "email": "mentor@example.org", 10 | "mentored_features": [ 11 | {"id": 9010, "name": "Second feature"}, 12 | {"id": 9009, "name": "First feature"} 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /packages/playwright/wait-for-app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # echo "waiting for backend to come up" 3 | while [[ "$(curl --connect-timeout 2 -s -o /dev/null -w ''%{http_code}'' http://localhost:7777)" != "200" ]]; do 4 | echo .. 5 | sleep 10 6 | done 7 | # echo backend is up 8 | -------------------------------------------------------------------------------- /pages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/pages/__init__.py -------------------------------------------------------------------------------- /pages/featurelist.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2021 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License") 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import json 17 | import logging 18 | 19 | import settings 20 | from framework import basehandlers 21 | from framework import permissions 22 | from framework import utils 23 | from internals import core_enums 24 | from internals import feature_helpers 25 | 26 | # from google.appengine.api import users 27 | from framework import users 28 | 29 | 30 | class FeaturesJsonHandler(basehandlers.FlaskHandler): 31 | 32 | HTTP_CACHE_TYPE = 'private' 33 | JSONIFY = True 34 | 35 | def get_template_data(self, **kwargs): 36 | user = users.get_current_user() 37 | feature_list = feature_helpers.get_features_by_impl_status( 38 | show_unlisted=permissions.can_edit_any_feature(user)) 39 | return feature_list 40 | -------------------------------------------------------------------------------- /pages/metrics.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | 17 | from framework import basehandlers 18 | from internals import fetchchannels 19 | 20 | 21 | class OmahaDataHandler(basehandlers.FlaskHandler): 22 | 23 | JSONIFY = True 24 | 25 | def get_template_data(self, **kwargs): 26 | omaha_data = fetchchannels.get_omaha_data() 27 | return omaha_data 28 | -------------------------------------------------------------------------------- /pages/metrics_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License") 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import testing_config # Must be imported before the module under test. 16 | 17 | from unittest import mock 18 | 19 | import os 20 | import flask 21 | import werkzeug 22 | import html5lib 23 | 24 | from pages import metrics 25 | 26 | test_app = flask.Flask(__name__) 27 | 28 | 29 | # TODO(jrobbins): Write unit test for OmahaDataHandler 30 | -------------------------------------------------------------------------------- /pages/users.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2013 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License") 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | __author__ = 'ericbidelman@chromium.org (Eric Bidelman)' 17 | 18 | 19 | import json 20 | import logging 21 | 22 | from api import accounts_api 23 | from framework import basehandlers 24 | from framework import permissions 25 | from internals import user_models 26 | 27 | 28 | class UserListHandler(basehandlers.FlaskHandler): 29 | 30 | TEMPLATE_PATH = 'admin/users/new.html' 31 | 32 | @permissions.require_admin_site 33 | def get_template_data(self, **kwargs): 34 | users = user_models.AppUser.query().fetch(None) 35 | user_list = [accounts_api.user_to_json_dict(user) for user in users] 36 | 37 | logging.info('user_list is %r', user_list) 38 | template_data = { 39 | 'users': json.dumps(user_list) 40 | } 41 | return template_data 42 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.ruff] 2 | indent-width = 2 3 | 4 | [tool.ruff.format] 5 | quote-style = "single" 6 | -------------------------------------------------------------------------------- /queue.yaml: -------------------------------------------------------------------------------- 1 | queue: 2 | - name: default 3 | target: notifier 4 | rate: 1/s 5 | retry_parameters: 6 | task_retry_limit: 3 7 | task_age_limit: 2d 8 | # bucket_size: 40 9 | # max_concurrent_requests: 5 10 | # total_storage_limit: 120M -------------------------------------------------------------------------------- /requirements.dev.txt: -------------------------------------------------------------------------------- 1 | # This file is also processed when you run `npm run deps` on your workstation, 2 | # but these libraries will not be install when running on GAE. These packages 3 | # are not needed on GAE because they are only for local development, or GAE 4 | # provides its own copy. 5 | 6 | coverage==7.11.0 7 | gunicorn==23.0.0 8 | 9 | # Mypy and dependencies 10 | mypy==1.18.2 11 | types-protobuf 12 | types-redis 13 | types-requests 14 | types-setuptools 15 | types-pytz 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | 2 | # Also see requirements.dev.txt 3 | 4 | # Py3 Libraries 5 | appengine-python-standard>=1.0.0 6 | html5lib==1.1 7 | funcsigs==1.0.2 8 | json5==0.12.1 9 | google-api-python-client==2.186.0 10 | 11 | # TODO(jrobbins): Add this back or replace it when python 3.10 is supported. 12 | # google-python-cloud-debugger==2.18 13 | # See https://github.com/GoogleCloudPlatform/cloud-debug-python/issues/33 14 | 15 | google-cloud-tasks==2.20.0 16 | google-cloud-ndb==2.3.4 17 | google-cloud-logging==3.12.1 18 | google-cloud-secret-manager==2.25.0 19 | google-cloud-storage==3.4.1 20 | google-auth==2.42.1 21 | google-genai==1.48.0 22 | requests==2.32.5 23 | redis==6.4.0 24 | fakeredis==2.32.0 25 | Flask==3.1.2 26 | flask-cors==6.0.1 27 | funcsigs==1.0.2 28 | Jinja2==3.1.6 29 | json5==0.12.1 30 | MarkupSafe==3.0.3 31 | Werkzeug==3.1.3 32 | click==8.3.0 33 | itsdangerous==2.2.0 34 | ghapi==1.0.8 35 | validators==0.35.0 36 | # Work-around for failure to deploy 37 | # https://stackoverflow.com/questions/69936420/google-cloud-platform-app-deploy-failure-due-to-pyparsing 38 | pyparsing==3.2.5 39 | pillow==12.0.0 40 | # OpenAPI files 41 | ./gen/py/chromestatus_openapi 42 | ./gen/py/webstatus_openapi 43 | types-python-dateutil==2.9.0.20251008 44 | -------------------------------------------------------------------------------- /scripts/client_secrets.json: -------------------------------------------------------------------------------- 1 | { 2 | "installed": { 3 | "client_id": "470026626516.apps.googleusercontent.com", 4 | "client_secret": "R1uICVrjoYFaOcMI7ISWEZKR", 5 | "redirect_uris": ["http://localhost", "urn:ietf:wg:oauth:2.0:oob"], 6 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 7 | "token_uri": "https://accounts.google.com/o/oauth2/token" 8 | } 9 | } -------------------------------------------------------------------------------- /scripts/debug_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Starts the dev server and services. 4 | # 5 | # Copyright 2017 Eric Bidelman 6 | 7 | export PYTHONPATH=cs-env/lib/python3/site-packages:$PYTHONPATH 8 | export GOOGLE_CLOUD_PROJECT='cr-status-staging' 9 | export SERVER_SOFTWARE='gunicorn' 10 | export GAE_ENV='localdev' 11 | export DATASTORE_EMULATOR_HOST=${DATASTORE_EMULATOR_HOST:-'localhost:15606'} 12 | 13 | # Using python3 directly has a chance of picking up the wrong environment. 14 | cs-env/bin/python3 -m debugpy --listen 0.0.0.0:5678 main.py 15 | -------------------------------------------------------------------------------- /scripts/start_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Starts the dev server and services. 4 | # 5 | # Copyright 2017 Eric Bidelman 6 | 7 | export PYTHONPATH=cs-env/lib/python3/site-packages:$PYTHONPATH 8 | export GOOGLE_CLOUD_PROJECT='cr-status-staging' 9 | export SERVER_SOFTWARE='gunicorn' 10 | export GAE_ENV='localdev' 11 | export DATASTORE_EMULATOR_HOST=${DATASTORE_EMULATOR_HOST:-'localhost:15606'} 12 | 13 | 14 | gunicorn --bind :7777 --workers 4 main:app 15 | 16 | 17 | # TODO(jrobbins): Consider switching back to dev_appserver when 18 | # it no longer requires python2. 19 | # 20 | # The directory in which this script resides. 21 | #readonly BASEDIR=$(dirname $BASH_SOURCE) 22 | # 23 | #dev_appserver.py -A cr-status --enable_console=1 \ 24 | # --support_datastore_emulator=1 --datastore_emulator_port=15606 \ 25 | # --env_var DATASTORE_EMULATOR_HOST='localhost:15606' \ 26 | # $BASEDIR/../dispatch.yaml \ 27 | # $BASEDIR/../notifier.yaml \ 28 | # $BASEDIR/../app.yaml 29 | 30 | # Note: When running locally, the default service is dev-default.yaml 31 | # which is a py3 service which does nothing. That avoids needing py2 32 | # on the developer's workstation. 33 | # On GAE, the default service is py2/app-py2.yaml which uses the GAE 34 | # py2 runtime. 35 | -------------------------------------------------------------------------------- /static/css/features/launch.css: -------------------------------------------------------------------------------- 1 | /* App specific */ 2 | /* ----- */ 3 | #content { 4 | flex-direction: column; 5 | counter-reset: h3; 6 | height: auto; 7 | } 8 | #content section { 9 | max-width: 600px; 10 | flex: 1 0 auto; 11 | margin-bottom: 15px; 12 | } 13 | #content section > div { 14 | background: white; 15 | border: 1px solid #ddd; 16 | box-shadow: rgba(0, 0, 0, 0.067) 1px 1px 4px; 17 | padding: 12px; 18 | margin: 8px 0 16px 0; 19 | } 20 | #content section > p { 21 | color: #444; 22 | } 23 | #content h3 { 24 | margin-bottom: 10px; 25 | } 26 | #content h3:before { 27 | counter-increment: h3; 28 | content: counter(h3) "."; 29 | margin-right: 5px; 30 | } 31 | 32 | .subject { 33 | font-size: 16px; 34 | margin-bottom: 10px; 35 | } 36 | 37 | .email .help { 38 | font-style: italic; 39 | color: #aaa; 40 | } 41 | .email h4 { 42 | font-weight: 600; 43 | } 44 | 45 | .alertbox { 46 | margin: 2em; 47 | padding: 1em; 48 | background: var(--warning-background); 49 | color: var(--warning-color); 50 | } -------------------------------------------------------------------------------- /static/img/a2hs_icon_24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/img/browsers-logos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/browsers-logos.png -------------------------------------------------------------------------------- /static/img/crstatus_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_128.png -------------------------------------------------------------------------------- /static/img/crstatus_144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_144.png -------------------------------------------------------------------------------- /static/img/crstatus_192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_192.png -------------------------------------------------------------------------------- /static/img/crstatus_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_48.png -------------------------------------------------------------------------------- /static/img/crstatus_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_512.png -------------------------------------------------------------------------------- /static/img/crstatus_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_72.png -------------------------------------------------------------------------------- /static/img/crstatus_96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/crstatus_96.png -------------------------------------------------------------------------------- /static/img/github-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/github-white.png -------------------------------------------------------------------------------- /static/img/google_sign_in/btn_google_signin_light_normal_web@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/google_sign_in/btn_google_signin_light_normal_web@2x.png -------------------------------------------------------------------------------- /static/img/google_sign_in/btn_google_signin_light_pressed_web@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChrome/chromium-dashboard/aaa07ce008e220a155ec8f7b9bfa5f7b863748dc/static/img/google_sign_in/btn_google_signin_light_pressed_web@2x.png -------------------------------------------------------------------------------- /static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /admin/ 3 | Disallow: /data/ 4 | 5 | Sitemap: http://www.chromestatus.com/features.xml?max-items=9999 6 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/bug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/caret-down-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/check-lg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/dash-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/exclamation-circle-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/exclamation-triangle-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/filter-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/graph-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/info-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/pencil-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/plus-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/sign-stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/sliders2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/star-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/upload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/x-circle-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/icons/x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/approval.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/arrow_circle_right_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/autorenew_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/blank_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/block_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/check_circle_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/check_circle_filled_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/check_circle_outline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/clock_loader_60_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/extension.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/help_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/highlight_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/menu_20px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/more_vert_24px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/navigate_before.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/navigate_next.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/pan-tool.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/pending_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/star.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/star_border.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/tune.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/shoelace/assets/material-icons/visibility_20px.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/admin/users/new.html: -------------------------------------------------------------------------------- 1 | {% extends "_base.html" %} 2 | 3 | {% block css %} 4 | 5 | {% endblock %} 6 | 7 | {% block subheader %} 8 |
9 |

Application users

10 |
11 | {% endblock %} 12 | 13 | {% block content %} 14 |
15 | 16 | 17 | 18 |
19 | {% endblock %} 20 | 21 | {% block js %} 22 | 28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /templates/blink/launch_bug.html: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 | TODO 22 |
23 | -------------------------------------------------------------------------------- /templates/farewell-rss.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Chrome Platform Status - Features 4 | 5 | https://chromestatus.com/features 6 | 2022-08-19T21:53:44Z 7 | 8 | 9 | Please use our web UI 10 | 11 | 2022-08-19T21:53:44Z 12 | Chrome Platform Status 13 | tag:chromestatus.com,2022-08-19 14 | 15 | ChromeStatus.com no longer offers an RSS feed. 16 | To keep up to date with new features, please visit our website. 17 | If you have a strong need for this RSS feed, please let us know 18 | by filing an issue at https://github.com/GoogleChrome/chromium-dashboard/issues. 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /templates/farewell-samples.html: -------------------------------------------------------------------------------- 1 | {% extends "_base.html" %} 2 | 3 | {% block css %} 4 | 10 | {% endblock %} 11 | 12 | {% block content %} 13 |

This site no long offers a list of all features that have 14 | samples.

15 | 16 |

If a feature entry has samples, a "Demos and samples" section 17 | is shown on the feature detail page.

18 | 19 |

To view a collection of samples for a variety of features, visit 20 | the GoogleChrome/samples repo on GitHub.

22 | {% endblock %} 23 | 24 | 25 | {% block js %} 26 | 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /templates/inactive_user_email.html: -------------------------------------------------------------------------------- 1 |

2 | You are receiving this notification because you are registered as a user for 3 | ChromeStatus.com and have been inactive for longer than 6 months. 4 |

5 |
6 |

7 | If you still need the ability to create features on ChromeStatus.com, signing 8 | into {{SITE_URL}} with this email will avoid any 9 | disruption in your access. 10 |

11 |
12 |

13 | For the sake of site security, a user with 9 months of inactivity is 14 | granted normal user access. If you no longer need special access, no 15 | action is required on your part. 16 | Please note that you if you need special access again, you may contact us at 17 | webstatus-request@google.com to re-establish special access. 18 |

19 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% block content %}NOTHING HERE{% endblock %} 2 | -------------------------------------------------------------------------------- /templates/origintrials/ot-activated-email.html: -------------------------------------------------------------------------------- 1 |

2 | Your trial creation request for {{stage.ot_display_name}} has been approved 3 | and processed. The setup is now complete and the trial can be seen in the 4 | OT console at: {{ot_url}} 5 |
6 | These changes have also been applied to the trial entry at: {{chromestatus_url}} 7 |

8 | Thanks,
9 | Origin Trials team 10 |

11 | -------------------------------------------------------------------------------- /templates/origintrials/ot-activation-failed-email.html: -------------------------------------------------------------------------------- 1 |

An automated origin trial activation has failed to process

2 |

3 | Trial Name: {{stage.ot_display_name}} 4 |
5 | Trial ID: {{stage.origin_trial_id}} 6 |
7 | Chromestatus URL: {{chromestatus_url}} 8 |
9 | Scheduled activation date: {{stage.ot_activation_date}} 10 |

11 | -------------------------------------------------------------------------------- /templates/origintrials/ot-automated-process-email.html: -------------------------------------------------------------------------------- 1 | Hello! This is your friendly neighborhood automated reminder script here. I just ran on {{email_date}} and 2 | identified the following facts: 3 | 14 | Could you please double check my work and make sure I sent the right emails? 15 | I'm looking forward to slowly replacing you through the 16 | inexorable tide of automation!

17 | <3

18 | -Your future robot overlord 19 | -------------------------------------------------------------------------------- /templates/origintrials/ot-beta-availability-email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome {{release_milestone}} will soon arrive on the 2 | beta channel.

3 | Check that your feature ({{name}}) shows up correctly under the origin trials 4 | section of the roadmap https://chromestatus.com/roadmap. This will automatically 5 | get it included in the blog post about Chrome {{release_milestone}} beta, which 6 | will go live on https://developer.chrome.com/tags/beta/. If you previously 7 | published a blog post allowing developers to sign up for tokens for your 8 | feature, this will be linked in the beta blog post. 9 | {% include "origintrials/ot-process-reminders-ps.html" %} 10 | -------------------------------------------------------------------------------- /templates/origintrials/ot-creation-approved-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 |
7 |

8 | All prerequisite reviews have been completed and you can now submit a 9 | request to create your origin trial. Click the "Request Trial Creation" 10 | button on the Origin Trial section of your feature's detail page. 12 |

13 |

14 | Note: Only feature owners signed in with a 15 | "chromium.org" or "google.com" domain email address will have access to 16 | the trial creation form, and at least 1 Googler contact is required 17 | during form submission to continue the trial creation process. If you 18 | have any questions or need assistance, reach out to origin-trials-support@google.com. 21 |

22 | Thanks,
23 | Origin Trials team 24 |

25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /templates/origintrials/ot-creation-processed-email.html: -------------------------------------------------------------------------------- 1 |

2 | Your trial creation request for {{stage.ot_display_name}} has been approved 3 | and processed. The trial is slated to begin with the Chrome stable release 4 | for {{stage.desktop_first}}. We'll notify you again when the 5 | trial has been activated and is available for registration in the 6 | OT Console. 7 |
8 | These changes have also been applied to the trial entry at: 9 | {{chromestatus_url}} 10 |

11 | Thanks,
12 | Origin Trials team 13 |

14 | -------------------------------------------------------------------------------- /templates/origintrials/ot-creation-request-failed-email.html: -------------------------------------------------------------------------------- 1 |

An automated origin trial request has failed to process

2 |

3 | Error text: {{error_text}} 4 |

5 |

6 | Stage ID: {{stage.id}} 7 |
8 | Origin trial ID (if available): {{stage.origin_trial_id}} 9 |
10 | Requested by: {{stage.ot_owner_email}} 11 |
12 | Additional contacts for your team?: {{stage.ot_emails}} 13 |
14 | Feature name: {{stage.ot_display_name}} 15 |
16 | Feature description: {{stage.ot_description}} 17 |
18 | Start Chrome milestone: {{stage.desktop_first}} 19 |
20 | End Chrome milestone: {{stage.desktop_last}} 21 |
22 | Chromium trial name: {{stage.ot_chromium_trial_name}} 23 |
24 | Is this a deprecation trial?: {{(stage.ot_is_deprecation_trial)}} 25 |
26 | Third party origin support: {{stage.ot_has_third_party_support}} 27 |
28 | WebFeature UseCounter value: {{stage.ot_webfeature_use_counter}} 29 |
30 | Documentation link: {{stage.ot_documentation_url}} 31 |
32 | Chromestatus link: {{chromestatus_url}} 33 |
34 | Feature feedback link: {{stage.ot_feedback_submission_url}} 35 |
36 | Intent to Experiment link: {{stage.intent_thread_url}} 37 |
38 | Is this a critical trial?: {{stage.ot_is_critical_trial}} 39 |
40 |
41 | Instructions for handling this request can be found at: 42 | https://g3doc.corp.google.com/chrome/origin_trials/g3doc/trial_admin.md?cl=head#setup-a-new-trial 43 |

44 | -------------------------------------------------------------------------------- /templates/origintrials/ot-ending-next-release-email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome {{release_milestone}} landed on the stable 2 | channel one week ago. The branch point of Chrome {{after_end_release}} occurs 3 | {{after_end_date}}, which will be the first release after the end of your 4 | trial.

5 | This is the point to be making the decision about what happens at the end of the 6 | trial. Options include: 7 |
    8 |
  1. Ship the feature, which requires an Intent to Ship
  2. 9 |
  3. Continue experimenting with the feature in a new trial, which requires an 10 | Intent to Continue Experimenting
  4. 11 |
  5. 12 | Let the origin trial finish and be disabled in Chrome {{after_end_release}}. 13 |
  6. 14 |
15 | {% include "origintrials/ot-process-reminders-ps.html" %} 16 | -------------------------------------------------------------------------------- /templates/origintrials/ot-ending-this-release-email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome {{release_milestone}} landed on the 2 | stable channel one week ago, so you should have now shared with blink-dev the 3 | things you've learned based on the feedback gathered from developers during 4 | token renewal. 5 | Also, you should share your plans for Chrome {{next_release}}, which will be 6 | the first release after the end of your trial. 7 | {% include "origintrials/ot-process-reminders-ps.html" %} 8 | -------------------------------------------------------------------------------- /templates/origintrials/ot-extended-email.html: -------------------------------------------------------------------------------- 1 |

2 | A recent extension request was finalized and processed. 3 |
4 | Requested by: {{extension_stage.ot_owner_email}} 5 |
6 | Feature name: {{ot_stage.ot_display_name}} 7 |
8 | Intent to Extend Experiment URL: {{extension_stage.intent_thread_url}} 9 |
10 | New end milestone: {{extension_stage.desktop_last}} 11 |
12 |
13 | No additional action needs to be taken if this information looks correct. 14 |

15 | -------------------------------------------------------------------------------- /templates/origintrials/ot-extension-approved-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 |
{{styles.icon_alert()}}Finalize your origin trial extension on feature entry:
{{feature.name}} 16 |
19 |
20 | 21 | 22 |
23 |

24 | Your requested origin trial extension has received approval and is ready 25 | to be finalized for submission. 26 |

27 |
28 | 29 | 30 |
31 |
Your next steps:
32 | 33 | 37 |
38 | 39 |
40 |
41 | -------------------------------------------------------------------------------- /templates/origintrials/ot-first-branch-email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome {{release_milestone}} branch is 2 | {{branch_date}}. This release will contain your feature as an origin trial. 3 |

4 | You should aim to post a blog post on https://developer.chrome.com/blog/ as 5 | soon as possible so you can begin to get origin trials sign ups early 6 | (which means you get feedback earlier!). If you are already working with 7 | someone from Chrome Web Developer Relations they can help you with this. 8 | Otherwise, reach out to chrome-devrel-content@google.com for help. 9 | {% include "origintrials/ot-process-reminders-ps.html" %} 10 | -------------------------------------------------------------------------------- /templates/origintrials/ot-last-branch-email.html: -------------------------------------------------------------------------------- 1 | According to go/chrome-schedule, Chrome {{release_milestone}} is branching 2 | {{branch_date}}. This release will be the final one to include your feature as 3 | an origin trial. 4 |

Code you land from here on will land in the first 5 | release after the origin trial is over. 6 | {% include "origintrials/ot-process-reminders-ps.html" %} 7 | -------------------------------------------------------------------------------- /templates/origintrials/ot-process-reminders-ps.html: -------------------------------------------------------------------------------- 1 |

P.S. This email was generated automatically (for 2 | details, see go/running-an-origin-trial). 3 | Please contact origin-trials-support@google.com if this email is incorrect or not useful. 4 | -------------------------------------------------------------------------------- /templates/reset-shipping-milestones-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 | 7 |
8 |

What Happened

9 |

10 | This is an automated notification to inform you that the upcoming milestones 11 | for your ChromeStatus feature have been reset. 12 |

13 | 14 |

Reason for this Change

15 |

16 | This action was taken because the accuracy of your feature's data was not 17 | verified in response to our recent notifications. 18 |

19 |

20 | To prevent this in the future, please respond to the accuracy 21 | verification notifications sent by ChromeStatus. This ensures your 22 | milestones remain active and your feature's data remains accurate. 23 |

24 |
25 | 26 |
27 |

Next Steps

28 |

29 | You can continue to edit and update your feature normally. Please visit your 30 | feature page to make any necessary updates: 31 |

32 | 35 |
36 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /templates/review-assigned-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 |
{{styles.icon_alert()}}Review assigned for feature entry:
{{feature.name}} 16 |
19 |
20 | 21 |
22 |

Review assigned{% if updater_email %} by {{updater_email}}{% endif %}:

23 | 24 |

A new reviewer has been assigned for {% if team_name %}{{team_name}}{% else %}your team{% endif %}.

25 |
    26 | {{formatted_changes|safe}} 27 |
28 |
29 | 30 |
31 |
Your next steps:
32 | 35 |
36 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /templates/review-comment-email.html: -------------------------------------------------------------------------------- 1 |
{{comment_content}}
2 | -------------------------------------------------------------------------------- /templates/review-comment-notification-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 |
{{styles.icon_updated()}}Comment posted on feature entry:
{{feature.name}} 17 |
20 |
21 | 22 |
23 |
A comment was added to this feature:
24 |
25 |
{{triggering_user_email}}
26 |
{{content}}
27 |
28 |
29 | 30 |
31 |
Your next steps:
32 | 35 |
36 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /templates/review-request-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 |
{{styles.icon_alert()}}Review requested for feature entry:
{{feature.name}} 16 |
19 |
20 | 21 |
22 |

Review requested{% if updater_email %} by {{updater_email}}{% endif %}:

23 | 24 |

Please review this feature entry on behalf of {% if team_name %}{{team_name}}{% else %}your team{% endif %}.

25 |
26 | 27 |
28 |
Your next steps:
29 | 32 |
33 | 34 |
35 |
36 | -------------------------------------------------------------------------------- /templates/slo_overdue_email.html: -------------------------------------------------------------------------------- 1 | {% if is_escalated %} 2 | 3 |

The {{appr_def.team_name}} review 5 | of {{feature.name}} 6 | is now overdue for {{needed_action}}.

7 | 8 |

All potential reviewers are being notified, 9 | even if the review was previously assigned to one reviewer.

10 | 11 | {% else %} 12 | 13 |

The {{appr_def.team_name}} review 15 | of {{feature.name}} 16 | is now due for {{needed_action}}.

17 | 18 | {% endif %} 19 | -------------------------------------------------------------------------------- /templates/test_template.html: -------------------------------------------------------------------------------- 1 | This is used by unit tests. 2 | 3 | Hi {{ name }}, how are you? 4 | -------------------------------------------------------------------------------- /templates/update-feature-email.html: -------------------------------------------------------------------------------- 1 | {% import 'email-styles.html' as styles %} 2 |
3 |
{{APP_TITLE}}
4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 |
{{styles.icon_updated()}}Updated feature entry:
{{feature.name}} 16 |
19 |
20 | 21 | 22 |
23 |
Updates made by {{updater_email}}:
24 |
    25 | {{formatted_changes|safe}} 26 |
27 |
28 | 29 | 30 |
31 |
Your next steps:
32 | 35 |
36 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ES2022", 4 | "moduleResolution": "bundler", 5 | "plugins": [ 6 | { 7 | "name": "ts-lit-plugin", 8 | "rules": { 9 | "no-incompatible-type-binding": "off" 10 | } 11 | } 12 | ], 13 | "strict": true, 14 | "noImplicitAny": false, 15 | "esModuleInterop": true, 16 | "skipLibCheck": true, 17 | "rootDir": "client-src", 18 | "allowJs": true, 19 | "checkJs": false, 20 | "resolveJsonModule": true, 21 | "outDir": "build", 22 | "emitDeclarationOnly": false, 23 | "incremental": true, 24 | "lib": ["ES2023", "DOM"], 25 | "experimentalDecorators": true, 26 | "useDefineForClassFields": false, 27 | "target": "ES2022", 28 | }, 29 | "include": [ 30 | "client-src/js-src/**/*", 31 | "client-src/elements/**/*", 32 | "client-src/components.js" 33 | ], 34 | "exclude": [ 35 | "node_modules", 36 | "static/dist" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /util/deployment/deploy-production: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Deploys the site to the production environment. 3 | set -e 4 | 5 | # Verify we are on the main branch 6 | BRANCH=$(git rev-parse --abbrev-ref HEAD) 7 | if [ "$BRANCH" != "main" ]; then 8 | echo "Not on the main branch. Aborting deployment." 9 | exit 1 10 | fi 11 | 12 | # Check for uncommitted changes 13 | if [ -n "$(git status --porcelain)" ]; then 14 | echo "Uncommitted changes detected:" 15 | git status 16 | read -p "Do you want to proceed with the deployment? (y/n) " -n 1 -r 17 | echo 18 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then 19 | echo "Deployment aborted." 20 | exit 1 21 | fi 22 | fi 23 | 24 | # Get the directory of the script 25 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 26 | 27 | # Create the GitHub issue for this deployment if it doesn't already exist. 28 | "$DIR/create-deployment-issue" 29 | 30 | export APP_NAME="cr-status" 31 | export APP_YAML="app.yaml" 32 | export NOTIFIER_YAML="notifier.yaml" 33 | 34 | "$DIR/deploy-env" 35 | 36 | echo "Remember to close the GitHub release issue." 37 | echo "https://github.com/GoogleChrome/chromium-dashboard/issues?q=is%3Aissue+label%3Arelease+is%3Aopen" 38 | -------------------------------------------------------------------------------- /util/deployment/deploy-staging: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Deploys the site to the staging environment. 3 | set -e 4 | 5 | # Get the directory of the script 6 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | 8 | export APP_NAME="cr-status-staging" 9 | export APP_YAML="app.staging.yaml" 10 | export NOTIFIER_YAML="notifier.staging.yaml" 11 | 12 | "$DIR/deploy-env" 13 | -------------------------------------------------------------------------------- /web-test-runner.config.mjs: -------------------------------------------------------------------------------- 1 | const filteredLogs = [ 2 | 'Lit is in dev mode', 3 | ]; 4 | 5 | export default { 6 | files: 'build/**/*_test.{js,ts}', 7 | concurrentBrowsers: 1, 8 | concurrency: 1, 9 | nodeResolve: true, 10 | browserStartTimeout: 60000, 11 | filterBrowserLogs(log) { 12 | for (const arg of log.args) { 13 | if (typeof arg === 'string' && filteredLogs.some(l => arg.includes(l))) { 14 | return false; 15 | } 16 | } 17 | 18 | return true; 19 | }, 20 | }; 21 | --------------------------------------------------------------------------------