mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d63f71931e |
+9
-7
@@ -5,10 +5,12 @@
|
||||
.git
|
||||
node_modules
|
||||
dist
|
||||
aio/node_modules
|
||||
aio/tools/examples/shared/node_modules
|
||||
aio/tools/examples/shared/example-scaffold
|
||||
|
||||
# All integration test node_modules folders
|
||||
integration/animations/node_modules
|
||||
integration/animations-async/node_modules
|
||||
integration/cli-elements-universal/node_modules
|
||||
integration/cli-hello-world/node_modules
|
||||
integration/cli-hello-world-ivy-i18n/node_modules
|
||||
@@ -20,20 +22,20 @@ integration/dynamic-compiler/node_modules
|
||||
integration/forms/node_modules
|
||||
integration/injectable-def/node_modules
|
||||
integration/ivy-i18n/node_modules
|
||||
integration/ng-add-localize/node_modules
|
||||
integration/ng_elements/node_modules
|
||||
integration/ng_update/node_modules
|
||||
integration/ng_update_migrations/node_modules
|
||||
integration/ng-add-localize/node_modules
|
||||
integration/nodenext_resolution/node_modules
|
||||
integration/npm_package_archives.bzl/node_modules
|
||||
integration/platform-server/node_modules
|
||||
integration/platform-server-hydration/node_modules
|
||||
integration/service-worker-schema/node_modules
|
||||
integration/side-effects/node_modules
|
||||
integration/standalone-bootstrap/node_modules
|
||||
integration/terser/node_modules
|
||||
integration/trusted-types/node_modules
|
||||
integration/typings_test_rxjs7/node_modules
|
||||
integration/typings_test_ts55/node_modules
|
||||
integration/typings_test_ts56/node_modules
|
||||
integration/typings_test_ts57/node_modules
|
||||
modules/ssr-benchmarks/node_modules
|
||||
integration/typings_test_ts49/node_modules
|
||||
integration/typings_test_ts50/node_modules
|
||||
integration/typings_test_ts51/node_modules
|
||||
integration/typings_test_ts52/node_modules
|
||||
|
||||
@@ -56,16 +56,31 @@ build --enable_runfiles
|
||||
build:release --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=release"
|
||||
build:release --stamp
|
||||
|
||||
# Building AIO against local Angular deps requires stamping
|
||||
# versions in Angular packages due to CLI version checks.
|
||||
build:aio_local_deps --stamp
|
||||
build:aio_local_deps --workspace_status_command="yarn -s --cwd aio local-workspace-status"
|
||||
|
||||
# Snapshots should also be stamped with version control information.
|
||||
build:snapshot-build --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=snapshot"
|
||||
build:snapshot-build --stamp
|
||||
|
||||
# Angular DevTools for Firefox releases *cannot* be stamped and `--config snapshot-build-firefox` is a no-op.
|
||||
# This is because Mozilla requires add-on source code to be uploaded and then they manually reproduce the build.
|
||||
# If we stamp the build based on Git information such as the current commit, then reproducing the build would require
|
||||
# uploading the entire `.git` directory. We already must upload the entire monorepo, and uploading `.git` as well
|
||||
# exceeds the max source file size. To address this, we just *don't* stamp Firefox builds of Angular DevTools.
|
||||
build:snapshot-build-firefox --nostamp
|
||||
##########################################################
|
||||
# AIO architect build configuration #
|
||||
# See aio/angular.json for available configurations. #
|
||||
# To build with a partiular configuration: #
|
||||
# bazel build //aio:build --aio_build_config=<config> #
|
||||
# Default config is `stable``. #
|
||||
##########################################################
|
||||
build --flag_alias=aio_build_config=//aio:flag_aio_build_config
|
||||
|
||||
####################################
|
||||
# AIO first party dep substitution #
|
||||
# Turn on with #
|
||||
# --config=aio_local_deps #
|
||||
####################################
|
||||
|
||||
build:aio_local_deps --//aio:flag_aio_local_deps
|
||||
|
||||
###############################
|
||||
# Output #
|
||||
@@ -78,6 +93,12 @@ query --output=label_kind
|
||||
# By default, failing tests don't print any output, it goes to the log file
|
||||
test --test_output=errors
|
||||
|
||||
################################
|
||||
# Settings for CircleCI #
|
||||
################################
|
||||
|
||||
# Bazel flags for CircleCI are in /.circleci/bazel.linux.rc and /.circleci/bazel.windows.rc
|
||||
|
||||
##################################
|
||||
# Remote Build Execution support #
|
||||
# Turn on these settings with #
|
||||
@@ -97,6 +118,10 @@ common:remote --jobs=200
|
||||
|
||||
build:remote --google_default_credentials
|
||||
|
||||
# Limit the number of test jobs for on an AIO local deps build. The example tests running
|
||||
# concurrently pushes the circleci executor RAM usage to its limits.
|
||||
test:aio_local_deps --jobs=24
|
||||
|
||||
# Force remote exeuctions to consider the entire run as linux
|
||||
build:remote --cpu=k8
|
||||
build:remote --host_cpu=k8
|
||||
@@ -152,8 +177,9 @@ test:saucelabs --flaky_test_attempts=1
|
||||
|
||||
# --ng_perf will ask the Ivy compiler to produce performance results for each build.
|
||||
build --flag_alias=ng_perf=//packages/compiler-cli:ng_perf
|
||||
# --full_build_adev will run adev build/serve in a full mode, performing prerendering and DCE.
|
||||
build --flag_alias=full_build_adev=//adev:full_build_adev
|
||||
# --adev_fast will run adev build/serve in a faster mode, skipping things like prerendering
|
||||
# for local development.
|
||||
build --flag_alias=fast_adev=//adev:fast_build_mode
|
||||
|
||||
####################################################
|
||||
# User bazel configuration
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Encryption
|
||||
|
||||
Based on https://github.com/circleci/encrypted-files
|
||||
|
||||
In the CircleCI web UI, we have a secret variable called `KEY`
|
||||
https://circleci.com/gh/angular/angular/edit#env-vars
|
||||
which is only exposed to non-fork builds
|
||||
(see "Pass secrets to builds from forked pull requests" under
|
||||
https://circleci.com/gh/angular/angular/edit#advanced-settings)
|
||||
|
||||
We use this as a symmetric AES encryption key to encrypt tokens like
|
||||
a GitHub token that enables publishing snapshots.
|
||||
|
||||
To create the github_token file, we take this approach:
|
||||
- Find the angular-builds:token in the internal pw database
|
||||
- Go inside the CircleCI default docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it circleci/node:10.12`
|
||||
- echo "https://[token]:@github.com" > credentials
|
||||
- openssl aes-256-cbc -e -in credentials -out .circleci/github_token -k $KEY
|
||||
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`
|
||||
@@ -0,0 +1,16 @@
|
||||
# Settings in this file should be OS agnostic. Use the bazel.<OS>.rc files for OS specific settings.
|
||||
|
||||
# Print all the options that apply to the build.
|
||||
# This helps us diagnose which options override others
|
||||
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
|
||||
build --announce_rc
|
||||
|
||||
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||
# By default this is set in the project `.bazelrc` to `1`.
|
||||
test --flaky_test_attempts=3
|
||||
|
||||
# More details on failures
|
||||
build --verbose_failures=true
|
||||
|
||||
# CI supports colors but Bazel does not detect it.
|
||||
common --color=yes
|
||||
@@ -0,0 +1,23 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Import config items common to both Linux and Windows setups.
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
build --repository_cache=/home/circleci/bazel_repository_cache
|
||||
|
||||
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||
# Limit Bazel to consuming resources that fit in CircleCI "2xlarge+" class
|
||||
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||
build --local_cpu_resources=20
|
||||
build --local_ram_resources=40960
|
||||
|
||||
# All build executed remotely should be done using our RBE configuration.
|
||||
build:remote --google_default_credentials
|
||||
|
||||
build --config=remote
|
||||
@@ -0,0 +1,17 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to $env:ProgramData\bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Import config items common to both Linux and Windows setups.
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Manually set the local resources used in windows CI runs
|
||||
build --local_ram_resources=120000
|
||||
build --local_cpu_resources=32
|
||||
|
||||
# All windows jobs run on master and should use http caching
|
||||
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||
build --remote_accept_cached=true
|
||||
build --remote_upload_local_results=true
|
||||
build --google_default_credentials
|
||||
@@ -0,0 +1,16 @@
|
||||
# This config is remaining in place to prevent pull requests failing because of CircleCI config missing.
|
||||
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
pass:
|
||||
docker:
|
||||
- image: cimg/base:2022.05
|
||||
steps:
|
||||
- run: echo "This too shall pass (always)"
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
default_workflow:
|
||||
jobs:
|
||||
- pass
|
||||
@@ -0,0 +1,76 @@
|
||||
####################################################################################################
|
||||
# Helpers for defining environment variables for CircleCI.
|
||||
#
|
||||
# In CircleCI, each step runs in a new shell. The way to share ENV variables across steps is to
|
||||
# export them from `$BASH_ENV`, which is automatically sourced at the beginning of every step (for
|
||||
# the default `bash` shell).
|
||||
#
|
||||
# See also https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables.
|
||||
####################################################################################################
|
||||
|
||||
# Set and print an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are public, i.e. it is OK for them to be
|
||||
# visible to anyone through the CI logs.
|
||||
#
|
||||
# Usage: `setPublicVar <name> <value>`
|
||||
function setPublicVar() {
|
||||
setSecretVar $1 "$2";
|
||||
echo "$1=$2";
|
||||
}
|
||||
|
||||
# Set (without printing) an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are secret, i.e. should not be visible to
|
||||
# everyone through the CI logs.
|
||||
#
|
||||
# Usage: `setSecretVar <name> <value>`
|
||||
function setSecretVar() {
|
||||
# WARNING: Secrets (e.g. passwords, access tokens) should NOT be printed.
|
||||
# (Keep original shell options to restore at the end.)
|
||||
local -r originalShellOptions=$(set +o);
|
||||
set +x -eu -o pipefail;
|
||||
|
||||
local assignmentStatement="export $1=\"${2:-}\";"
|
||||
|
||||
echo "${assignmentStatement}" >> $BASH_ENV;
|
||||
eval "${assignmentStatement}"
|
||||
|
||||
# Restore original shell options.
|
||||
eval "$originalShellOptions";
|
||||
}
|
||||
|
||||
|
||||
# Create a function to set an environment variable, when called.
|
||||
#
|
||||
# Use this function for creating setter for public environment variables that require expensive or
|
||||
# time-consuming computaions and may not be needed. When needed, you can call this function to set
|
||||
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
|
||||
#
|
||||
# Arguments:
|
||||
# - `<name>`: The name of the environment variable. The generated setter function will be
|
||||
# `setPublicVar_<name>`.
|
||||
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
|
||||
# executed lazily, it must be properly escaped. For example:
|
||||
# ```sh
|
||||
# # DO NOT do this:
|
||||
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
|
||||
#
|
||||
# # DO this isntead:
|
||||
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
|
||||
# ```
|
||||
#
|
||||
# Usage: `createPublicVarSetter <name> <code>`
|
||||
#
|
||||
# Example:
|
||||
# ```sh
|
||||
# createPublicVarSetter MY_VAR 'echo "FOO"';
|
||||
# echo $MY_VAR; # Not defined
|
||||
#
|
||||
# setPublicVar_MY_VAR;
|
||||
# source $BASH_ENV;
|
||||
# echo $MY_VAR; # FOO
|
||||
# ```
|
||||
function createPublicVarSetter() {
|
||||
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
|
||||
}
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
####################################################################################################
|
||||
# Set bazel configuration for CircleCI runs.
|
||||
####################################################################################################
|
||||
cp "${PROJECT_ROOT}/.circleci/bazel.linux.rc" ".bazelrc.user";
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Variables
|
||||
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
|
||||
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
|
||||
|
||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||
source $envHelpersPath;
|
||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define PUBLIC environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
||||
####################################################################################################
|
||||
setPublicVar CI "$CI"
|
||||
setPublicVar PROJECT_ROOT "$projectDir";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
|
||||
# workflows of such builds).
|
||||
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
|
||||
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
|
||||
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
|
||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
|
||||
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define "lazy" PUBLIC environment variables for CircleCI.
|
||||
# (I.e. functions to set an environment variable when called.)
|
||||
####################################################################################################
|
||||
createPublicVarSetter CI_STABLE_BRANCH "\$(npm info @angular/core dist-tags.latest | sed -r 's/^\\s*([0-9]+\\.[0-9]+)\\.[0-9]+.*$/\\1.x/')";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SECRET environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SauceLabs environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setPublicVar SAUCE_USERNAME "angular-framework";
|
||||
setSecretVar SAUCE_ACCESS_KEY "f4bf7c639c5a-c6bb-d6a4-a4b5-800aa111";
|
||||
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
|
||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-framework-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
|
||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||
|
||||
####################################################################################################
|
||||
# Create shell script in /tmp for Bazel actions to access CI envs without
|
||||
# busting the cache. Used by payload-size.sh script in integration tests.
|
||||
####################################################################################################
|
||||
readonly bazelVarEnv="/tmp/bazel-ci-env.sh"
|
||||
echo "# Setup by /.circle/env.sh" > $bazelVarEnv
|
||||
echo "export PROJECT_ROOT=\"${PROJECT_ROOT}\";" >> $bazelVarEnv
|
||||
echo "export CI_BRANCH=\"${CI_BRANCH}\";" >> $bazelVarEnv
|
||||
echo "export CI_BUILD_URL=\"${CI_BUILD_URL}\";" >> $bazelVarEnv
|
||||
echo "export CI_COMMIT=\"${CI_COMMIT}\";" >> $bazelVarEnv
|
||||
echo "export CI_PULL_REQUEST=\"${CI_PULL_REQUEST}\";" >> $bazelVarEnv
|
||||
echo "export CI_REPO_NAME=\"${CI_REPO_NAME}\";" >> $bazelVarEnv
|
||||
echo "export CI_REPO_OWNER=\"${CI_REPO_OWNER}\";" >> $bazelVarEnv
|
||||
echo "export CI_SECRET_PAYLOAD_FIREBASE_TOKEN=\"${CI_SECRET_PAYLOAD_FIREBASE_TOKEN}\";" >> $bazelVarEnv
|
||||
|
||||
####################################################################################################
|
||||
# Platform-specific environment setup (which can leverage the base variables from here)
|
||||
####################################################################################################
|
||||
|
||||
# Conditionally, load additional environment settings based on the current VM
|
||||
# operating system running. We detect Windows by checking for `%AppData%`.
|
||||
if [[ -n "${APPDATA}" ]]; then
|
||||
source ${projectDir}/.circleci/env.windows.sh
|
||||
else
|
||||
source ${projectDir}/.circleci/env.linux.sh
|
||||
fi
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
####################################################################################################
|
||||
# Set bazel configuration for CircleCI runs.
|
||||
####################################################################################################
|
||||
cp "${PROJECT_ROOT}/.circleci/bazel.windows.rc" ".bazelrc.user";
|
||||
|
||||
# Override the `PATH` environment variable so that the windows-nvm NodeJS version
|
||||
# always has precedence over potential existing NodeJS versions from the image.
|
||||
setPublicVar PATH "/c/Program Files/nodejs/:$PATH"
|
||||
|
||||
# Expose the Bazelisk version. We need to run Bazelisk globally since Windows has problems launching
|
||||
# Bazel from a node modules directoy that might be modified by the Bazel Yarn install then.
|
||||
setPublicVar BAZELISK_VERSION \
|
||||
"$(cd ${PROJECT_ROOT}; node -p 'require("./package.json").devDependencies["@bazel/bazelisk"]')"
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# Install bazel remote cache proxy
|
||||
# This is temporary until the feature is no longer experimental on CircleCI.
|
||||
# See remote cache documentation in /docs/BAZEL.md
|
||||
|
||||
set -u -e
|
||||
|
||||
readonly DOWNLOAD_URL="https://5-116431813-gh.circle-artifacts.com/0/pkg/bazel-remote-proxy-$(uname -s)_$(uname -m)"
|
||||
|
||||
curl --fail -o ~/bazel-remote-proxy "$DOWNLOAD_URL"
|
||||
chmod +x ~/bazel-remote-proxy
|
||||
@@ -1,5 +1,6 @@
|
||||
# Image metadata and config.
|
||||
# Ideally, the Node.js version should match what we use on CI.
|
||||
# See `executors > default-executor` in `.circleci/config.yml`.
|
||||
FROM cimg/node:18.13.0@sha256:45d0ee279f522c4562a464df71108104cc9b2187205333ffd0707d4f05589731
|
||||
|
||||
|
||||
@@ -11,7 +12,7 @@ LABEL name="Angular dev environment" \
|
||||
EXPOSE 4000 4200 4433 5000 8080 9876
|
||||
|
||||
|
||||
# Switch to `root`.
|
||||
# Switch to `root` (CircleCI images use `circleci` as the user).
|
||||
USER root
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
"postCreateCommand": "yarn install",
|
||||
"extensions": [
|
||||
"devondcarew.bazel-code",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin"
|
||||
"gkalpak.aio-docs-utils",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||
//"angular.ng-template",
|
||||
//"dbaeumer.vscode-eslint",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: 'Docs or angular.dev Bug Report'
|
||||
description: Report an issue in Angular's documentation or angular.dev application
|
||||
name: 'Docs or angular.io Bug Report'
|
||||
description: Report an issue in Angular's documentation or angular.io application
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Security issue disclosure
|
||||
url: https://angular.dev/best-practices/security#report-issues
|
||||
url: https://angular.io/guide/security#report-issues
|
||||
about: Report a security issue in Angular Framework, CDK, Material, or CLI
|
||||
- name: Angular CLI
|
||||
url: https://github.com/angular/angular-cli/issues/new/choose
|
||||
|
||||
@@ -18,7 +18,7 @@ What kind of change does this PR introduce?
|
||||
- [ ] Build related changes
|
||||
- [ ] CI related changes
|
||||
- [ ] Documentation content changes
|
||||
- [ ] angular.dev application / infrastructure changes
|
||||
- [ ] angular.io application / infrastructure changes
|
||||
- [ ] Other... Please describe:
|
||||
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
load("//tools:defaults.bzl", "esbuild_checked_in")
|
||||
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
])
|
||||
|
||||
esbuild_checked_in(
|
||||
name = "main",
|
||||
entry_point = "//.github/actions/deploy-docs-site/lib:main.ts",
|
||||
external = [
|
||||
"undici",
|
||||
],
|
||||
platform = "node",
|
||||
target = "node14",
|
||||
deps = [
|
||||
"//.github/actions/deploy-docs-site/lib",
|
||||
],
|
||||
)
|
||||
@@ -1,19 +0,0 @@
|
||||
name: 'Deploy angular.dev site'
|
||||
description: 'Automatically deploy and set up redirects for angular.dev'
|
||||
author: 'Angular'
|
||||
inputs:
|
||||
serviceKey:
|
||||
description: 'The service key used for firebase deployments.'
|
||||
required: true
|
||||
githubReleaseTrainReadToken:
|
||||
description: 'GitHub access token for reading release trains without rate limits.'
|
||||
required: true
|
||||
configPath:
|
||||
description: 'The path to the firebase config file.'
|
||||
required: true
|
||||
distDir:
|
||||
description: 'The path to the firebase dist directory.'
|
||||
required: true
|
||||
runs:
|
||||
using: 'node20'
|
||||
main: 'main.js'
|
||||
@@ -1,23 +0,0 @@
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
package(default_visibility = ["//.github/actions/deploy-docs-site:__subpackages__"])
|
||||
|
||||
exports_files([
|
||||
"main.ts",
|
||||
])
|
||||
|
||||
ts_library(
|
||||
name = "lib",
|
||||
srcs = glob(
|
||||
["*.ts"],
|
||||
),
|
||||
#tsconfig = "//.github/actions/deploy-docs-site:tsconfig.json",
|
||||
deps = [
|
||||
"@npm//@actions/core",
|
||||
"@npm//@actions/github",
|
||||
"@npm//@angular/ng-dev",
|
||||
"@npm//@types/node",
|
||||
"@npm//@types/tmp",
|
||||
"@npm//tmp",
|
||||
],
|
||||
)
|
||||
@@ -1,20 +0,0 @@
|
||||
import {fileSync} from 'tmp';
|
||||
import {writeSync} from 'fs';
|
||||
import {getInput, setSecret} from '@actions/core';
|
||||
|
||||
let credentialFilePath: undefined | string;
|
||||
|
||||
export function getCredentialFilePath(): string {
|
||||
if (credentialFilePath === undefined) {
|
||||
const tmpFile = fileSync({postfix: '.json'});
|
||||
writeSync(tmpFile.fd, getInput('serviceKey', {required: true}));
|
||||
setSecret(tmpFile.name);
|
||||
credentialFilePath = tmpFile.name;
|
||||
}
|
||||
return credentialFilePath;
|
||||
}
|
||||
|
||||
/** Github access token. Used for querying the active release trains. */
|
||||
export const githubReleaseTrainReadToken: string = getInput('githubReleaseTrainReadToken', {
|
||||
required: true,
|
||||
});
|
||||
@@ -1,116 +0,0 @@
|
||||
import {cp, mkdtemp, readFile, rm, writeFile} from 'fs/promises';
|
||||
import {Deployment} from './deployments';
|
||||
import {join} from 'path';
|
||||
|
||||
import {tmpdir} from 'os';
|
||||
import {spawnSync} from 'child_process';
|
||||
import {getCredentialFilePath} from './credential';
|
||||
|
||||
export async function deployToFirebase(
|
||||
deployment: Deployment,
|
||||
configPath: string,
|
||||
distDirPath: string,
|
||||
) {
|
||||
if (deployment.destination == undefined) {
|
||||
console.log(`No deployment necessary for docs created from: ${deployment.branch}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Preparing for deployment to firebase...');
|
||||
|
||||
const tmpDeployDir = await mkdtemp(join(tmpdir(), 'deploy-directory'));
|
||||
const deployConfigPath = join(tmpDeployDir, 'firebase.json');
|
||||
|
||||
const config = JSON.parse(await readFile(configPath, {encoding: 'utf-8'})) as {
|
||||
hosting: {public: string};
|
||||
};
|
||||
config['hosting']['public'] = './dist';
|
||||
|
||||
await writeFile(deployConfigPath, JSON.stringify(config, null, 2));
|
||||
|
||||
await cp(distDirPath, join(tmpDeployDir, 'dist'), {recursive: true});
|
||||
spawnSync(`chmod 777 -R ${tmpDeployDir}`, {encoding: 'utf-8', shell: true});
|
||||
|
||||
firebase(
|
||||
`target:clear --config ${deployConfigPath} --project angular-dev-site hosting angular-docs`,
|
||||
tmpDeployDir,
|
||||
);
|
||||
firebase(
|
||||
`target:apply --config ${deployConfigPath} --project angular-dev-site hosting angular-docs ${deployment.destination}`,
|
||||
tmpDeployDir,
|
||||
);
|
||||
firebase(
|
||||
`deploy --config ${deployConfigPath} --project angular-dev-site --only hosting --non-interactive`,
|
||||
tmpDeployDir,
|
||||
);
|
||||
firebase(
|
||||
`target:clear --config ${deployConfigPath} --project angular-dev-site hosting angular-docs`,
|
||||
tmpDeployDir,
|
||||
);
|
||||
|
||||
await rm(tmpDeployDir, {recursive: true});
|
||||
}
|
||||
|
||||
export async function setupRedirect(deployment: Deployment) {
|
||||
if (deployment.redirect === undefined) {
|
||||
console.log(`No redirect necessary for docs created from: ${deployment.branch}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Preparing to set up redirect on firebase...');
|
||||
|
||||
const redirectConfig = JSON.stringify(
|
||||
{
|
||||
hosting: {
|
||||
target: 'angular-docs',
|
||||
redirects: [
|
||||
{
|
||||
type: 302,
|
||||
regex: '^(.*)$',
|
||||
destination: `${deployment.redirect.to}:1`,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
);
|
||||
|
||||
const tmpRedirectDir = await mkdtemp(join(tmpdir(), 'redirect-directory'));
|
||||
const redirectConfigPath = join(tmpRedirectDir, 'firebase.json');
|
||||
|
||||
await writeFile(redirectConfigPath, redirectConfig);
|
||||
spawnSync(`chmod 777 -R ${tmpRedirectDir}`, {encoding: 'utf-8', shell: true});
|
||||
|
||||
firebase(
|
||||
`target:clear --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs`,
|
||||
tmpRedirectDir,
|
||||
);
|
||||
firebase(
|
||||
`target:apply --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs ${deployment.redirect.from}`,
|
||||
tmpRedirectDir,
|
||||
);
|
||||
firebase(
|
||||
`deploy --config ${redirectConfigPath} --project angular-dev-site --only hosting --non-interactive`,
|
||||
tmpRedirectDir,
|
||||
);
|
||||
firebase(
|
||||
`target:clear --config ${redirectConfigPath} --project angular-dev-site hosting angular-docs`,
|
||||
tmpRedirectDir,
|
||||
);
|
||||
|
||||
await rm(tmpRedirectDir, {recursive: true});
|
||||
}
|
||||
|
||||
function firebase(cmd: string, cwd?: string) {
|
||||
spawnSync('npx', `-y firebase-tools@13.15.1 ${cmd}`.split(' '), {
|
||||
cwd,
|
||||
encoding: 'utf-8',
|
||||
shell: true,
|
||||
stdio: 'inherit',
|
||||
env: {
|
||||
...process.env,
|
||||
GOOGLE_APPLICATION_CREDENTIALS: getCredentialFilePath(),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import {fetchLongTermSupportBranchesFromNpm, ActiveReleaseTrains} from '@angular/ng-dev';
|
||||
import {ReleaseConfig} from '@angular/ng-dev';
|
||||
import {AuthenticatedGitClient} from '@angular/ng-dev';
|
||||
|
||||
export interface Deployment {
|
||||
branch: string;
|
||||
redirect?: {
|
||||
from: string;
|
||||
to: string;
|
||||
};
|
||||
destination?: string;
|
||||
}
|
||||
|
||||
export type Deployments = Map<string, Deployment>;
|
||||
|
||||
export async function getDeployments(): Promise<Deployments> {
|
||||
const {github} = await AuthenticatedGitClient.get();
|
||||
const releaseTrains = await ActiveReleaseTrains.fetch({
|
||||
api: github,
|
||||
name: 'angular',
|
||||
owner: 'angular',
|
||||
nextBranchName: 'main',
|
||||
});
|
||||
const ltsBranches = await fetchLongTermSupportBranchesFromNpm({
|
||||
representativeNpmPackage: '@angular/core',
|
||||
} as ReleaseConfig);
|
||||
|
||||
const docSites = new Map<string, Deployment>();
|
||||
|
||||
[...ltsBranches.active, ...ltsBranches.inactive].forEach((branch) => {
|
||||
docSites.set(branch.name, {
|
||||
branch: branch.name,
|
||||
destination: `v${branch.version.major}-angular-dev`,
|
||||
});
|
||||
});
|
||||
|
||||
docSites.set(releaseTrains.latest.branchName, {
|
||||
branch: releaseTrains.latest.branchName,
|
||||
redirect: {
|
||||
from: `v${releaseTrains.latest.version.major}-angular-dev`,
|
||||
to: 'https://angular.dev',
|
||||
},
|
||||
destination: 'angular-dev-site',
|
||||
});
|
||||
|
||||
if (releaseTrains.releaseCandidate) {
|
||||
docSites.set(releaseTrains.next.branchName, {
|
||||
branch: releaseTrains.next.branchName,
|
||||
});
|
||||
|
||||
docSites.set(releaseTrains.releaseCandidate.branchName, {
|
||||
branch: releaseTrains.releaseCandidate.branchName,
|
||||
destination: 'next-angular-dev',
|
||||
redirect: {
|
||||
from: `v${releaseTrains.releaseCandidate.version.major}-angular-dev`,
|
||||
to: 'https://next.angular.dev',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
docSites.set(releaseTrains.next.branchName, {
|
||||
branch: releaseTrains.next.branchName,
|
||||
destination: 'next-angular-dev',
|
||||
});
|
||||
}
|
||||
|
||||
return docSites;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
import {getInput, setFailed} from '@actions/core';
|
||||
import {context} from '@actions/github';
|
||||
import {deployToFirebase, setupRedirect} from './deploy';
|
||||
import {getDeployments} from './deployments';
|
||||
import {AuthenticatedGitClient, GithubConfig, setConfig} from '@angular/ng-dev';
|
||||
import {githubReleaseTrainReadToken} from './credential';
|
||||
|
||||
const refMatcher = /refs\/heads\/(.*)/;
|
||||
|
||||
async function deployDocs() {
|
||||
setConfig({
|
||||
github: <GithubConfig>{
|
||||
mainBranchName: 'main',
|
||||
name: 'angular',
|
||||
owner: 'angular',
|
||||
},
|
||||
});
|
||||
|
||||
AuthenticatedGitClient.configure(githubReleaseTrainReadToken);
|
||||
|
||||
if (context.eventName !== 'push') {
|
||||
throw Error();
|
||||
}
|
||||
const matchedRef = context.ref.match(refMatcher);
|
||||
if (matchedRef === null) {
|
||||
throw Error();
|
||||
}
|
||||
|
||||
const currentBranch = matchedRef[1];
|
||||
const configPath = getInput('configPath');
|
||||
const distDir = getInput('distDir');
|
||||
|
||||
const deployment = (await getDeployments()).get(currentBranch);
|
||||
if (deployment === undefined) {
|
||||
console.log(`Current branch (${currentBranch}) does not deploy a documentation site.`);
|
||||
console.log(`Exiting...`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log('Doc site deployment information');
|
||||
console.log('');
|
||||
console.log('Current Branch:');
|
||||
console.log(` ${deployment.branch}`);
|
||||
console.log('');
|
||||
console.log('Firebase Site:');
|
||||
if (deployment.destination === undefined) {
|
||||
console.log(' No deployment of a documenation site is necessary');
|
||||
} else {
|
||||
console.log(` Deploying to: ${deployment.destination}`);
|
||||
}
|
||||
console.log('');
|
||||
console.log('Redirect Configuration:');
|
||||
if (deployment.redirect === undefined) {
|
||||
console.log(' No redirects are necessary');
|
||||
} else {
|
||||
console.log(` From: ${deployment.redirect.from}`);
|
||||
console.log(` To: ${deployment.redirect.to}`);
|
||||
}
|
||||
|
||||
await deployToFirebase(deployment, configPath, distDir);
|
||||
await setupRedirect(deployment);
|
||||
}
|
||||
|
||||
// Only run if the action is executed in a repository with is in the Angular org. This is in place
|
||||
// to prevent the action from actually running in a fork of a repository with this action set up.
|
||||
if (context.repo.owner === 'angular') {
|
||||
deployDocs().catch((e: Error) => {
|
||||
setFailed(e.message);
|
||||
console.error(e);
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
'The action was skipped as this action is only meant to run in repos belonging to the Angular organization.',
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "Node16",
|
||||
"target": "es2020",
|
||||
"lib": ["es2021", "dom"],
|
||||
"experimentalDecorators": true,
|
||||
"strict": true,
|
||||
"outDir": "../../../dist/tsc-non-bazel-out",
|
||||
"skipLibCheck": true,
|
||||
"noImplicitOverride": true,
|
||||
// TODO(ESM): Remove this when Bazel also uses the Node resolution.
|
||||
"esModuleInterop": true,
|
||||
"noImplicitReturns": true,
|
||||
"jsx": "react",
|
||||
"jsxFactory": "h",
|
||||
"jsxFragmentFactory": "Fragment"
|
||||
},
|
||||
"exclude": []
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
name: 'Saucelabs legacy test job'
|
||||
description: 'Runs tests against Saucelabs (outside of Bazel)'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Starting Saucelabs tunnel service
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
||||
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
||||
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
||||
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
||||
- name: Preparing Bazel-generated fixtures required in legacy tests
|
||||
shell: bash
|
||||
run: |
|
||||
yarn bazel build //packages/core/test:downleveled_es5_fixture //packages/common/locales
|
||||
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
||||
mkdir -p dist/legacy-test-out/core/test/reflection/
|
||||
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
||||
dist/legacy-test-out/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
||||
# Locale files are needed for i18n tests running within Saucelabs. These are added
|
||||
# directly as sources so that the TypeScript compilation of `/packages/tsconfig.json`
|
||||
# can succeed. Note that the base locale and currencies files are checked-in, so
|
||||
# we do not need to re-generate those through Bazel.
|
||||
mkdir -p packages/common/locales/extra
|
||||
cp dist/bin/packages/common/locales/*.ts packages/common/locales
|
||||
cp dist/bin/packages/common/locales/extra/*.ts packages/common/locales/extra
|
||||
- name: Build bundle of tests to run on Saucelabs
|
||||
shell: bash
|
||||
run: node tools/legacy-saucelabs/build-saucelabs-test-bundle.mjs
|
||||
- name: Wait and confirm Saucelabs tunnel has connected
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||
- name: Running tests on Saucelabs.
|
||||
shell: bash
|
||||
run: KARMA_WEB_TEST_MODE=SL_REQUIRED yarn karma start ./karma-js.conf.js --single-run
|
||||
- name: Stop Saucelabs tunnel service
|
||||
shell: bash
|
||||
run: ./tools/saucelabs/sauce-service.sh stop
|
||||
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4
|
||||
- uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4
|
||||
with:
|
||||
path: |
|
||||
./node_modules/
|
||||
|
||||
@@ -21,16 +21,16 @@ jobs:
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --full_build_adev --config=release
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
with:
|
||||
token: '${{secrets.GITHUB_TOKEN}}'
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
|
||||
@@ -13,9 +13,9 @@ jobs:
|
||||
assistant_to_the_branch_manager:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
|
||||
id: comment-branch
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
# Specify repository as the PR branch might be from a fork.
|
||||
repository: ${{steps.comment-branch.outputs.head_owner}}/${{steps.comment-branch.outputs.head_repo}}
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
|
||||
+121
-33
@@ -1,10 +1,12 @@
|
||||
name: CI (push)
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- '[0-9]+.[0-9]+.x'
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -21,11 +23,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./node_modules
|
||||
./aio/node_modules
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Install node modules in aio
|
||||
run: yarn install --frozen-lockfile --cwd aio
|
||||
- name: Check code lint
|
||||
run: yarn -s tslint
|
||||
- name: Check for circular dependencies
|
||||
@@ -36,18 +43,28 @@ jobs:
|
||||
run: yarn -s ng-dev ngbot verify
|
||||
- name: Confirm code builds with typescript as expected
|
||||
run: yarn -s check-tooling-setup
|
||||
- name: Check commit message
|
||||
# Commit message validation is only done on pull requests as its too late to validate once
|
||||
# it has been merged.
|
||||
if: github.event_name == 'pull_request'
|
||||
run: yarn ng-dev commit-message validate-range ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
|
||||
- name: Check code format
|
||||
# Code formatting checks are only done on pull requests as its too late to validate once
|
||||
# it has been merged.
|
||||
if: github.event_name == 'pull_request'
|
||||
run: yarn ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
|
||||
|
||||
devtools:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -59,13 +76,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
@@ -76,30 +93,29 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev in fast mode to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --config=release
|
||||
- name: Run tests
|
||||
run: yarn bazel test //adev/...
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel test --config=aio_local_deps //adev:test
|
||||
|
||||
publish-snapshots:
|
||||
if: github.event_name == 'push'
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -111,7 +127,7 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -119,9 +135,9 @@ jobs:
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -152,38 +168,110 @@ jobs:
|
||||
- run: yarn --cwd packages/zone.js/test/typings install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd packages/zone.js/test/typings test
|
||||
|
||||
bazel-saucelabs:
|
||||
# TODO: Replace legacy job with Bazel saucelabs job.
|
||||
if: github.event_name == 'push'
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@50bb71e51d3372ca2e359adb9069f89beeac4ae7
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
- name: Run all saucelabs bazel tests
|
||||
run: |
|
||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "fixme-saucelabs", ...)')
|
||||
yarn bazel test --config=saucelabs --jobs=$JOBS ${TESTS}
|
||||
|
||||
saucelabs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- uses: ./.github/actions/saucelabs-legacy
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@50bb71e51d3372ca2e359adb9069f89beeac4ae7
|
||||
- name: Starting Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
|
||||
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
|
||||
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
|
||||
# test in all supported browsers on Saucelabs anyway until this job can be removed.
|
||||
- name: Preparing Bazel-generated fixtures required in legacy tests
|
||||
run: |
|
||||
yarn bazel build //packages/core/test:downleveled_es5_fixture //packages/common/locales
|
||||
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
|
||||
mkdir -p dist/legacy-test-out/core/test/reflection/
|
||||
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
|
||||
dist/legacy-test-out/core/test/reflection/es5_downleveled_inheritance_fixture.js
|
||||
# Locale files are needed for i18n tests running within Saucelabs. These are added
|
||||
# directly as sources so that the TypeScript compilation of `/packages/tsconfig.json`
|
||||
# can succeed. Note that the base locale and currencies files are checked-in, so
|
||||
# we do not need to re-generate those through Bazel.
|
||||
mkdir -p packages/common/locales/extra
|
||||
cp dist/bin/packages/common/locales/*.ts packages/common/locales
|
||||
cp dist/bin/packages/common/locales/extra/*.ts packages/common/locales/extra
|
||||
- name: Build bundle of tests to run on Saucelabs
|
||||
run: node tools/legacy-saucelabs/build-saucelabs-test-bundle.mjs
|
||||
- name: Wait and confirm Saucelabs tunnel has connected
|
||||
run: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||
timeout-minutes: 3
|
||||
- name: Running tests on Saucelabs.
|
||||
run: KARMA_WEB_TEST_MODE=SL_REQUIRED yarn karma start ./karma-js.conf.js --single-run
|
||||
- name: Stop Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh stop
|
||||
|
||||
adev-deploy:
|
||||
needs: [adev]
|
||||
if: needs.adev.result == 'success'
|
||||
if: needs.adev.result == 'success' && github.event_name == 'push' && github.ref_name == 'main'
|
||||
env:
|
||||
DEPLOY_PROJECT: angular-dev-site
|
||||
DEPLOY_SITE: angular-dev-site
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --full_build_adev --config=release
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- name: Move generated project files into deployment directory
|
||||
run: cp -r dist/bin/adev/build adev/build
|
||||
- name: Setup firebase context
|
||||
run: |
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{ env.DEPLOY_PROJECT }} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{ env.DEPLOY_PROJECT }} hosting angular-docs ${{ env.DEPLOY_SITE }}
|
||||
- name: Deploy to firebase
|
||||
uses: ./.github/actions/deploy-docs-site
|
||||
uses: FirebaseExtended/action-hosting-deploy@120e124148ab7016bec2374e5050f15051255ba2 # v0.7.1
|
||||
with:
|
||||
serviceKey: ${{ secrets.ANGULAR_DEV_SITE_DEPLOY }}
|
||||
githubReleaseTrainReadToken: ${{ secrets.DOCS_DEPLOY_GITHUB_RELEASE_TRAIN_TOKEN }}
|
||||
configPath: 'adev/firebase.json'
|
||||
distDir: 'dist/bin/adev/build/browser'
|
||||
entryPoint: './adev'
|
||||
firebaseServiceAccount: ${{ secrets.ANGULAR_DEV_SITE_DEPLOY }}
|
||||
projectId: ${{ env.DEPLOY_PROJECT }}
|
||||
channelId: live
|
||||
|
||||
@@ -12,14 +12,14 @@ jobs:
|
||||
labels:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -13,8 +13,8 @@ jobs:
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Manual jobs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
|
||||
jobs:
|
||||
# Bazel saucelabs job resides in `manual.yml` because it's currently unstable, but
|
||||
# kept as "runnable" for debugging/stabilization effort purposes.
|
||||
bazel-saucelabs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Saucelabs Variables
|
||||
uses: angular/dev-infra/github-actions/saucelabs@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
- name: Run all saucelabs bazel tests
|
||||
run: |
|
||||
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "fixme-saucelabs", ...)')
|
||||
yarn bazel test --config=saucelabs --jobs=$JOBS ${TESTS}
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Monitoring
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run at 10:00AM every day.
|
||||
- cron: '0 10 * * *'
|
||||
|
||||
permissions: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
check_aio:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
MINIMUM_PWA_SCORE: 95
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: ['https://next.angular.io/', 'https://angular.io/']
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
- name: Install node modules in aio
|
||||
run: yarn install --frozen-lockfile --cwd aio
|
||||
- name: Run basic e2e and deployment config tests.
|
||||
run: yarn --cwd aio test-production-url --test_env=TARGET_URL="${{ matrix.version }}"
|
||||
- name: Run PWA-score tests.
|
||||
run: yarn --cwd aio test-pwa-score "${{ matrix.version }}" "${{ env.MINIMUM_PWA_SCORE }}"
|
||||
- name: Run a11y tests.
|
||||
run: yarn --cwd aio test-a11y-score "${{ matrix.version }}"
|
||||
|
||||
check_contributor_links:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@5774b71c01a55c4c998f858ee37d3b77ae704c31
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Install node modules in aio
|
||||
run: yarn install --frozen-lockfile --cwd aio
|
||||
- name: Check website provided in contributors.json file
|
||||
run: node aio/scripts/test-external-urls.js
|
||||
@@ -1,53 +0,0 @@
|
||||
name: Performance Tracking
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
id-token: 'write'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
list:
|
||||
timeout-minutes: 3
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
workflows: ${{ steps.workflows.outputs.workflows }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn -s install --frozen-lockfile
|
||||
- id: workflows
|
||||
run: echo "workflows=$(yarn -s ng-dev perf workflows --list)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
workflow:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
needs: list
|
||||
strategy:
|
||||
matrix:
|
||||
workflow: ${{ fromJSON(needs.list.outputs.workflows) }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn -s install --frozen-lockfile
|
||||
# We utilize the google-github-actions/auth action to allow us to get an active credential using workflow
|
||||
# identity federation. This allows us to request short lived credentials on demand, rather than storing
|
||||
# credentials in secrets long term. More information can be found at:
|
||||
# https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform
|
||||
- uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # v2
|
||||
with:
|
||||
project_id: 'internal-200822'
|
||||
workload_identity_provider: 'projects/823469418460/locations/global/workloadIdentityPools/measurables-tracking/providers/angular'
|
||||
service_account: 'measures-uploader@internal-200822.iam.gserviceaccount.com'
|
||||
- run: yarn ng-dev perf workflows --name ${{ matrix.workflow }} --commit-sha ${{github.sha}}
|
||||
@@ -1,177 +0,0 @@
|
||||
name: Pull Request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Check code lint
|
||||
run: yarn -s tslint
|
||||
- name: Check for circular dependencies
|
||||
run: yarn -s ts-circular-deps:check
|
||||
- name: Validate pull approve configuration
|
||||
run: yarn -s ng-dev pullapprove verify
|
||||
- name: Validate angular robot configuration
|
||||
run: yarn -s ng-dev ngbot verify
|
||||
- name: Confirm code builds with typescript as expected
|
||||
run: yarn -s check-tooling-setup
|
||||
- name: Check commit message
|
||||
run: yarn ng-dev commit-message validate-range ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}
|
||||
- name: Check code format
|
||||
run: yarn ng-dev format changed --check ${{ github.event.pull_request.base.sha }}
|
||||
- name: Check Package Licenses
|
||||
uses: angular/dev-infra/github-actions/linting/licenses@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
allow-dependencies-licenses: 'pkg:npm/google-protobuf@'
|
||||
|
||||
devtools:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
run: yarn devtools:test
|
||||
- name: Test build
|
||||
run: yarn devtools:build:chrome
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
run: yarn test:ci
|
||||
|
||||
artifacts:
|
||||
needs: [test]
|
||||
if: needs.test.result == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
run: yarn tsx ./scripts/build/build-packages-dist.mts
|
||||
- name: Archive build artifacts
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: pr-artifacts-${{ github.event.number }}
|
||||
path: dist/packages-dist/
|
||||
|
||||
adev:
|
||||
runs-on:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev in fast mode to ensure it continues to work
|
||||
run: yarn bazel build //adev:build --config=release
|
||||
- name: Run tests
|
||||
run: yarn bazel test //adev/...
|
||||
|
||||
zone-js:
|
||||
runs-on:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./node_modules
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
yarn bazel build \
|
||||
//packages/zone.js/bundles:zone.umd.js \
|
||||
//packages/zone.js:npm_package \
|
||||
//packages/zone.js/test/closure:closure_js \
|
||||
|
||||
- run: |
|
||||
rm -Rf packages/zone.js/build
|
||||
rm -Rf packages/zone.js/test/extra/*.umd.js
|
||||
|
||||
mkdir -p packages/zone.js/build/
|
||||
mkdir -p packages/zone.js/build/test/
|
||||
|
||||
cp dist/bin/packages/zone.js/bundles/zone.umd.js packages/zone.js/build/zone.umd.js
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/
|
||||
cp dist/bin/packages/zone.js/test/closure/zone.closure.mjs ./packages/zone.js/build/test/zone.closure.mjs
|
||||
|
||||
# Install
|
||||
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
||||
# Run zone.js tools tests
|
||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
||||
- run: yarn --cwd packages/zone.js jest:test
|
||||
- run: yarn --cwd packages/zone.js jest:nodetest
|
||||
- run: yarn --cwd packages/zone.js electrontest
|
||||
- run: yarn --cwd packages/zone.js/test/typings install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd packages/zone.js/test/typings test
|
||||
|
||||
saucelabs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
env:
|
||||
SAUCE_TUNNEL_IDENTIFIER: angular-framework-${{ github.run_number }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- uses: ./.github/actions/saucelabs-legacy
|
||||
@@ -25,12 +25,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Run analysis'
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
|
||||
# Upload the results as artifacts.
|
||||
- name: 'Upload artifact'
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -47,6 +47,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: 'Upload to code-scanning'
|
||||
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
|
||||
uses: github/codeql-action/upload-sarif@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Update ADEV Angular CLI help
|
||||
name: Update AIO Angular CLI help
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
# Setting `persist-credentials: false` prevents the github-action account from being the
|
||||
# account that is attempted to be used for authentication, instead the remote is set to
|
||||
@@ -28,11 +28,11 @@ jobs:
|
||||
# This is needed as otherwise the PR creation will fail with `shallow update not allowed` when the forked branch is not in sync.
|
||||
fetch-depth: 0
|
||||
- name: Generate CLI help
|
||||
run: node adev/scripts/update-cli-help/index.mjs
|
||||
run: node aio/scripts/update-cli-help/index.mjs
|
||||
env:
|
||||
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
|
||||
- name: Create a PR (if necessary)
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@40b2cbdbcc40f36f125d721c4e8decd3bb607ea4
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@1421ff04811ecb45812930c5d1f61d912880e75f
|
||||
with:
|
||||
branch-prefix: update-cli-help
|
||||
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
|
||||
|
||||
+8
-3
@@ -4,8 +4,11 @@
|
||||
/bazel-out
|
||||
/integration/bazel/bazel-*
|
||||
*.log
|
||||
node_modules/
|
||||
modules/ssr-benchmarks/node_modules/
|
||||
/node_modules/
|
||||
|
||||
# CircleCI temporary file for cache key computation.
|
||||
# See `save_month_to_file` in `.circleci/config.yml`.
|
||||
month.txt
|
||||
|
||||
# Include when developing application packages.
|
||||
pubspec.lock
|
||||
@@ -53,6 +56,8 @@ baseline.json
|
||||
|
||||
# Husky
|
||||
.husky/_
|
||||
aio/content/examples/.DS_Store
|
||||
|
||||
|
||||
# Ignore cache created with the Angular CLI.
|
||||
.angular/
|
||||
.angular/
|
||||
@@ -6,7 +6,7 @@ export const caretaker: CaretakerConfig = {
|
||||
githubQueries: [
|
||||
{
|
||||
name: 'Merge Queue',
|
||||
query: `is:pr is:open label:"action: merge"`,
|
||||
query: `is:pr is:open status:success label:"action: merge"`,
|
||||
},
|
||||
{
|
||||
name: 'Merge Assistance Queue',
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
workflows:
|
||||
build-adev:
|
||||
name: Build adev
|
||||
prepare:
|
||||
- bazel clean
|
||||
workflow:
|
||||
- bazel build //adev:build
|
||||
+55
-6
@@ -7,8 +7,23 @@ export const format: FormatConfig = {
|
||||
'prettier': {
|
||||
'matchers': [
|
||||
'**/*.{yaml,yml}',
|
||||
'**/*.{js,ts}',
|
||||
'devtools/**/*.{js,ts,html,scss}',
|
||||
'adev/**/*.{js,ts}',
|
||||
'devtools/**/*.{js,ts}',
|
||||
'tools/**/*.{js,ts}',
|
||||
'modules/**/*.{js,ts}',
|
||||
'scripts/**/*.{js,ts}',
|
||||
'packages/animations/**/*.{js,ts}',
|
||||
'packages/bazel/**/*.{js,ts}',
|
||||
'packages/benchpress/**/*.{js,ts}',
|
||||
'packages/common/**/*.{js,ts}',
|
||||
'packages/docs/**/*.{js,ts}',
|
||||
'packages/elements/**/*.{js,ts}',
|
||||
'packages/examples/**/*.{js,ts}',
|
||||
'packages/misc/**/*.{js,ts}',
|
||||
'packages/private/**/*.{js,ts}',
|
||||
'packages/router/**/*.{js,ts}',
|
||||
'packages/service-worker/**/*.{js,ts}',
|
||||
'packages/upgrade/**/*.{js,ts}',
|
||||
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
@@ -16,16 +31,50 @@ export const format: FormatConfig = {
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
],
|
||||
},
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
// Do not format generated ng-dev script
|
||||
'!dev-infra/ng-dev.js',
|
||||
'!dev-infra/build-worker.js',
|
||||
// Do not format compliance test-cases since they must match generated code
|
||||
'!packages/compiler-cli/test/compliance/test_cases/**/*.js',
|
||||
// Do not format the locale files which are checked-in for Google3, but generated using
|
||||
// the `generate-locales-tool` from `packages/common/locales`.
|
||||
'!packages/core/src/i18n/locale_en.ts',
|
||||
'!packages/common/locales/closure-locale.ts',
|
||||
'!packages/common/src/i18n/currencies.ts',
|
||||
// Test cases contain non valid code.
|
||||
'!packages/compiler-cli/test/compliance/test_cases/**/*.{js,ts}',
|
||||
// Temporarily disable formatting for adev
|
||||
'!adev/**',
|
||||
|
||||
// Ignore generated javascript file(s)
|
||||
'!.github/actions/deploy-docs-site/main.js',
|
||||
// Migrated to prettier
|
||||
'!devtools/**/*.{js,ts}',
|
||||
'!tools/**/*.{js,ts}',
|
||||
'!modules/**/*.{js,ts}',
|
||||
'!scripts/**/*.{js,ts}',
|
||||
'!packages/animations/**/*.{js,ts}',
|
||||
'!packages/bazel/**/*.{js,ts}',
|
||||
'!packages/benchpress/**/*.{js,ts}',
|
||||
'!packages/common/**/*.{js,ts}',
|
||||
'!packages/docs/**/*.{js,ts}',
|
||||
'!packages/elements/**/*.{js,ts}',
|
||||
'!packages/examples/**/*.{js,ts}',
|
||||
'!packages/misc/**/*.{js,ts}',
|
||||
'!packages/private/**/*.{js,ts}',
|
||||
'!packages/router/**/*.{js,ts}',
|
||||
'!packages/service-worker/**/*.{js,ts}',
|
||||
'!packages/upgrade/**/*.{js,ts}',
|
||||
],
|
||||
},
|
||||
'buildifier': true,
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
{
|
||||
"syncedFilePatterns": ["LICENSE", "modules/benchmarks/**", "packages/**"],
|
||||
"separateFilePatterns": ["packages/core/primitives/**"],
|
||||
"syncedFilePatterns": [
|
||||
"LICENSE",
|
||||
"modules/benchmarks/**",
|
||||
"packages/**"
|
||||
],
|
||||
"separateFilePatterns": [
|
||||
"packages/core/primitives/**"
|
||||
],
|
||||
"alwaysExternalFilePatterns": [
|
||||
"packages/*",
|
||||
"packages/bazel/**",
|
||||
"packages/bazel/*",
|
||||
"packages/bazel/src/*",
|
||||
"packages/bazel/src/api-extractor/**",
|
||||
"packages/bazel/src/builders/**",
|
||||
"packages/bazel/src/ng_module/**",
|
||||
"packages/bazel/src/ng_package/**",
|
||||
"packages/bazel/src/protractor/**",
|
||||
"packages/bazel/src/schematics/**",
|
||||
"packages/bazel/src/types_bundle/**",
|
||||
"packages/compiler-cli/linker/**",
|
||||
"packages/compiler-cli/src/ngtsc/sourcemaps/**",
|
||||
"packages/compiler-cli/src/ngtsc/testing/**",
|
||||
@@ -12,14 +26,12 @@
|
||||
"packages/compiler-cli/private/tooling.ts",
|
||||
"packages/compiler-cli/private/babel.d.ts",
|
||||
"packages/compiler-cli/src/bin/**",
|
||||
"packages/core/schematics/utils/tsurge/helpers/angular_devkit/**",
|
||||
"packages/docs/**",
|
||||
"packages/elements/schematics/**",
|
||||
"packages/examples/**",
|
||||
"packages/localize/**",
|
||||
"packages/private/**",
|
||||
"packages/service-worker/**",
|
||||
"packages/ssr/BUILD.bazel",
|
||||
"packages/common/locales/generate-locales-tool/**",
|
||||
"packages/common/locales/index.bzl",
|
||||
"packages/http/**",
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ export const release: ReleaseConfig = {
|
||||
return performNpmReleaseBuild();
|
||||
},
|
||||
releaseNotes: {
|
||||
hiddenScopes: ['bazel', 'dev-infra', 'docs-infra', 'zone.js', 'devtools'],
|
||||
hiddenScopes: ['aio', 'bazel', 'dev-infra', 'docs-infra', 'zone.js', 'devtools'],
|
||||
},
|
||||
releasePrLabels: ['area: build & ci', 'action: merge', 'PullApprove: disable'],
|
||||
};
|
||||
|
||||
+3
-4
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"tabs": false,
|
||||
"embeddedLanguageFormatting": "off",
|
||||
"singleQuote": true,
|
||||
"semi": true,
|
||||
"semicolon": true,
|
||||
"quoteProps": "preserve",
|
||||
"bracketSpacing": false,
|
||||
"trailingComma": "all"
|
||||
"bracketSpacing": false
|
||||
}
|
||||
|
||||
+928
-128
File diff suppressed because it is too large
Load Diff
Vendored
+1
@@ -6,5 +6,6 @@
|
||||
"recommendations": [
|
||||
"BazelBuild.vscode-bazel",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
],
|
||||
}
|
||||
|
||||
Vendored
+8
@@ -1,10 +1,16 @@
|
||||
{
|
||||
// Format js and ts files on save with `clang-format.executable`
|
||||
// If `clang-format.executable` is not being used, these two settings should be removed otherwise it will break existing formatting.
|
||||
// You can instead run `yarn gulp format` to manually format your code.
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
// Please install https://marketplace.visualstudio.com/items?itemName=xaver.clang-format to take advantage of `clang-format` in VSCode.
|
||||
// (See https://clang.llvm.org/docs/ClangFormat.html for more info `clang-format`.)
|
||||
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
|
||||
// Exclude third party modules and build artifacts from the editor watchers/searches.
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
@@ -12,12 +18,14 @@
|
||||
"**/node_modules/**": true,
|
||||
"**/bazel-out/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/aio/src/generated/**": true,
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/bower_components": true,
|
||||
"**/bazel-out": true,
|
||||
"**/dist": true,
|
||||
"**/aio/src/generated": true,
|
||||
".history": true,
|
||||
},
|
||||
"git.ignoreLimitWarning": true,
|
||||
|
||||
+147529
File diff suppressed because one or more lines are too long
Vendored
-148049
File diff suppressed because one or more lines are too long
@@ -2,4 +2,4 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
yarn-path ".yarn/releases/yarn-1.22.22.cjs"
|
||||
yarn-path ".yarn/releases/yarn-1.22.19.cjs"
|
||||
|
||||
+3
-3
@@ -64,11 +64,11 @@ config_setting(
|
||||
|
||||
nodejs_binary(
|
||||
name = "yarn_vendored",
|
||||
data = [".yarn/releases/yarn-1.22.22.cjs"],
|
||||
entry_point = ".yarn/releases/yarn-1.22.22.cjs",
|
||||
data = [".yarn/releases/yarn-1.22.19.cjs"],
|
||||
entry_point = ".yarn/releases/yarn-1.22.19.cjs",
|
||||
visibility = [
|
||||
"//aio/tools/examples/shared:__pkg__",
|
||||
"//integration:__subpackages__",
|
||||
"//modules/ssr-benchmarks:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+106
-1206
File diff suppressed because it is too large
Load Diff
+16
-11
@@ -32,7 +32,7 @@ Stack Overflow is a much better place to ask questions since:
|
||||
|
||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||
|
||||
If you would like to chat about the question in real-time, you can reach out via [the Angular community Discord server][discord].
|
||||
If you would like to chat about the question in real-time, you can reach out via [our Discord server][discord].
|
||||
|
||||
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
@@ -89,7 +89,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
We cannot accept code without a signed CLA.
|
||||
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
||||
|
||||
4. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the [angular/angular](https://github.com/angular/angular/fork) repo.
|
||||
4. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) the angular/angular repo.
|
||||
|
||||
5. In your forked repository, make your changes in a new git branch:
|
||||
|
||||
@@ -138,7 +138,7 @@ If we ask for changes via code reviews then:
|
||||
git push
|
||||
```
|
||||
|
||||
For more info on working with fixup commits see [here](./contributing-docs/using-fixup-commits.md).
|
||||
For more info on working with fixup commits see [here](docs/FIXUP_COMMITS.md).
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
@@ -205,9 +205,9 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
* All public API methods **must be documented**.
|
||||
* We follow [Google's TypeScript Style Guide][ts-style-guide], but wrap all code at **100 characters**.
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||
|
||||
An automated formatter is available, see [DEVELOPER.md](contributing-docs/building-and-testing-angular.md#formatting-your-source-code).
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
@@ -260,7 +260,7 @@ The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is opti
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (examples: Github Actions, SauceLabs)
|
||||
* **ci**: Changes to our CI configuration files and scripts (examples: CircleCi, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
@@ -302,7 +302,7 @@ There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts and /tools
|
||||
|
||||
* `docs-infra`: used for docs-app (angular.dev) related changes within the /adev directory of the repo
|
||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||
|
||||
* `migrations`: used for changes to the `ng update` migrations.
|
||||
|
||||
@@ -353,9 +353,9 @@ DEPRECATED: <what is deprecated>
|
||||
Closes #<pr number>
|
||||
```
|
||||
|
||||
Breaking Change section should start with the phrase `BREAKING CHANGE: ` followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||
|
||||
Similarly, a Deprecation section should start with `DEPRECATED: ` followed by a short description of what is deprecated, a blank line, and a detailed description of the deprecation that also mentions the recommended update path.
|
||||
Similarly, a Deprecation section should start with "DEPRECATED: " followed by a short description of what is deprecated, a blank line, and a detailed description of the deprecation that also mentions the recommended update path.
|
||||
|
||||
|
||||
### Revert commits
|
||||
@@ -389,11 +389,16 @@ The following documents can help you sort out issues with GitHub accounts and mu
|
||||
|
||||
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/main/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[corporate-cla]: https://cla.developers.google.com/about/google-corporate
|
||||
[dev-doc]: ./contributing-docs/building-and-testing-angular.md
|
||||
[dev-doc]: https://github.com/angular/angular/blob/main/docs/DEVELOPER.md
|
||||
[github]: https://github.com/angular/angular
|
||||
[discord]: https://discord.gg/angular
|
||||
[individual-cla]: https://cla.developers.google.com/about/google-individual
|
||||
[ts-style-guide]: https://google.github.io/styleguide/tsguide.html
|
||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||
[jsfiddle]: https://jsfiddle.net/
|
||||
[plunker]: https://plnkr.co/edit
|
||||
[runnable]: https://runnable.com/
|
||||
[stackoverflow]: https://stackoverflow.com/questions/tagged/angular
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2025 Google LLC. https://angular.dev/license
|
||||
Copyright (c) 2010-2024 Google LLC. https://angular.io/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h1 align="center">Angular - The modern web developer's platform</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="adev/src/assets/images/press-kit/angular_icon_gradient.gif" alt="angular-logo" width="120px" height="120px"/>
|
||||
<img src="aio/src/assets/images/logos/angular/angular_renaissance.png" alt="angular-logo" width="120px" height="120px"/>
|
||||
<br>
|
||||
<em>Angular is a development platform for building mobile and desktop web applications
|
||||
<br> using TypeScript/JavaScript and other languages.</em>
|
||||
@@ -18,12 +18,15 @@
|
||||
·
|
||||
<a href="https://github.com/angular/angular/issues">Submit an Issue</a>
|
||||
·
|
||||
<a href="https://blog.angular.dev/">Blog</a>
|
||||
<a href="https://blog.angular.io/">Blog</a>
|
||||
<br>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://circleci.com/gh/angular/workflows/angular/tree/main">
|
||||
<img src="https://img.shields.io/circleci/build/github/angular/angular/main.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/@angular/core">
|
||||
<img src="https://img.shields.io/npm/v/@angular/core.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen" alt="Angular on npm" />
|
||||
</a>
|
||||
@@ -32,6 +35,12 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://app.circleci.com/insights/github/angular/angular/workflows/default_workflow?branch=main">
|
||||
<img src="https://dl.circleci.com/insights-snapshot/gh/angular/angular/main/default_workflow/badge.svg" alt="InsightsSnapshot" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
## Documentation
|
||||
@@ -54,7 +63,22 @@ Get started with Angular, learn the fundamentals and explore advanced topics on
|
||||
|
||||
### Local Development
|
||||
|
||||
To contribute to the Angular Docs, check out the [Angular.dev README](adev/README.md)
|
||||
To contribute to Angular docs, you can setup a local environment with the following commands:
|
||||
|
||||
```bash
|
||||
# Clone Angular repo
|
||||
git clone https://github.com/angular/angular.git
|
||||
|
||||
# Navigate to project directory
|
||||
cd angular
|
||||
|
||||
# Install dependencies
|
||||
yarn
|
||||
|
||||
# Build and run local dev server
|
||||
# Note: Initial build will take some time
|
||||
yarn docs
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
@@ -92,7 +116,7 @@ Angular is cross-platform, fast, scalable, has incredible tooling, and is loved
|
||||
## Ecosystem
|
||||
|
||||
<p>
|
||||
<img src="/contributing-docs/images/angular-ecosystem-logos.png" alt="angular ecosystem logos" width="500px" height="auto">
|
||||
<img src="/docs/images/angular-ecosystem-logos.png" alt="angular ecosystem logos" width="500px" height="auto">
|
||||
</p>
|
||||
|
||||
- [Angular Command Line (CLI)][cli]
|
||||
@@ -104,7 +128,7 @@ Angular is cross-platform, fast, scalable, has incredible tooling, and is loved
|
||||
|
||||
## Upgrading
|
||||
|
||||
Check out our [upgrade guide](https://angular.dev/update-guide/) to find out the best way to upgrade your project.
|
||||
Check out our [upgrade guide](https://update.angular.io/) to find out the best way to upgrade your project.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -143,8 +167,8 @@ Join the conversation and help the community.
|
||||
[angularmaterial]: https://material.angular.io/
|
||||
[cli]: https://angular.dev/tools/cli
|
||||
[architecture]: https://angular.dev/essentials
|
||||
[componentstemplates]: https://angular.dev/tutorials/learn-angular/1-components-in-angular
|
||||
[forms]: https://angular.dev/tutorials/learn-angular/15-forms
|
||||
[componentstemplates]: https://angular.dev/tutorials/learn-angular/components-in-angular
|
||||
[forms]: https://angular.dev/tutorials/learn-angular/forms
|
||||
[api]: https://angular.dev/api
|
||||
[angularelements]: https://angular.dev/guide/elements
|
||||
[ssr]: https://angular.dev/guide/ssr
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
Angular is part of Google [Open Source Software Vulnerability Reward Program](https://bughunters.google.com/about/rules/6521337925468160/google-open-source-software-vulnerability-reward-program-rules). For vulnerabilities in Angular, please submit your report [here](https://bughunters.google.com/report).
|
||||
|
||||
For more information, check out [Angular's security policy](https://angular.dev/best-practices/security).
|
||||
For more information, check out [Angular's security policy](https://angular.io/guide/security).
|
||||
|
||||
@@ -2,12 +2,27 @@ workspace(
|
||||
name = "angular",
|
||||
managed_directories = {
|
||||
"@npm": ["node_modules"],
|
||||
"@aio_npm": ["aio/node_modules"],
|
||||
},
|
||||
)
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("//:yarn.bzl", "YARN_LABEL")
|
||||
|
||||
# Add a patch fix for rules_webtesting v0.3.5 required for enabling runfiles on Windows.
|
||||
# TODO: Remove the http_archive for this transitive dependency when a release is cut
|
||||
# for https://github.com/bazelbuild/rules_webtesting/commit/581b1557e382f93419da6a03b91a45c2ac9a9ec8
|
||||
# and the version is updated in rules_nodejs.
|
||||
http_archive(
|
||||
name = "io_bazel_rules_webtesting",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
"//:tools/bazel-repo-patches/rules_webtesting__windows_runfiles_fix.patch",
|
||||
],
|
||||
sha256 = "e9abb7658b6a129740c0b3ef6f5a2370864e102a5ba5ffca2cea565829ed825a",
|
||||
urls = ["https://github.com/bazelbuild/rules_webtesting/releases/download/0.3.5/rules_webtesting.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
patches = [
|
||||
@@ -50,16 +65,16 @@ load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
|
||||
nodejs_register_toolchains(
|
||||
name = "nodejs",
|
||||
node_repositories = {
|
||||
"18.20.0-darwin_arm64": ("node-v18.20.0-darwin-arm64.tar.gz", "node-v18.20.0-darwin-arm64", "10066ad4dd9e03ea5c4c45ef8775420ff37b860de09bbdf87b97e0c07b1ea036"),
|
||||
"18.20.0-darwin_amd64": ("node-v18.20.0-darwin-x64.tar.gz", "node-v18.20.0-darwin-x64", "062ba71618e88e06321de5caa038843c350aababa2d315f3ca7b8551f8e66c1c"),
|
||||
"18.20.0-linux_arm64": ("node-v18.20.0-linux-arm64.tar.xz", "node-v18.20.0-linux-arm64", "afe51da9ffb38ac1e3a20d9a06efd403ced4bf8831ab554a02a088dd8392fd79"),
|
||||
"18.20.0-linux_ppc64le": ("node-v18.20.0-linux-ppc64le.tar.xz", "node-v18.20.0-linux-ppc64le", "9e652bbf53a3e37285b11dfb9d6a9bb8b02010c3b50e5c8229d4cc10e72681da"),
|
||||
"18.20.0-linux_s390x": ("node-v18.20.0-linux-s390x.tar.xz", "node-v18.20.0-linux-s390x", "a6c2a5796b9d9e9bf21da62ec89ff30b41a8108880b9eaa3c912f1ce795a7743"),
|
||||
"18.20.0-linux_amd64": ("node-v18.20.0-linux-x64.tar.xz", "node-v18.20.0-linux-x64", "03eea148e56785babb27930b05ed6bf311aaa3bc573c0399dd63cad2fe5713c7"),
|
||||
"18.20.0-windows_amd64": ("node-v18.20.0-win-x64.zip", "node-v18.20.0-win-x64", "1c0aab05cc6836a8f5148cca345b92ebc948a4a2013f18d117b7ade6ff05aca6"),
|
||||
"18.18.2-darwin_arm64": ("node-v18.18.2-darwin-arm64.tar.gz", "node-v18.18.2-darwin-arm64", "9f982cc91b28778dd8638e4f94563b0c2a1da7aba62beb72bd427721035ab553"),
|
||||
"18.18.2-darwin_amd64": ("node-v18.18.2-darwin-x64.tar.gz", "node-v18.18.2-darwin-x64", "5bb8da908ed590e256a69bf2862238c8a67bc4600119f2f7721ca18a7c810c0f"),
|
||||
"18.18.2-linux_arm64": ("node-v18.18.2-linux-arm64.tar.xz", "node-v18.18.2-linux-arm64", "2e630e18548627f61eaf573233da7949dc0a1df5eef3f486fa9820c5f6c121aa"),
|
||||
"18.18.2-linux_ppc64le": ("node-v18.18.2-linux-ppc64le.tar.xz", "node-v18.18.2-linux-ppc64le", "b0adff5cf5938266b711d6c724fb134d802e0dee40b3a3f73d162de1b3d11880"),
|
||||
"18.18.2-linux_s390x": ("node-v18.18.2-linux-s390x.tar.xz", "node-v18.18.2-linux-s390x", "c70ec2074b5e2b42c55bb4b8105418b67bf8a61c500d9376a07430dfcc341fdb"),
|
||||
"18.18.2-linux_amd64": ("node-v18.18.2-linux-x64.tar.xz", "node-v18.18.2-linux-x64", "75aba25ae76999309fc6c598efe56ce53fbfc221381a44a840864276264ab8ac"),
|
||||
"18.18.2-windows_amd64": ("node-v18.18.2-win-x64.zip", "node-v18.18.2-win-x64", "3bb0e51e579a41a22b3bf6cb2f3e79c03801aa17acbe0ca00fc555d1282e7acd"),
|
||||
},
|
||||
# We need at least Node 18.17 due to some transitive dependencies.
|
||||
node_version = "18.20.0",
|
||||
node_version = "18.18.2",
|
||||
)
|
||||
|
||||
# Download npm dependencies.
|
||||
@@ -75,7 +90,7 @@ yarn_install(
|
||||
"//:.yarnrc",
|
||||
"//:tools/npm-patches/@bazel+jasmine+5.8.1.patch",
|
||||
"//tools:postinstall-patches.js",
|
||||
"//tools/esm-interop:patches/npm/@angular+build-tooling+0.0.0-d30a56c19bafaac67cf44e605ed8c2c0e45b0a51.patch",
|
||||
"//tools/esm-interop:patches/npm/@angular+build-tooling+0.0.0-e0ec7b60641d7f6369be45d8d02663fd50f320be.patch",
|
||||
"//tools/esm-interop:patches/npm/@bazel+concatjs+5.8.1.patch",
|
||||
"//tools/esm-interop:patches/npm/@bazel+esbuild+5.7.1.patch",
|
||||
"//tools/esm-interop:patches/npm/@bazel+protractor+5.7.1.patch",
|
||||
@@ -94,6 +109,54 @@ yarn_install(
|
||||
yarn_lock = "//:yarn.lock",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
name = "aio_npm",
|
||||
# Note that we add the postinstall scripts here so that the dependencies are re-installed
|
||||
# when the postinstall patches are modified.
|
||||
data = [
|
||||
YARN_LABEL,
|
||||
"//:.yarnrc",
|
||||
"//:tools/npm-patches/@bazel+jasmine+5.8.1.patch",
|
||||
"//aio:tools/cli-patches/bazel-architect-output.patch",
|
||||
"//aio:tools/cli-patches/patch.js",
|
||||
],
|
||||
# Currently disabled due to:
|
||||
# 1. Missing Windows support currently.
|
||||
# 2. Incompatibilites with the `ts_library` rule.
|
||||
exports_directories_only = False,
|
||||
manual_build_file_contents = npm_package_archives(),
|
||||
package_json = "//aio:package.json",
|
||||
# We prefer to symlink the `node_modules` to only maintain a single install.
|
||||
# See https://github.com/angular/dev-infra/pull/446#issuecomment-1059820287 for details.
|
||||
symlink_node_modules = True,
|
||||
yarn = YARN_LABEL,
|
||||
yarn_lock = "//aio:yarn.lock",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
name = "aio_example_deps",
|
||||
# Rename the default js_library target from "node_modules" as this obscures the
|
||||
# the source directory stamped as a filegroup in the manual BUILD contents below.
|
||||
all_node_modules_target_name = "node_modules_all",
|
||||
data = [
|
||||
YARN_LABEL,
|
||||
"//:.yarnrc",
|
||||
],
|
||||
# Disabled because, when False, yarn_install preserves the node_modules folder
|
||||
# with bin symlinks in the external repository. This is needed to link the shared
|
||||
# set of deps for example e2es.
|
||||
exports_directories_only = False,
|
||||
manual_build_file_contents = """\
|
||||
filegroup(
|
||||
name = "node_modules_files",
|
||||
srcs = ["node_modules"],
|
||||
)
|
||||
""",
|
||||
package_json = "//aio/tools/examples/shared:package.json",
|
||||
yarn = YARN_LABEL,
|
||||
yarn_lock = "//aio/tools/examples/shared:yarn.lock",
|
||||
)
|
||||
|
||||
load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies")
|
||||
|
||||
aspect_bazel_lib_dependencies()
|
||||
@@ -143,10 +206,10 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "0eae9a0c840e1e0d0b9ace056f8bde06384315315c4e2ebdb5cec722d1d4134b",
|
||||
strip_prefix = "rules_sass-aff53ca13ff2af82d323adb02a83c45a301e9ae8",
|
||||
sha256 = "5633816e996a79c77f44306f6228b9ef18fc2ecb412d63b4e314a132225facba",
|
||||
strip_prefix = "rules_sass-79bd239ce77c101ea1aed575678020bd2999f17d",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/aff53ca13ff2af82d323adb02a83c45a301e9ae8.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/79bd239ce77c101ea1aed575678020bd2999f17d.zip",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -181,15 +244,3 @@ http_archive(
|
||||
strip_prefix = "sc-4.8.2-osx",
|
||||
url = "https://saucelabs.com/downloads/sc-4.8.2-osx.zip",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
name = "npm_ts_versions",
|
||||
data = [
|
||||
YARN_LABEL,
|
||||
"//:.yarnrc",
|
||||
],
|
||||
exports_directories_only = False,
|
||||
package_json = "//packages/core/schematics/migrations/signal-migration/test/ts-versions:package.json",
|
||||
yarn = YARN_LABEL,
|
||||
yarn_lock = "//packages/core/schematics/migrations/signal-migration/test/ts-versions:yarn.lock",
|
||||
)
|
||||
|
||||
+47
-72
@@ -1,17 +1,11 @@
|
||||
load("//:packages.bzl", "link_packages")
|
||||
load("@npm//@angular/build-tooling/bazel/remote-execution:index.bzl", "ENABLE_NETWORK")
|
||||
load("@npm//@angular/build-tooling/bazel/http-server:index.bzl", "http_server")
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin")
|
||||
load("@npm//@angular-devkit/architect-cli:index.bzl", "architect", "architect_test")
|
||||
load("@bazel_skylib//lib:collections.bzl", "collections")
|
||||
load("//adev/tools/local_deps:index.bzl", "ensure_local_package_deps", "link_local_packages")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
])
|
||||
|
||||
# All source and configuration files required to build the docs app
|
||||
APPLICATION_FILES = [
|
||||
"angular.json",
|
||||
@@ -22,30 +16,21 @@ APPLICATION_FILES = [
|
||||
["src/**/*"],
|
||||
exclude = [
|
||||
"src/**/*.spec.ts",
|
||||
# Temporarily exclude generated sources produced by the non-bazel
|
||||
# build until the whole project is built by bazel and this directory
|
||||
# isn't needed.
|
||||
"src/generated/**/*",
|
||||
],
|
||||
)
|
||||
|
||||
TEST_FILES = APPLICATION_FILES + [
|
||||
"karma.conf.js",
|
||||
"test-main.ts",
|
||||
"tsconfig.spec.json",
|
||||
] + glob(
|
||||
["src/**/*.spec.ts"],
|
||||
["**/*.spec.ts"],
|
||||
)
|
||||
|
||||
APPLICATION_ASSETS = [
|
||||
"//adev/src/assets/images",
|
||||
"//adev/src/assets/textures",
|
||||
"//adev/src/assets/previews",
|
||||
"//adev/src/assets:tutorials",
|
||||
"//adev/src/assets/icons",
|
||||
"//adev/src/assets:api",
|
||||
"//adev/src/assets:content",
|
||||
]
|
||||
|
||||
APPLICATION_DEPS = [
|
||||
"@npm//@angular/docs",
|
||||
"@npm//@angular/build",
|
||||
APPLICATION_DEPS = link_packages([
|
||||
"@npm//@angular-devkit/build-angular",
|
||||
"@npm//@angular/animations",
|
||||
"@npm//@angular/cdk",
|
||||
@@ -53,18 +38,25 @@ APPLICATION_DEPS = [
|
||||
"@npm//@angular/compiler",
|
||||
"@npm//@angular/compiler-cli",
|
||||
"@npm//@angular/core",
|
||||
"@npm//@angular/docs",
|
||||
"@npm//@angular/forms",
|
||||
"@npm//@angular/material",
|
||||
"@npm//@angular/platform-browser",
|
||||
"@npm//@angular/platform-server",
|
||||
"@npm//@angular/router",
|
||||
"@npm//@angular/ssr",
|
||||
"@npm//gsap",
|
||||
"@npm//marked",
|
||||
"@npm//ngx-progressbar",
|
||||
"@npm//ogl",
|
||||
"@npm//rxjs",
|
||||
"@npm//typescript",
|
||||
"//adev/src/assets/images",
|
||||
"//adev/src/assets/textures",
|
||||
"//adev/src/assets/previews",
|
||||
"//adev/src/assets:tutorials",
|
||||
"//adev/src/assets/icons",
|
||||
"//adev/src/assets:api",
|
||||
"//adev/src/assets:content",
|
||||
"@npm//@typescript/vfs",
|
||||
"@npm//@codemirror/state",
|
||||
"@npm//@codemirror/view",
|
||||
@@ -81,33 +73,25 @@ APPLICATION_DEPS = [
|
||||
"@npm//@lezer/highlight",
|
||||
"@npm//@lezer/javascript",
|
||||
"@npm//@lezer/common",
|
||||
"@npm//@stackblitz/sdk",
|
||||
"@npm//open-in-idx",
|
||||
"@npm//@webcontainer/api",
|
||||
"@npm//@xterm/xterm",
|
||||
"@npm//@xterm/addon-fit",
|
||||
"@npm//algoliasearch",
|
||||
"@npm//xterm-addon-fit",
|
||||
"@npm//angular-split",
|
||||
"@npm//zone.js",
|
||||
]
|
||||
])
|
||||
|
||||
TEST_DEPS = APPLICATION_DEPS + [
|
||||
TEST_DEPS = APPLICATION_DEPS + link_packages([
|
||||
"@npm//@angular/platform-browser-dynamic",
|
||||
"@npm//@angular/build-tooling/bazel/browsers/chromium",
|
||||
"@npm//@types/jasmine",
|
||||
"@npm//@types/node",
|
||||
"@npm//assert",
|
||||
"@npm//jasmine",
|
||||
"@npm//jasmine-core",
|
||||
"@npm//karma-chrome-launcher",
|
||||
"@npm//karma-coverage",
|
||||
"@npm//karma-jasmine",
|
||||
"@npm//karma-jasmine-html-reporter",
|
||||
]
|
||||
|
||||
# Create `npm_link` targets for all dependencies that correspond to a
|
||||
# first-party Angular package that can be built from `HEAD`.
|
||||
link_local_packages(
|
||||
all_deps = collections.uniq(APPLICATION_DEPS + TEST_DEPS),
|
||||
)
|
||||
"//aio/tools:windows-chromium-path",
|
||||
])
|
||||
|
||||
copy_to_bin(
|
||||
name = "application_files_bin",
|
||||
@@ -115,52 +99,39 @@ copy_to_bin(
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "full_build_adev",
|
||||
name = "fast_build_mode",
|
||||
build_setting_default = False,
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "prod_build",
|
||||
name = "fast",
|
||||
flag_values = {
|
||||
":full_build_adev": "true",
|
||||
":fast_build_mode": "true",
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "dev_build",
|
||||
name = "full",
|
||||
flag_values = {
|
||||
":full_build_adev": "false",
|
||||
":fast_build_mode": "false",
|
||||
},
|
||||
)
|
||||
|
||||
config_based_architect_env = select({
|
||||
":dev_build": {
|
||||
"NG_BUILD_PARTIAL_SSR": "1",
|
||||
},
|
||||
":prod_build": {
|
||||
"NG_BUILD_OPTIMIZE_CHUNKS": "1",
|
||||
},
|
||||
})
|
||||
|
||||
config_based_architect_flags = select({
|
||||
":dev_build": [
|
||||
"angular-dev:build:development",
|
||||
],
|
||||
":prod_build": [
|
||||
"angular-dev:build:production",
|
||||
],
|
||||
":fast": ["--no-prerender"],
|
||||
":full": ["--prerender"],
|
||||
})
|
||||
|
||||
architect(
|
||||
name = "build",
|
||||
args = config_based_architect_flags + [
|
||||
args = [
|
||||
"angular-dev:build",
|
||||
"--output-path=build",
|
||||
],
|
||||
] + config_based_architect_flags,
|
||||
chdir = "$(RULEDIR)",
|
||||
data = ensure_local_package_deps(APPLICATION_DEPS) + APPLICATION_ASSETS + [
|
||||
data = APPLICATION_DEPS + [
|
||||
":application_files_bin",
|
||||
],
|
||||
env = config_based_architect_env,
|
||||
# Network is required to inline fonts.
|
||||
exec_properties = ENABLE_NETWORK,
|
||||
output_dir = True,
|
||||
@@ -169,14 +140,21 @@ architect(
|
||||
],
|
||||
)
|
||||
|
||||
http_server(
|
||||
architect(
|
||||
name = "serve",
|
||||
additional_root_paths = [
|
||||
"angular/adev/build/browser",
|
||||
args = [
|
||||
"angular-dev:serve",
|
||||
"--poll=1000",
|
||||
"--live-reload",
|
||||
"--watch",
|
||||
],
|
||||
chdir = package_name(),
|
||||
data = APPLICATION_DEPS + [
|
||||
":application_files_bin",
|
||||
],
|
||||
tags = [
|
||||
"no-remote-exec",
|
||||
],
|
||||
enable_dev_ui = True,
|
||||
relax_cors = True,
|
||||
deps = [":build"],
|
||||
)
|
||||
|
||||
architect_test(
|
||||
@@ -186,10 +164,7 @@ architect_test(
|
||||
"--no-watch",
|
||||
],
|
||||
chdir = package_name(),
|
||||
data = ensure_local_package_deps(TEST_DEPS) + TEST_FILES + APPLICATION_ASSETS + [
|
||||
"//adev/tools:windows-chromium-path",
|
||||
"@npm//@angular/build-tooling/bazel/browsers/chromium",
|
||||
],
|
||||
data = TEST_DEPS + TEST_FILES,
|
||||
env = {
|
||||
"CHROME_BIN": "../$(CHROMIUM)",
|
||||
},
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# [Angular.dev](https://www.angular.dev)
|
||||
|
||||
This site is built with Angular.
|
||||
|
||||
The content is written primarily in Markdown format located in `src/content`. For simple edits, you can directly edit the file on GitHub and generate a Pull Request.
|
||||
|
||||
## Local Development
|
||||
|
||||
For local development, [yarn](https://yarnpkg.com/) is the preferred package manager. You can setup a local environment with the following commands
|
||||
:
|
||||
|
||||
```bash
|
||||
# Clone Angular repo
|
||||
git clone https://github.com/angular/angular.git
|
||||
|
||||
# Navigate to project directory
|
||||
cd angular
|
||||
|
||||
# Install dependencies
|
||||
yarn
|
||||
|
||||
# Build and run local dev server
|
||||
# Note: Initial build will take some time
|
||||
yarn docs
|
||||
```
|
||||
|
||||
If you are having issues with the docs building, see the [FAQs](#faqs) section.
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to report a bug, contribute some code, or improve the documentation? Excellent!
|
||||
|
||||
Read through our [contributing guidelines](/CONTRIBUTING.md) to learn about our submission process, coding rules, and more.
|
||||
|
||||
And if you're new, check out one of our issues labeled as <kbd>[help wanted](https://github.com/angular/angular/labels/help%20wanted)</kbd> or <kbd>[good first issue](https://github.com/angular/angular/labels/good%20first%20issue)</kbd>.
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct](/CODE_OF_CONDUCT.md).
|
||||
|
||||
## FAQs
|
||||
|
||||
### The build is failing and I'm seeing `bazel:bazel failed: missing input file` messages.
|
||||
|
||||
This is most likely due to a bazel dependency / caching issue. To resolve this, run the following command:
|
||||
|
||||
```
|
||||
# Try this first
|
||||
yarn bazel clean
|
||||
|
||||
# If that doesn't work, try it with the expunge flag
|
||||
yarn bazel clean --expunge
|
||||
```
|
||||
+13
-18
@@ -17,24 +17,24 @@
|
||||
"prefix": "adev",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:application",
|
||||
"builder": "@angular-devkit/build-angular:application",
|
||||
"options": {
|
||||
"externalDependencies": ["path"],
|
||||
"define": {
|
||||
// We need this until xterm 5.6.0 is released
|
||||
// see https://github.com/xtermjs/xterm.js/pull/4940
|
||||
"self": "this"
|
||||
},
|
||||
"outputMode": "static",
|
||||
"externalDependencies": [
|
||||
"path"
|
||||
],
|
||||
"outputPath": "dist/angular-dev",
|
||||
"index": "src/index.html",
|
||||
"browser": "src/main.ts",
|
||||
"server": "src/main.server.ts",
|
||||
"polyfills": [],
|
||||
"polyfills": ["src/polyfills.ts", "zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["src/favicon.ico", "src/robots.txt", "src/assets"],
|
||||
"styles": ["@angular/docs/styles/global-styles.scss", "./src/local-styles.scss"],
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/robots.txt",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": ["@angular/docs/styles/global-styles.scss"],
|
||||
"scripts": [],
|
||||
"webWorkerTsConfig": "tsconfig.worker.json",
|
||||
"optimization": {
|
||||
@@ -84,10 +84,10 @@
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"include": ["src/app"],
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"main": "test-main.ts",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["@angular/docs/styles/global-styles.scss"],
|
||||
@@ -99,11 +99,6 @@
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": "dca119a9-da31-47f7-a6cb-b60541037021",
|
||||
"cache": {
|
||||
// Disable build caching as the cache folder will just be dropped
|
||||
// when run under Bazel sandboxed execution.
|
||||
"enabled": false
|
||||
}
|
||||
"analytics": "dca119a9-da31-47f7-a6cb-b60541037021"
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -3,10 +3,9 @@
|
||||
"target": "angular-docs",
|
||||
"public": "./build/browser",
|
||||
"ignore": ["**/.*"],
|
||||
"trailingSlash": false,
|
||||
"headers": [
|
||||
{
|
||||
"source": "assets/images/tutorials/common/*.jpg",
|
||||
"source": "assets/tutorials/common/*.jpg",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cross-Origin-Resource-Policy",
|
||||
@@ -19,7 +18,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": "/**/*-[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z].*",
|
||||
"source": "*.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].+(css|js)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
|
||||
+1
-9
@@ -1,15 +1,7 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
const {getAdjustedChromeBinPathForWindows} = require('../adev/tools/windows-chromium-path');
|
||||
const {getAdjustedChromeBinPathForWindows} = require('../aio/tools/windows-chromium-path');
|
||||
|
||||
process.env.CHROME_BIN = getAdjustedChromeBinPathForWindows();
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Generating data for `angular.dev/cli`
|
||||
|
||||
This script updates the Angular CLI help JSON files stored in `adev/src/content/cli/help`. This files are used to generate the [angular.dev CLI](https://angular.dev/cli) pages.
|
||||
@@ -1,163 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
//tslint:disable:no-console
|
||||
import {execSync} from 'node:child_process';
|
||||
import {readFile, writeFile, readdir, mkdtemp, realpath, copyFile, unlink} from 'node:fs/promises';
|
||||
import {tmpdir} from 'node:os';
|
||||
import {get} from 'node:https';
|
||||
import {dirname, resolve as resolvePath, posix, join} from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {existsSync, constants as fsConstants} from 'node:fs';
|
||||
|
||||
const GITHUB_API = 'https://api.github.com/repos/';
|
||||
const CLI_BUILDS_REPO = 'angular/cli-builds';
|
||||
const GITHUB_API_CLI_BUILDS = posix.join(GITHUB_API, CLI_BUILDS_REPO);
|
||||
|
||||
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
||||
const CLI_HELP_CONTENT_PATH = resolvePath(scriptDir, '../../src/content/cli/help');
|
||||
const CLI_SHA_PATH = join(CLI_HELP_CONTENT_PATH, 'build-info.json');
|
||||
|
||||
async function main() {
|
||||
if (!existsSync(CLI_SHA_PATH)) {
|
||||
throw new Error(`${CLI_SHA_PATH} does not exist.`);
|
||||
}
|
||||
|
||||
const branch = process.env.GITHUB_REF;
|
||||
const {sha: currentSha} = JSON.parse(await readFile(CLI_SHA_PATH, 'utf-8'));
|
||||
const latestSha = await getShaFromCliBuilds(branch);
|
||||
|
||||
console.log(`Comparing ${currentSha}...${latestSha}.`);
|
||||
const affectedFiles = await getAffectedFiles(currentSha, latestSha);
|
||||
const changedHelpFiles = affectedFiles.filter((file) => file.startsWith('help/'));
|
||||
|
||||
if (changedHelpFiles.length === 0) {
|
||||
console.log(`No 'help/**' files changed between ${currentSha} and ${latestSha}.`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`The below help files changed between ${currentSha} and ${latestSha}:\n` +
|
||||
changedHelpFiles.map((f) => '* ' + f).join('\n'),
|
||||
);
|
||||
|
||||
const temporaryDir = await realpath(await mkdtemp(join(tmpdir(), 'cli-src-')));
|
||||
const execOptions = {cwd: temporaryDir, stdio: 'inherit'};
|
||||
execSync('git init', execOptions);
|
||||
execSync('git remote add origin https://github.com/angular/cli-builds.git', execOptions);
|
||||
// fetch a commit
|
||||
execSync(`git fetch origin ${latestSha}`, execOptions);
|
||||
// reset this repository's main branch to the commit of interest
|
||||
execSync('git reset --hard FETCH_HEAD', execOptions);
|
||||
// get sha when files where changed
|
||||
const shaWhenFilesChanged = execSync(`git rev-list -1 ${latestSha} "help/"`, {
|
||||
encoding: 'utf8',
|
||||
cwd: temporaryDir,
|
||||
stdio: ['ignore', 'pipe', 'ignore'],
|
||||
}).trim();
|
||||
|
||||
// Delete existing JSON help files.
|
||||
const helpFilesUnlink = (await readdir(CLI_HELP_CONTENT_PATH))
|
||||
.filter((f) => f.endsWith('.json'))
|
||||
.map((f) => unlink(join(CLI_HELP_CONTENT_PATH, f)));
|
||||
|
||||
await Promise.allSettled(helpFilesUnlink);
|
||||
|
||||
// Copy new help files
|
||||
const tempHelpDir = join(temporaryDir, 'help');
|
||||
const helpFilesCopy = (await readdir(tempHelpDir)).map((f) => {
|
||||
const src = join(tempHelpDir, f);
|
||||
const dest = join(CLI_HELP_CONTENT_PATH, f);
|
||||
|
||||
return copyFile(src, dest, fsConstants.COPYFILE_FICLONE);
|
||||
});
|
||||
|
||||
await Promise.allSettled(helpFilesCopy);
|
||||
|
||||
// Write SHA to file.
|
||||
await writeFile(
|
||||
CLI_SHA_PATH,
|
||||
JSON.stringify(
|
||||
{
|
||||
branchName: branch,
|
||||
sha: shaWhenFilesChanged,
|
||||
},
|
||||
undefined,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
console.log('\nChanges: ');
|
||||
execSync(`git status --porcelain`, {stdio: 'inherit'});
|
||||
|
||||
console.log(`Successfully updated help files in '${CLI_HELP_CONTENT_PATH}'.\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SHA of a branch.
|
||||
*
|
||||
* @param {string} branch
|
||||
* @param {string} headSha
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
async function getShaFromCliBuilds(branch) {
|
||||
const sha = await httpGet(`${GITHUB_API_CLI_BUILDS}/commits/${branch}`, {
|
||||
headers: {Accept: 'application/vnd.github.VERSION.sha'},
|
||||
});
|
||||
|
||||
if (!sha) {
|
||||
throw new Error(`Unable to extract the SHA for '${branch}'.`);
|
||||
}
|
||||
|
||||
return sha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the affected files.
|
||||
*
|
||||
* @param {string} baseSha
|
||||
* @param {string} headSha
|
||||
* @returns Promise<string[]>
|
||||
*/
|
||||
async function getAffectedFiles(baseSha, headSha) {
|
||||
const {files} = JSON.parse(
|
||||
await httpGet(`${GITHUB_API_CLI_BUILDS}/compare/${baseSha}...${headSha}`),
|
||||
);
|
||||
return files.map((f) => f.filename);
|
||||
}
|
||||
|
||||
function httpGet(url, options = {}) {
|
||||
options.headers ??= {};
|
||||
options.headers[
|
||||
'Authorization'
|
||||
] = `token ${process.env.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN}`;
|
||||
// User agent is required
|
||||
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#user-agent-required
|
||||
options.headers['User-Agent'] = `ADEV_Angular_CLI_Sources_Update`;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
get(url, options, (res) => {
|
||||
let data = '';
|
||||
res
|
||||
.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
})
|
||||
.on('end', () => {
|
||||
resolve(data);
|
||||
});
|
||||
}).on('error', (e) => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,49 +0,0 @@
|
||||
load("//tools:defaults.bzl", "ng_module", "ng_package")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "docs",
|
||||
srcs = [
|
||||
"index.ts",
|
||||
],
|
||||
module_name = "@angular/docs",
|
||||
deps = [
|
||||
"//adev/shared-docs/components",
|
||||
"//adev/shared-docs/constants",
|
||||
"//adev/shared-docs/directives",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/pipes",
|
||||
"//adev/shared-docs/providers",
|
||||
"//adev/shared-docs/services",
|
||||
"//adev/shared-docs/testing",
|
||||
"//adev/shared-docs/utils",
|
||||
],
|
||||
)
|
||||
|
||||
ng_package(
|
||||
name = "npm_package",
|
||||
srcs = [
|
||||
"package.json",
|
||||
"//adev/shared-docs/icons",
|
||||
"//adev/shared-docs/pipeline:BUILD.bazel",
|
||||
"//adev/shared-docs/pipeline:_guides.bzl",
|
||||
"//adev/shared-docs/pipeline:_playground.bzl",
|
||||
"//adev/shared-docs/pipeline:_stackblitz.bzl",
|
||||
"//adev/shared-docs/pipeline:_tutorial.bzl",
|
||||
"//adev/shared-docs/pipeline:guides.mjs",
|
||||
"//adev/shared-docs/pipeline:guides-no-mermaid.mjs",
|
||||
"//adev/shared-docs/pipeline:playground.mjs",
|
||||
"//adev/shared-docs/pipeline:stackblitz.mjs",
|
||||
"//adev/shared-docs/pipeline:tutorial.mjs",
|
||||
"//adev/shared-docs/pipeline/examples/template:files",
|
||||
"//adev/shared-docs/pipeline/tutorials/common:files",
|
||||
"//adev/shared-docs/styles",
|
||||
],
|
||||
visibility = [
|
||||
"//adev:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":docs",
|
||||
],
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ts_library(
|
||||
name = "components",
|
||||
srcs = [
|
||||
"index.ts",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/components/algolia-icon",
|
||||
"//adev/shared-docs/components/breadcrumb",
|
||||
"//adev/shared-docs/components/cookie-popup",
|
||||
"//adev/shared-docs/components/copy-source-code-button",
|
||||
"//adev/shared-docs/components/icon",
|
||||
"//adev/shared-docs/components/navigation-list",
|
||||
"//adev/shared-docs/components/search-dialog",
|
||||
"//adev/shared-docs/components/select",
|
||||
"//adev/shared-docs/components/slide-toggle",
|
||||
"//adev/shared-docs/components/table-of-contents",
|
||||
"//adev/shared-docs/components/text-field",
|
||||
"//adev/shared-docs/components/top-level-banner",
|
||||
"//adev/shared-docs/components/viewers",
|
||||
],
|
||||
)
|
||||
@@ -1,20 +0,0 @@
|
||||
load("//tools:defaults.bzl", "ng_module")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "algolia-icon",
|
||||
srcs = [
|
||||
"algolia-icon.component.ts",
|
||||
],
|
||||
assets = [
|
||||
"algolia-icon.component.html",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
"//adev/shared-docs/components/search-dialog:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//packages/core",
|
||||
],
|
||||
)
|
||||
@@ -1,52 +0,0 @@
|
||||
<!-- Algolia logo -->
|
||||
<svg
|
||||
id="Layer_1"
|
||||
class="docs-algolia-logo"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 2196.2 500"
|
||||
>
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1,
|
||||
.cls-2 {
|
||||
fill: #003dff;
|
||||
}
|
||||
.cls-2 {
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M1070.38,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"
|
||||
/>
|
||||
<rect class="cls-1" x="1845.88" y="104.73" width="62.58" height="277.9" rx="5.9" ry="5.9" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M1851.78,71.38h50.77c3.26,0,5.9-2.64,5.9-5.9V5.9c0-3.62-3.24-6.39-6.82-5.83l-50.77,7.95c-2.87,.45-4.99,2.92-4.99,5.83v51.62c0,3.26,2.64,5.9,5.9,5.9Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M1764.03,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M1631.95,142.72c-11.14-12.25-24.83-21.65-40.78-28.31-15.92-6.53-33.26-9.85-52.07-9.85-18.78,0-36.15,3.17-51.92,9.85-15.59,6.66-29.29,16.05-40.76,28.31-11.47,12.23-20.38,26.87-26.76,44.03-6.38,17.17-9.24,37.37-9.24,58.36,0,20.99,3.19,36.87,9.55,54.21,6.38,17.32,15.14,32.11,26.45,44.36,11.29,12.23,24.83,21.62,40.6,28.46,15.77,6.83,40.12,10.33,52.4,10.48,12.25,0,36.78-3.82,52.7-10.48,15.92-6.68,29.46-16.23,40.78-28.46,11.29-12.25,20.05-27.04,26.25-44.36,6.22-17.34,9.24-33.22,9.24-54.21,0-20.99-3.34-41.19-10.03-58.36-6.38-17.17-15.14-31.8-26.43-44.03Zm-44.43,163.75c-11.47,15.75-27.56,23.7-48.09,23.7-20.55,0-36.63-7.8-48.1-23.7-11.47-15.75-17.21-34.01-17.21-61.2,0-26.89,5.59-49.14,17.06-64.87,11.45-15.75,27.54-23.52,48.07-23.52,20.55,0,36.63,7.78,48.09,23.52,11.47,15.57,17.36,37.98,17.36,64.87,0,27.19-5.72,45.3-17.19,61.2Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M894.42,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M2133.97,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M1314.05,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-11.79,18.34-19.6,39.64-22.11,62.59-.58,5.3-.88,10.68-.88,16.14s.31,11.15,.93,16.59c4.28,38.09,23.14,71.61,50.66,94.52,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47h0c17.99,0,34.61-5.93,48.16-15.97,16.29-11.58,28.88-28.54,34.48-47.75v50.26h-.11v11.08c0,21.84-5.71,38.27-17.34,49.36-11.61,11.08-31.04,16.63-58.25,16.63-11.12,0-28.79-.59-46.6-2.41-2.83-.29-5.46,1.5-6.27,4.22l-12.78,43.11c-1.02,3.46,1.27,7.02,4.83,7.53,21.52,3.08,42.52,4.68,54.65,4.68,48.91,0,85.16-10.75,108.89-32.21,21.48-19.41,33.15-48.89,35.2-88.52V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,64.1s.65,139.13,0,143.36c-12.08,9.77-27.11,13.59-43.49,14.7-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-1.32,0-2.63-.03-3.94-.1-40.41-2.11-74.52-37.26-74.52-79.38,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M249.83,0C113.3,0,2,110.09,.03,246.16c-2,138.19,110.12,252.7,248.33,253.5,42.68,.25,83.79-10.19,120.3-30.03,3.56-1.93,4.11-6.83,1.08-9.51l-23.38-20.72c-4.75-4.21-11.51-5.4-17.36-2.92-25.48,10.84-53.17,16.38-81.71,16.03-111.68-1.37-201.91-94.29-200.13-205.96,1.76-110.26,92-199.41,202.67-199.41h202.69V407.41l-115-102.18c-3.72-3.31-9.42-2.66-12.42,1.31-18.46,24.44-48.53,39.64-81.93,37.34-46.33-3.2-83.87-40.5-87.34-86.81-4.15-55.24,39.63-101.52,94-101.52,49.18,0,89.68,37.85,93.91,85.95,.38,4.28,2.31,8.27,5.52,11.12l29.95,26.55c3.4,3.01,8.79,1.17,9.63-3.3,2.16-11.55,2.92-23.58,2.07-35.92-4.82-70.34-61.8-126.93-132.17-131.26-80.68-4.97-148.13,58.14-150.27,137.25-2.09,77.1,61.08,143.56,138.19,145.26,32.19,.71,62.03-9.41,86.14-26.95l150.26,133.2c6.44,5.71,16.61,1.14,16.61-7.47V9.48C499.66,4.25,495.42,0,490.18,0H249.83Z"
|
||||
/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.0 KiB |
@@ -1,16 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-algolia-icon',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './algolia-icon.component.html',
|
||||
})
|
||||
export class AlgoliaIcon {}
|
||||
@@ -1,54 +0,0 @@
|
||||
load("//tools:defaults.bzl", "karma_web_test_suite", "ng_module", "ts_library")
|
||||
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "breadcrumb",
|
||||
srcs = [
|
||||
"breadcrumb.component.ts",
|
||||
],
|
||||
assets = [
|
||||
":breadcrumb.component.css",
|
||||
"breadcrumb.component.html",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
"//adev/shared-docs/components/viewers:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/services",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"//packages/router",
|
||||
],
|
||||
)
|
||||
|
||||
sass_binary(
|
||||
name = "style",
|
||||
src = "breadcrumb.component.scss",
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
":breadcrumb",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/services",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/platform-browser",
|
||||
"//packages/router",
|
||||
"//packages/router/testing",
|
||||
],
|
||||
)
|
||||
|
||||
karma_web_test_suite(
|
||||
name = "test",
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
@@ -1,13 +0,0 @@
|
||||
@for (breadcrumb of breadcrumbItems(); track $index) {
|
||||
<div class="docs-breadcrumb">
|
||||
@if (breadcrumb.path) {
|
||||
@if (breadcrumb.isExternal) {
|
||||
<a [href]="breadcrumb.path">{{ breadcrumb.label }}</a>
|
||||
} @else {
|
||||
<a [routerLink]="'/' + breadcrumb.path">{{ breadcrumb.label }}</a>
|
||||
}
|
||||
} @else {
|
||||
<span>{{ breadcrumb.label }}</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-block-end: 1.5rem;
|
||||
}
|
||||
|
||||
.docs-breadcrumb {
|
||||
span {
|
||||
color: var(--quaternary-contrast);
|
||||
font-size: 0.875rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
span {
|
||||
&::after {
|
||||
content: 'chevron_right';
|
||||
font-family: var(--icons);
|
||||
margin-inline: 0.5rem;
|
||||
color: var(--quinary-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {Breadcrumb} from './breadcrumb.component';
|
||||
import {NavigationState} from '../../services';
|
||||
import {NavigationItem} from '../../interfaces';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {provideExperimentalZonelessChangeDetection} from '@angular/core';
|
||||
|
||||
describe('Breadcrumb', () => {
|
||||
let fixture: ComponentFixture<Breadcrumb>;
|
||||
let navigationStateSpy: jasmine.SpyObj<NavigationState>;
|
||||
|
||||
beforeEach(() => {
|
||||
navigationStateSpy = jasmine.createSpyObj('NavigationState', ['activeNavigationItem']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [Breadcrumb, RouterTestingModule],
|
||||
providers: [
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
{
|
||||
provide: NavigationState,
|
||||
useValue: navigationStateSpy,
|
||||
},
|
||||
],
|
||||
});
|
||||
fixture = TestBed.createComponent(Breadcrumb);
|
||||
});
|
||||
|
||||
it('should display proper breadcrumb structure based on navigation state', () => {
|
||||
navigationStateSpy.activeNavigationItem.and.returnValue(item);
|
||||
|
||||
fixture.detectChanges();
|
||||
const breadcrumbs = fixture.debugElement.queryAll(By.css('.docs-breadcrumb span'));
|
||||
|
||||
expect(breadcrumbs.length).toBe(2);
|
||||
expect(breadcrumbs[0].nativeElement.innerText).toEqual('Grandparent');
|
||||
expect(breadcrumbs[1].nativeElement.innerText).toEqual('Parent');
|
||||
});
|
||||
|
||||
it('should display breadcrumb links when navigation item has got path', () => {
|
||||
navigationStateSpy.activeNavigationItem.and.returnValue(exampleItemWithPath);
|
||||
|
||||
fixture.detectChanges();
|
||||
const breadcrumbs = fixture.debugElement.queryAll(By.css('.docs-breadcrumb a'));
|
||||
|
||||
expect(breadcrumbs.length).toBe(1);
|
||||
expect(breadcrumbs[0].nativeElement.innerText).toEqual('Parent');
|
||||
expect(breadcrumbs[0].nativeElement.href).toEqual(`${window.origin}/example`);
|
||||
});
|
||||
});
|
||||
|
||||
const grandparent: NavigationItem = {
|
||||
label: 'Grandparent',
|
||||
};
|
||||
|
||||
const parent: NavigationItem = {
|
||||
label: 'Parent',
|
||||
parent: grandparent,
|
||||
};
|
||||
|
||||
const item: NavigationItem = {
|
||||
label: 'Active Item',
|
||||
parent: parent,
|
||||
};
|
||||
|
||||
const parentWithPath: NavigationItem = {
|
||||
label: 'Parent',
|
||||
path: '/example',
|
||||
};
|
||||
|
||||
const exampleItemWithPath: NavigationItem = {
|
||||
label: 'Active Item',
|
||||
parent: parentWithPath,
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, inject, computed} from '@angular/core';
|
||||
import {NavigationState} from '../../services/index';
|
||||
import {NavigationItem} from '../../interfaces/index';
|
||||
import {RouterLink} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-breadcrumb',
|
||||
imports: [RouterLink],
|
||||
templateUrl: './breadcrumb.component.html',
|
||||
styleUrls: ['./breadcrumb.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class Breadcrumb {
|
||||
private readonly navigationState = inject(NavigationState);
|
||||
|
||||
breadcrumbItems = computed(() => {
|
||||
const breadcrumbs: NavigationItem[] = [];
|
||||
let activeItem = this.navigationState.activeNavigationItem()?.parent;
|
||||
|
||||
while (activeItem != null) {
|
||||
breadcrumbs.push(activeItem);
|
||||
activeItem = activeItem.parent;
|
||||
}
|
||||
|
||||
return breadcrumbs.reverse();
|
||||
});
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
load("//tools:defaults.bzl", "karma_web_test_suite", "ng_module", "ts_library")
|
||||
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "cookie-popup",
|
||||
srcs = [
|
||||
"cookie-popup.component.ts",
|
||||
],
|
||||
assets = [
|
||||
":cookie-popup.component.css",
|
||||
"cookie-popup.component.html",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/providers",
|
||||
"//adev/shared-docs/utils",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
],
|
||||
)
|
||||
|
||||
sass_binary(
|
||||
name = "style",
|
||||
src = "cookie-popup.component.scss",
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
":cookie-popup",
|
||||
"//adev/shared-docs/providers",
|
||||
"//adev/shared-docs/testing",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
],
|
||||
)
|
||||
|
||||
karma_web_test_suite(
|
||||
name = "test",
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
@@ -1,22 +0,0 @@
|
||||
@if (!hasAccepted()) {
|
||||
<div class="docs-cookies-popup docs-invert-mode">
|
||||
<p>This site uses cookies from Google to deliver its services and to analyze traffic.</p>
|
||||
|
||||
<div>
|
||||
<a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">
|
||||
<button class="docs-primary-btn" [attr.text]="'Learn more'" aria-label="Learn More">
|
||||
Learn more
|
||||
</button>
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
(click)="accept()"
|
||||
class="docs-primary-btn"
|
||||
[attr.text]="'Ok, Got it'"
|
||||
aria-label="Ok, Got it"
|
||||
>
|
||||
Ok, Got it
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
:host {
|
||||
position: fixed;
|
||||
bottom: 0.5rem;
|
||||
right: 0.5rem;
|
||||
z-index: var(--z-index-cookie-consent);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
animation: 1s linear forwards 0.5s fadeIn;
|
||||
}
|
||||
|
||||
.docs-cookies-popup {
|
||||
padding: 1rem;
|
||||
background-color: var(--page-background);
|
||||
border: 1px solid var(--senary-contrast);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
max-width: 265px;
|
||||
transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
|
||||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-block: 0;
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
100% {
|
||||
opacity: 100%;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {CookiePopup, STORAGE_KEY} from './cookie-popup.component';
|
||||
import {LOCAL_STORAGE} from '../../providers/index';
|
||||
import {MockLocalStorage} from '../../testing/index';
|
||||
import {provideExperimentalZonelessChangeDetection} from '@angular/core';
|
||||
|
||||
describe('CookiePopup', () => {
|
||||
let fixture: ComponentFixture<CookiePopup>;
|
||||
let mockLocalStorage = new MockLocalStorage();
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CookiePopup],
|
||||
providers: [
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
{
|
||||
provide: LOCAL_STORAGE,
|
||||
useValue: mockLocalStorage,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should make the popup visible by default', () => {
|
||||
initComponent(false);
|
||||
|
||||
expect(getCookiesPopup()).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should hide the cookies popup if the user has already accepted cookies', () => {
|
||||
initComponent(true);
|
||||
|
||||
expect(getCookiesPopup()).toBeNull();
|
||||
});
|
||||
|
||||
it('should hide the cookies popup', () => {
|
||||
initComponent(false);
|
||||
|
||||
accept();
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getCookiesPopup()).toBeNull();
|
||||
});
|
||||
|
||||
it('should store the user confirmation', () => {
|
||||
initComponent(false);
|
||||
|
||||
expect(mockLocalStorage.getItem(STORAGE_KEY)).toBeNull();
|
||||
|
||||
accept();
|
||||
|
||||
expect(mockLocalStorage.getItem(STORAGE_KEY)).toBe('true');
|
||||
});
|
||||
|
||||
// Helpers
|
||||
function getCookiesPopup() {
|
||||
return (fixture.nativeElement as HTMLElement).querySelector('.docs-cookies-popup');
|
||||
}
|
||||
|
||||
function accept() {
|
||||
(fixture.nativeElement as HTMLElement)
|
||||
.querySelector<HTMLButtonElement>('button[text="Ok, Got it"]')
|
||||
?.click();
|
||||
}
|
||||
|
||||
function initComponent(cookiesAccepted: boolean) {
|
||||
mockLocalStorage.setItem(STORAGE_KEY, cookiesAccepted ? 'true' : null);
|
||||
fixture = TestBed.createComponent(CookiePopup);
|
||||
|
||||
fixture.detectChanges();
|
||||
}
|
||||
});
|
||||
@@ -1,53 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core';
|
||||
import {LOCAL_STORAGE} from '../../providers/index';
|
||||
import {setCookieConsent} from '../../utils';
|
||||
|
||||
/**
|
||||
* Decelare gtag as part of the window in this file as gtag is expected to already be loaded.
|
||||
*/
|
||||
declare const window: Window & typeof globalThis & {gtag?: Function};
|
||||
|
||||
export const STORAGE_KEY = 'docs-accepts-cookies';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-cookie-popup',
|
||||
templateUrl: './cookie-popup.component.html',
|
||||
styleUrls: ['./cookie-popup.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CookiePopup {
|
||||
private readonly localStorage = inject(LOCAL_STORAGE);
|
||||
|
||||
/** Whether the user has accepted the cookie disclaimer. */
|
||||
hasAccepted = signal<boolean>(false);
|
||||
|
||||
constructor() {
|
||||
// Needs to be in a try/catch, because some browsers will
|
||||
// throw when using `localStorage` in private mode.
|
||||
try {
|
||||
this.hasAccepted.set(this.localStorage?.getItem(STORAGE_KEY) === 'true');
|
||||
} catch {
|
||||
this.hasAccepted.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
/** Accepts the cookie disclaimer. */
|
||||
protected accept(): void {
|
||||
try {
|
||||
this.localStorage?.setItem(STORAGE_KEY, 'true');
|
||||
} catch {}
|
||||
|
||||
this.hasAccepted.set(true);
|
||||
|
||||
// Enable Google Analytics consent properties
|
||||
setCookieConsent('granted');
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
load("//tools:defaults.bzl", "karma_web_test_suite", "ng_module", "ts_library")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "copy-source-code-button",
|
||||
srcs = [
|
||||
"copy-source-code-button.component.ts",
|
||||
],
|
||||
assets = [
|
||||
"copy-source-code-button.component.html",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
"//adev/shared-docs/components/viewers:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/components/icon",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"@npm//@angular/cdk",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
":copy-source-code-button",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/platform-browser",
|
||||
"@npm//@angular/cdk",
|
||||
],
|
||||
)
|
||||
|
||||
karma_web_test_suite(
|
||||
name = "test",
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
<i>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="docs-copy"
|
||||
>
|
||||
<path
|
||||
d="M5 22C4.45 22 3.97917 21.8042 3.5875 21.4125C3.19583 21.0208 3 20.55 3 20V6H5V20H16V22H5ZM9 18C8.45 18 7.97917 17.8042 7.5875 17.4125C7.19583 17.0208 7 16.55 7 16V4C7 3.45 7.19583 2.97917 7.5875 2.5875C7.97917 2.19583 8.45 2 9 2H18C18.55 2 19.0208 2.19583 19.4125 2.5875C19.8042 2.97917 20 3.45 20 4V16C20 16.55 19.8042 17.0208 19.4125 17.4125C19.0208 17.8042 18.55 18 18 18H9ZM9 16H18V4H9V16Z"
|
||||
fill="#A39FA9"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
|
||||
<docs-icon class="docs-check">check</docs-icon>
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
|
||||
|
||||
import {
|
||||
CONFIRMATION_DISPLAY_TIME_MS,
|
||||
CopySourceCodeButton,
|
||||
} from './copy-source-code-button.component';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
provideExperimentalZonelessChangeDetection,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
|
||||
const SUCCESSFULLY_COPY_CLASS_NAME = 'docs-copy-source-code-button-success';
|
||||
const FAILED_COPY_CLASS_NAME = 'docs-copy-source-code-button-failed';
|
||||
|
||||
describe('CopySourceCodeButton', () => {
|
||||
let component: CodeSnippetWrapper;
|
||||
let fixture: ComponentFixture<CodeSnippetWrapper>;
|
||||
let copySpy: jasmine.Spy<(text: string) => boolean>;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CodeSnippetWrapper],
|
||||
providers: [provideExperimentalZonelessChangeDetection()],
|
||||
});
|
||||
fixture = TestBed.createComponent(CodeSnippetWrapper);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
const clipboardService = TestBed.inject(Clipboard);
|
||||
copySpy = spyOn(clipboardService, 'copy');
|
||||
});
|
||||
|
||||
it('should call clipboard service when clicked on copy source code', async () => {
|
||||
const expectedCodeToBeCopied = 'npm install -g @angular/cli';
|
||||
component.code.set(expectedCodeToBeCopied);
|
||||
|
||||
await fixture.whenStable();
|
||||
|
||||
const button = fixture.debugElement.query(By.directive(CopySourceCodeButton)).nativeElement;
|
||||
button.click();
|
||||
|
||||
expect(copySpy.calls.argsFor(0)[0].trim()).toBe(expectedCodeToBeCopied);
|
||||
});
|
||||
|
||||
it('should not copy lines marked as deleted when code snippet contains diff', async () => {
|
||||
const codeInHtmlFormat = `
|
||||
<code>
|
||||
<div class="line remove"><span class="hljs-tag"><<span class="hljs-name">div</span> *<span class="hljs-attr">ngFor</span>=<span class="hljs-string">"let product of products"</span>></span></div>
|
||||
<div class="line add"><span class="hljs-tag"><<span class="hljs-name">div</span> *<span class="hljs-attr">ngFor</span>=<span class="hljs-string">"let product of products()"</span>></span></div>
|
||||
</code>
|
||||
`;
|
||||
const expectedCodeToBeCopied = `<div *ngFor="let product of products()">`;
|
||||
component.code.set(codeInHtmlFormat);
|
||||
|
||||
await fixture.whenStable();
|
||||
|
||||
const button = fixture.debugElement.query(By.directive(CopySourceCodeButton)).nativeElement;
|
||||
button.click();
|
||||
|
||||
expect(copySpy.calls.argsFor(0)[0].trim()).toBe(expectedCodeToBeCopied);
|
||||
});
|
||||
|
||||
it(`should set ${SUCCESSFULLY_COPY_CLASS_NAME} for ${CONFIRMATION_DISPLAY_TIME_MS} ms when copy was executed properly`, fakeAsync(() => {
|
||||
component.code.set('example');
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(By.directive(CopySourceCodeButton)).nativeElement;
|
||||
button.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(button).toHaveClass(SUCCESSFULLY_COPY_CLASS_NAME);
|
||||
|
||||
tick(CONFIRMATION_DISPLAY_TIME_MS);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(button).not.toHaveClass(SUCCESSFULLY_COPY_CLASS_NAME);
|
||||
}));
|
||||
|
||||
it(`should set ${FAILED_COPY_CLASS_NAME} for ${CONFIRMATION_DISPLAY_TIME_MS} ms when copy failed`, fakeAsync(() => {
|
||||
component.code.set('example');
|
||||
copySpy.and.throwError('Fake copy error');
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(By.directive(CopySourceCodeButton)).nativeElement;
|
||||
button.click();
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(button).toHaveClass(FAILED_COPY_CLASS_NAME);
|
||||
|
||||
tick(CONFIRMATION_DISPLAY_TIME_MS);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(button).not.toHaveClass(FAILED_COPY_CLASS_NAME);
|
||||
}));
|
||||
});
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<pre>
|
||||
<code [innerHtml]="code()"></code>
|
||||
</pre>
|
||||
<button docs-copy-source-code></button>
|
||||
`,
|
||||
imports: [CopySourceCodeButton],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
class CodeSnippetWrapper {
|
||||
code = signal('');
|
||||
}
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
WritableSignal,
|
||||
inject,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
import {IconComponent} from '../icon/icon.component';
|
||||
|
||||
export const REMOVED_LINE_CLASS_NAME = '.line.remove';
|
||||
export const CONFIRMATION_DISPLAY_TIME_MS = 2000;
|
||||
|
||||
@Component({
|
||||
selector: 'button[docs-copy-source-code]',
|
||||
imports: [CommonModule, IconComponent],
|
||||
templateUrl: './copy-source-code-button.component.html',
|
||||
host: {
|
||||
'type': 'button',
|
||||
'aria-label': 'Copy example source to clipboard',
|
||||
'title': 'Copy example source',
|
||||
'(click)': 'copySourceCode()',
|
||||
'[class.docs-copy-source-code-button-success]': 'showCopySuccess()',
|
||||
'[class.docs-copy-source-code-button-failed]': 'showCopyFailure()',
|
||||
},
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CopySourceCodeButton {
|
||||
private readonly changeDetector = inject(ChangeDetectorRef);
|
||||
private readonly clipboard = inject(Clipboard);
|
||||
private readonly elementRef = inject(ElementRef);
|
||||
|
||||
protected readonly showCopySuccess = signal(false);
|
||||
protected readonly showCopyFailure = signal(false);
|
||||
|
||||
copySourceCode(): void {
|
||||
try {
|
||||
const codeElement = this.elementRef.nativeElement.parentElement.querySelector(
|
||||
'code',
|
||||
) as HTMLElement;
|
||||
const sourceCode = this.getSourceCode(codeElement);
|
||||
this.clipboard.copy(sourceCode);
|
||||
this.showResult(this.showCopySuccess);
|
||||
} catch {
|
||||
this.showResult(this.showCopyFailure);
|
||||
}
|
||||
}
|
||||
|
||||
private getSourceCode(codeElement: HTMLElement): string {
|
||||
this.showCopySuccess.set(false);
|
||||
this.showCopyFailure.set(false);
|
||||
|
||||
const removedLines: NodeList = codeElement.querySelectorAll(REMOVED_LINE_CLASS_NAME);
|
||||
|
||||
if (removedLines.length) {
|
||||
// Get only those lines which are not marked as removed
|
||||
const formattedText = Array.from(codeElement.querySelectorAll('.line:not(.remove)'))
|
||||
.map((line) => (line as HTMLDivElement).innerText)
|
||||
.join('\n');
|
||||
|
||||
return formattedText.trim();
|
||||
} else {
|
||||
const text: string = codeElement.innerText || '';
|
||||
return text.replace(/\n\n\n/g, ``).trim();
|
||||
}
|
||||
}
|
||||
|
||||
private showResult(messageState: WritableSignal<boolean>) {
|
||||
messageState.set(true);
|
||||
|
||||
setTimeout(() => {
|
||||
messageState.set(false);
|
||||
// It's required for code snippets embedded in the ExampleViewer.
|
||||
this.changeDetector.markForCheck();
|
||||
}, CONFIRMATION_DISPLAY_TIME_MS);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
|
||||
load("//tools:defaults.bzl", "ng_module")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "icon",
|
||||
srcs = [
|
||||
"icon.component.ts",
|
||||
],
|
||||
assets = [
|
||||
":icon.component.css",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
"//adev/shared-docs/components/copy-source-code-button:__pkg__",
|
||||
"//adev/shared-docs/components/navigation-list:__pkg__",
|
||||
"//adev/shared-docs/components/table-of-contents:__pkg__",
|
||||
"//adev/shared-docs/components/text-field:__pkg__",
|
||||
"//adev/shared-docs/components/top-level-banner:__pkg__",
|
||||
"//adev/shared-docs/components/viewers:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
],
|
||||
)
|
||||
|
||||
sass_binary(
|
||||
name = "style",
|
||||
src = "icon.component.scss",
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
.docs-icon_high-contrast {
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {DOCUMENT} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
afterNextRender,
|
||||
computed,
|
||||
inject,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-icon',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: {
|
||||
'class': 'material-symbols-outlined',
|
||||
'[style.font-size.px]': 'fontSize()',
|
||||
'aria-hidden': 'true',
|
||||
'translate': 'no',
|
||||
},
|
||||
template: '<ng-content />',
|
||||
styleUrl: './icon.component.scss',
|
||||
})
|
||||
export class IconComponent {
|
||||
private static isFontLoaded = signal(false);
|
||||
|
||||
protected readonly fontSize = computed(() => (IconComponent.isFontLoaded() ? null : 0));
|
||||
|
||||
/** Share the same promise across different instances of the component */
|
||||
private static whenFontLoad?: Promise<FontFace[]> | undefined;
|
||||
|
||||
constructor() {
|
||||
if (IconComponent.isFontLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const document = inject(DOCUMENT);
|
||||
afterNextRender(async () => {
|
||||
IconComponent.whenFontLoad ??= document.fonts.load('normal 1px "Material Symbols Outlined"');
|
||||
await IconComponent.whenFontLoad;
|
||||
IconComponent.isFontLoaded.set(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
export * from './viewers/docs-viewer/docs-viewer.component';
|
||||
export * from './cookie-popup/cookie-popup.component';
|
||||
export * from './navigation-list/navigation-list.component';
|
||||
export * from './select/select.component';
|
||||
export * from './slide-toggle/slide-toggle.component';
|
||||
export * from './table-of-contents/table-of-contents.component';
|
||||
export * from './text-field/text-field.component';
|
||||
export * from './icon/icon.component';
|
||||
export * from './search-dialog/search-dialog.component';
|
||||
export * from './top-level-banner/top-level-banner.component';
|
||||
@@ -1,58 +0,0 @@
|
||||
load("//tools:defaults.bzl", "karma_web_test_suite", "ng_module", "ts_library")
|
||||
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "navigation-list",
|
||||
srcs = [
|
||||
"navigation-list.component.ts",
|
||||
],
|
||||
assets = [
|
||||
":navigation-list.component.css",
|
||||
"navigation-list.component.html",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/components/icon",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/pipes",
|
||||
"//adev/shared-docs/services",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"//packages/router",
|
||||
],
|
||||
)
|
||||
|
||||
sass_binary(
|
||||
name = "style",
|
||||
src = "navigation-list.component.scss",
|
||||
deps = [
|
||||
"//adev/shared-docs/styles",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
":navigation-list",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/services",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/platform-browser",
|
||||
"//packages/router",
|
||||
"//packages/router/testing",
|
||||
],
|
||||
)
|
||||
|
||||
karma_web_test_suite(
|
||||
name = "test",
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
@@ -1,75 +0,0 @@
|
||||
<ng-template #navigationList let-navigationItems>
|
||||
<ul
|
||||
class="docs-navigation-list docs-faceted-list"
|
||||
[class.docs-navigation-list-dropdown]="isDropdownView()"
|
||||
>
|
||||
@for (item of navigationItems; track $index) {
|
||||
<li class="docs-faceted-list-item">
|
||||
@if (item.path) {
|
||||
@if (item.isExternal) {
|
||||
<a [href]="item.path" target="_blank">
|
||||
<span [class.docs-external-link]="item.isExternal">{{ item.label }}</span>
|
||||
@if (item.children && item.level! > 1 && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
} @else {
|
||||
<a
|
||||
[routerLink]="'/' + item.path"
|
||||
[routerLinkActiveOptions]="{
|
||||
queryParams: 'ignored',
|
||||
fragment: 'ignored',
|
||||
matrixParams: 'exact',
|
||||
paths: 'exact',
|
||||
exact: false
|
||||
}"
|
||||
routerLinkActive="docs-faceted-list-item-active"
|
||||
(click)="emitClickOnLink()"
|
||||
>
|
||||
<span>{{item.label}}</span>
|
||||
@if (item.children && !item.isExpanded) {
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
}
|
||||
</a>
|
||||
}
|
||||
} @else {
|
||||
<!-- Nav Section Header -->
|
||||
@if (item.level !== collapsableLevel() && item.level !== expandableLevel()) {
|
||||
<div class="docs-secondary-nav-header">
|
||||
<span>{{item.label}}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Nav Button Expand/Collapse -->
|
||||
@if (
|
||||
(item.children && item.level === expandableLevel()) || item.level === collapsableLevel()
|
||||
) {
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(item)"
|
||||
[attr.aria-label]="(item.isExpanded ? 'Collapse' : 'Expand') + ' ' + item.label"
|
||||
[attr.aria-expanded]="item.isExpanded"
|
||||
class="docs-secondary-nav-button"
|
||||
[class.docs-faceted-list-item-active]="item | isActiveNavigationItem: activeItem()"
|
||||
[class.docs-expanded-button]="item.children && item.level == collapsableLevel()"
|
||||
[class.docs-not-expanded-button]="item.children && item.level === expandableLevel()"
|
||||
[class.docs-nav-item-has-icon]="
|
||||
item.children && item.level === expandableLevel() && !item.isExpanded
|
||||
"
|
||||
>
|
||||
@if (item.children && item.level === collapsableLevel()) {
|
||||
<docs-icon>arrow_back</docs-icon>
|
||||
}
|
||||
<span>{{ item.label }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
@if (displayItemsToLevel() > item.level && item.children?.length > 0) {
|
||||
<ng-container *ngTemplateOutlet="navigationList; context: {$implicit: item.children}" />
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<ng-container *ngTemplateOutlet="navigationList; context: {$implicit: navigationItems()}" />
|
||||
@@ -1,146 +0,0 @@
|
||||
@use '../../styles/media-queries' as mq;
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
min-width: var(--secondary-nav-width);
|
||||
list-style: none;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
height: 100vh;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding-block: 1.5rem;
|
||||
font-size: 0.875rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--septenary-contrast);
|
||||
@include mq.for-tablet-landscape-down {
|
||||
background-color: var(--quinary-contrast);
|
||||
}
|
||||
|
||||
border-radius: 10px;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background-color: var(--quinary-contrast);
|
||||
}
|
||||
|
||||
.docs-nav-secondary & {
|
||||
padding-block: 2rem;
|
||||
}
|
||||
|
||||
> .docs-faceted-list {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.docs-nav-item-has-icon {
|
||||
&::after {
|
||||
// FIXME: for some reason this disappears when transformed
|
||||
content: 'chevron_right';
|
||||
font-size: 1.25rem;
|
||||
font-family: var(--icons);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docs-secondary-nav-header {
|
||||
padding-block: 1.25rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.docs-secondary-nav-button {
|
||||
width: 15rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border: none;
|
||||
padding-block: 1.25rem;
|
||||
padding-inline-start: 0;
|
||||
color: var(--primary-contrast);
|
||||
font-size: 0.875rem;
|
||||
font-family: var(--inter-font);
|
||||
line-height: 160%;
|
||||
letter-spacing: -0.00875rem;
|
||||
transition:
|
||||
color 0.3s ease,
|
||||
background 0.3s ease;
|
||||
text-align: left; // forces left alignment of text in button
|
||||
|
||||
&.docs-secondary-nav-button-active {
|
||||
// font gradient
|
||||
background-image: var(--pink-to-purple-vertical-gradient);
|
||||
&::before {
|
||||
opacity: 1;
|
||||
transform: scaleY(1);
|
||||
background: var(--pink-to-purple-vertical-gradient);
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
opacity: 1;
|
||||
transform: scaleY(1.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docs-expanded-button {
|
||||
justify-content: start;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
a,
|
||||
.docs-not-expanded-button {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
line-height: 1.4rem;
|
||||
letter-spacing: -0.00875rem;
|
||||
padding: 0.5rem;
|
||||
padding-inline-start: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
// Add padding-bottom to last item in the list
|
||||
.docs-navigation-list {
|
||||
width: 100%;
|
||||
|
||||
li:last-of-type {
|
||||
ul:last-of-type {
|
||||
li:last-of-type {
|
||||
padding-block-end: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:first-child {
|
||||
margin-inline-start: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-external-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
gap: 0.5rem;
|
||||
&::after {
|
||||
content: 'open_in_new';
|
||||
font-family: var(--icons);
|
||||
font-size: 1.1rem;
|
||||
color: var(--quinary-contrast);
|
||||
transition: color 0.3s ease;
|
||||
margin-inline-end: 0.4rem;
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {NavigationList} from './navigation-list.component';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {NavigationItem} from '../../interfaces';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {provideExperimentalZonelessChangeDetection, signal} from '@angular/core';
|
||||
import {NavigationState} from '../../services';
|
||||
|
||||
const navigationItems: NavigationItem[] = [
|
||||
{
|
||||
label: 'Introduction',
|
||||
path: 'guide',
|
||||
level: 1,
|
||||
},
|
||||
{
|
||||
label: 'Getting Started',
|
||||
level: 1,
|
||||
children: [
|
||||
{label: 'What is Angular?', path: 'guide/what-is-angular', level: 2},
|
||||
{label: 'Setup', path: 'guide/setup', level: 2},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
describe('NavigationList', () => {
|
||||
let component: NavigationList;
|
||||
let fixture: ComponentFixture<NavigationList>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [NavigationList],
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
{provide: NavigationState, useClass: FakeNavigationListState},
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
],
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(NavigationList);
|
||||
fixture.componentRef.setInput('navigationItems', []);
|
||||
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should display provided navigation structure', () => {
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.detectChanges();
|
||||
|
||||
const links = fixture.debugElement.queryAll(By.css('a'));
|
||||
const nonClickableItem = fixture.debugElement.queryAll(By.css('.docs-secondary-nav-header'));
|
||||
|
||||
expect(links.length).toBe(3);
|
||||
expect(nonClickableItem.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should append `docs-navigation-list-dropdown` when isDropdownView is true', () => {
|
||||
fixture.componentRef.setInput('isDropdownView', true);
|
||||
fixture.detectChanges();
|
||||
|
||||
const ulElement = fixture.debugElement.query(By.css('ul.docs-navigation-list-dropdown'));
|
||||
|
||||
expect(ulElement).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not append `docs-navigation-list-dropdown` when isDropdownView is false', () => {
|
||||
fixture.componentRef.setInput('isDropdownView', false);
|
||||
fixture.detectChanges();
|
||||
|
||||
const ulElement = fixture.debugElement.query(By.css('ul.docs-navigation-list-dropdown'));
|
||||
|
||||
expect(ulElement).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should emit linkClicked when user clicked on link', () => {
|
||||
const emitClickOnLinkSpy = spyOn(component, 'emitClickOnLink');
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.detectChanges(true);
|
||||
|
||||
const guideLink = fixture.debugElement.query(By.css('a[href="/guide"]'));
|
||||
guideLink.nativeElement.click();
|
||||
|
||||
expect(emitClickOnLinkSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it(`should not call navigationState.toggleItem() when item's level is equal to 1 and is not neither expandable or collapsable level`, () => {
|
||||
const navigationState = TestBed.inject(NavigationState);
|
||||
const toggleItemSpy = spyOn(navigationState, 'toggleItem');
|
||||
const itemToToggle = navigationItems[1];
|
||||
|
||||
component.toggle(itemToToggle);
|
||||
|
||||
expect(toggleItemSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should call navigationState.toggleItem() when item's level is expandable`, () => {
|
||||
const navigationState = TestBed.inject(NavigationState);
|
||||
const toggleItemSpy = spyOn(navigationState, 'toggleItem');
|
||||
const itemToToggle = navigationItems[1];
|
||||
|
||||
fixture.componentRef.setInput('expandableLevel', 1);
|
||||
component.toggle(itemToToggle);
|
||||
|
||||
expect(toggleItemSpy).toHaveBeenCalledOnceWith(itemToToggle);
|
||||
});
|
||||
|
||||
it(`should call navigationState.toggleItem() when item's level is collapsable`, () => {
|
||||
const navigationState = TestBed.inject(NavigationState);
|
||||
const toggleItemSpy = spyOn(navigationState, 'toggleItem');
|
||||
const itemToToggle = navigationItems[1].children![1];
|
||||
|
||||
fixture.componentRef.setInput('collapsableLevel', 2);
|
||||
component.toggle(itemToToggle);
|
||||
|
||||
expect(toggleItemSpy).toHaveBeenCalledOnceWith(itemToToggle);
|
||||
});
|
||||
|
||||
it('should display only items to provided level (Level 1)', () => {
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.componentRef.setInput('displayItemsToLevel', 1);
|
||||
fixture.detectChanges(true);
|
||||
|
||||
const items = fixture.debugElement.queryAll(By.css('li.docs-faceted-list-item'));
|
||||
|
||||
expect(items.length).toBe(2);
|
||||
expect(items[0].nativeElement.innerText).toBe(navigationItems[0].label);
|
||||
expect(items[1].nativeElement.innerText).toBe(navigationItems[1].label);
|
||||
});
|
||||
|
||||
it('should display all items (Level 2)', () => {
|
||||
fixture.componentRef.setInput('navigationItems', [...navigationItems]);
|
||||
fixture.componentRef.setInput('displayItemsToLevel', 2);
|
||||
fixture.detectChanges(true);
|
||||
|
||||
const items = fixture.debugElement.queryAll(By.css('li.docs-faceted-list-item'));
|
||||
|
||||
expect(items.length).toBe(4);
|
||||
|
||||
expect(items[0].nativeElement.innerText).toBe(navigationItems[0].label);
|
||||
expect(items[1].nativeElement.innerText.startsWith(navigationItems[1].label)).toBeTrue();
|
||||
|
||||
const secondItemChildren = navigationItems[1].children || [];
|
||||
|
||||
expect(items[2].nativeElement.innerText).toBe(secondItemChildren[0].label);
|
||||
expect(items[3].nativeElement.innerText).toBe(secondItemChildren[1].label);
|
||||
});
|
||||
});
|
||||
|
||||
class FakeNavigationListState {
|
||||
isOpened = signal(true);
|
||||
activeNavigationItem = signal(navigationItems.at(1));
|
||||
toggleItem(item: NavigationItem) {}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, Component, inject, input, output} from '@angular/core';
|
||||
import {NavigationItem} from '../../interfaces/index';
|
||||
import {NavigationState} from '../../services/index';
|
||||
import {RouterLink, RouterLinkActive} from '@angular/router';
|
||||
import {IconComponent} from '../icon/icon.component';
|
||||
import {IsActiveNavigationItem} from '../../pipes/is-active-navigation-item.pipe';
|
||||
import {NgTemplateOutlet} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-navigation-list',
|
||||
imports: [RouterLink, RouterLinkActive, IconComponent, IsActiveNavigationItem, NgTemplateOutlet],
|
||||
templateUrl: './navigation-list.component.html',
|
||||
styleUrls: ['./navigation-list.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NavigationList {
|
||||
readonly navigationItems = input.required<NavigationItem[]>();
|
||||
readonly displayItemsToLevel = input<number>(2);
|
||||
readonly collapsableLevel = input<number | undefined>();
|
||||
readonly expandableLevel = input<number>(2);
|
||||
readonly isDropdownView = input<boolean>(false);
|
||||
|
||||
readonly linkClicked = output<void>();
|
||||
|
||||
private readonly navigationState = inject(NavigationState);
|
||||
|
||||
readonly activeItem = this.navigationState.activeNavigationItem;
|
||||
|
||||
toggle(item: NavigationItem): void {
|
||||
if (
|
||||
item.level === 1 &&
|
||||
item.level !== this.expandableLevel() &&
|
||||
item.level !== this.collapsableLevel()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.navigationState.toggleItem(item);
|
||||
}
|
||||
|
||||
emitClickOnLink(): void {
|
||||
this.linkClicked.emit();
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
load("//tools:defaults.bzl", "karma_web_test_suite", "ng_module", "ts_library")
|
||||
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:private"])
|
||||
|
||||
ng_module(
|
||||
name = "search-dialog",
|
||||
srcs = [
|
||||
"search-dialog.component.ts",
|
||||
],
|
||||
assets = [
|
||||
":search-dialog.component.css",
|
||||
"search-dialog.component.html",
|
||||
],
|
||||
visibility = [
|
||||
"//adev/shared-docs/components:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//adev/shared-docs/components/algolia-icon",
|
||||
"//adev/shared-docs/components/text-field",
|
||||
"//adev/shared-docs/directives",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/pipes",
|
||||
"//adev/shared-docs/services",
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"//packages/forms",
|
||||
"//packages/router",
|
||||
],
|
||||
)
|
||||
|
||||
sass_binary(
|
||||
name = "style",
|
||||
src = "search-dialog.component.scss",
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
["*.spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
":search-dialog",
|
||||
"//adev/shared-docs/components/algolia-icon",
|
||||
"//adev/shared-docs/interfaces",
|
||||
"//adev/shared-docs/providers",
|
||||
"//adev/shared-docs/services",
|
||||
"//adev/shared-docs/testing",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/platform-browser",
|
||||
"//packages/router",
|
||||
"//packages/router/testing",
|
||||
],
|
||||
)
|
||||
|
||||
karma_web_test_suite(
|
||||
name = "test",
|
||||
deps = [":test_lib"],
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user