Compare commits
198 Commits
zone.js-0.
...
7.2.4
Author | SHA1 | Date | |
---|---|---|---|
74c202a5cd | |||
483e8d28ec | |||
a6fd118f79 | |||
fe6e76c1e7 | |||
de560019f2 | |||
52ed53d071 | |||
5b72d4d676 | |||
c1aa1bf872 | |||
dad1bc7ca3 | |||
2109c30afe | |||
874919a25b | |||
c64e666755 | |||
1da403d8f3 | |||
60c5ebd46a | |||
b71d1987cd | |||
e6325eb9ef | |||
114519ab6a | |||
a9a095d44a | |||
5f9d574d4d | |||
baeb446392 | |||
0d1bfdc505 | |||
fa130e9445 | |||
194710fc1d | |||
6ae5e2b32a | |||
d85d396c26 | |||
1a25144297 | |||
449da8c18e | |||
0f37ed1060 | |||
5c85b4f1e9 | |||
22bc6ef22a | |||
bf928d1c9e | |||
d11c2f915b | |||
98c99e5073 | |||
2c63108faa | |||
0ff48a1266 | |||
ea2a3f8335 | |||
cbed4851a3 | |||
7c157780a9 | |||
cc1b2a5373 | |||
5076185fc8 | |||
65375f4c21 | |||
068a6070dc | |||
47e9761a01 | |||
bef52d20b5 | |||
fe50710021 | |||
71b66fb862 | |||
8db05b408e | |||
351610ca8d | |||
ef78e33560 | |||
12b8a6e351 | |||
260ac20e92 | |||
aed48e00d2 | |||
a9d46e4952 | |||
2f19ad9b46 | |||
81678e62db | |||
cf82fbceba | |||
1d67cb0ce1 | |||
318bd83a6e | |||
f767c22b31 | |||
8346a6dca2 | |||
6397885e74 | |||
8cee56e8c5 | |||
a1b9995731 | |||
35f7ff047a | |||
4ad691a33d | |||
c5af3f8617 | |||
bc1032866c | |||
63e6d1a896 | |||
cb9fd9b4d7 | |||
d5dca0764c | |||
bcd1a09dec | |||
898c0134e7 | |||
763d2150cc | |||
beacbfcb8e | |||
f72319cf6e | |||
5877b3f702 | |||
cf310ba1fa | |||
c2d2953ee4 | |||
5c5fe34241 | |||
32737a6bf7 | |||
7642308c14 | |||
f1c08d83b0 | |||
617412f9c3 | |||
cf716684a9 | |||
54565ed389 | |||
ab08385336 | |||
eb8ccf65d1 | |||
cb93027f32 | |||
607fd8e970 | |||
f4ac96d0ff | |||
1c7d156abd | |||
4c00059260 | |||
93d78c9c51 | |||
49bee4c0d8 | |||
d8c75f1bb0 | |||
6d40ef2d6b | |||
4ea6c27dcf | |||
a4d9192fbc | |||
7b772e93a3 | |||
05168395b0 | |||
03293c4fec | |||
479019f457 | |||
68515818b9 | |||
8bc369f828 | |||
3d1a4d5cc3 | |||
5c56b778e0 | |||
585e871c96 | |||
6ae7aee2c3 | |||
701270d039 | |||
02a852a34a | |||
531f940212 | |||
de80f1b6dd | |||
ca3965afe0 | |||
f269e433a7 | |||
8750b09fca | |||
ea2eef737b | |||
0ceab97a03 | |||
fbbdaaacc0 | |||
080de58a88 | |||
5390948360 | |||
0d860051af | |||
edbba24b60 | |||
6ae8d7691d | |||
af3cf36ce9 | |||
1be2f11965 | |||
495ce325b2 | |||
92411043d1 | |||
aa3f75b3c9 | |||
d64aadf57a | |||
51f7f081a3 | |||
b9fd62413f | |||
c5664bf245 | |||
c66a076614 | |||
28d34b699d | |||
47840bee71 | |||
305331f634 | |||
5e6c24cb01 | |||
0ec4e1372a | |||
84c1bad3a1 | |||
1640832f56 | |||
8ab036262d | |||
76e8c0ac7b | |||
0e81e418fb | |||
60255b68c0 | |||
ae7b3c8d45 | |||
9556ba7bca | |||
80994b25b9 | |||
2f154b980f | |||
342d352a00 | |||
f240ae5084 | |||
e4fc8bad35 | |||
5c680d4aa8 | |||
f05c5f82c8 | |||
2e0c58ec3e | |||
21093b9090 | |||
a6153accf0 | |||
dee789c204 | |||
12dd552fcd | |||
079bcffe07 | |||
30256e8fe8 | |||
8ee69831fc | |||
c3d8e2888d | |||
bea677136b | |||
11728bbbd9 | |||
1da4b03940 | |||
54ba0f021f | |||
836a5c72a0 | |||
f589933440 | |||
ef3ec34aa3 | |||
37a6d2d033 | |||
354f3639bb | |||
c4b06868b1 | |||
e3853e842e | |||
aee5cbd057 | |||
e9614eff1a | |||
80f9f7e8ef | |||
7d2589556f | |||
468fcab59d | |||
f720e972d4 | |||
b51ae7e59a | |||
eedb06936f | |||
ee5a094424 | |||
9773b5a173 | |||
eed171839e | |||
1057b52def | |||
302506e940 | |||
cc35feb445 | |||
21b875d4d0 | |||
dac9c09235 | |||
5cba438eb5 | |||
2b001cb2b1 | |||
0be8487f09 | |||
e1e69ca828 | |||
f376c46d78 | |||
fad4145f48 | |||
6b394f62be | |||
16aad8b2d8 | |||
25bbcbcbe5 |
@ -1,8 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
aio/content
|
|
||||||
aio/node_modules
|
aio/node_modules
|
||||||
aio/tools/examples/shared/node_modules
|
aio/tools/examples/shared/node_modules
|
||||||
integration/bazel
|
|
||||||
integration/bazel-schematics/demo
|
|
||||||
packages/bazel/node_modules
|
|
||||||
|
64
.bazelrc
64
.bazelrc
@ -1,3 +1,5 @@
|
|||||||
|
# Load any settings specific to the current user
|
||||||
|
try-import .bazelrc.user
|
||||||
################################
|
################################
|
||||||
# Settings for Angular team members only
|
# Settings for Angular team members only
|
||||||
################################
|
################################
|
||||||
@ -10,10 +12,8 @@ build:angular-team --remote_http_cache=https://storage.googleapis.com/angular-te
|
|||||||
|
|
||||||
# Make compilation fast, by keeping a few copies of the compilers
|
# Make compilation fast, by keeping a few copies of the compilers
|
||||||
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
||||||
|
build --strategy=TypeScriptCompile=worker
|
||||||
build --strategy=AngularTemplateCompile=worker
|
build --strategy=AngularTemplateCompile=worker
|
||||||
# TODO(alexeagle): re-enable after fixing worker instability with rxjs typings
|
|
||||||
# build --strategy=TypeScriptCompile=worker
|
|
||||||
build --strategy=TypeScriptCompile=standalone
|
|
||||||
|
|
||||||
# Enable debugging tests with --config=debug
|
# Enable debugging tests with --config=debug
|
||||||
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
||||||
@ -35,9 +35,8 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
|||||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||||
build --symlink_prefix=dist/
|
build --symlink_prefix=dist/
|
||||||
|
|
||||||
# Disable watchfs as it causes tests to be flaky on Windows
|
# Performance: avoid stat'ing input files
|
||||||
# https://github.com/angular/angular/issues/29541
|
build --watchfs
|
||||||
build --nowatchfs
|
|
||||||
|
|
||||||
# Turn off legacy external runfiles
|
# Turn off legacy external runfiles
|
||||||
run --nolegacy_external_runfiles
|
run --nolegacy_external_runfiles
|
||||||
@ -53,22 +52,6 @@ build --incompatible_strict_action_env
|
|||||||
run --incompatible_strict_action_env
|
run --incompatible_strict_action_env
|
||||||
test --incompatible_strict_action_env
|
test --incompatible_strict_action_env
|
||||||
|
|
||||||
###############################
|
|
||||||
# Saucelabs support #
|
|
||||||
# Turn on these settings with #
|
|
||||||
# --config=saucelabs #
|
|
||||||
###############################
|
|
||||||
|
|
||||||
# Expose SauceLabs environment to actions
|
|
||||||
# These environment variables are needed by
|
|
||||||
# web_test_karma to run on Saucelabs
|
|
||||||
test:saucelabs --action_env=SAUCE_USERNAME
|
|
||||||
test:saucelabs --action_env=SAUCE_ACCESS_KEY
|
|
||||||
test:saucelabs --action_env=SAUCE_READY_FILE
|
|
||||||
test:saucelabs --action_env=SAUCE_PID_FILE
|
|
||||||
test:saucelabs --action_env=SAUCE_TUNNEL_IDENTIFIER
|
|
||||||
test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Release support #
|
# Release support #
|
||||||
# Turn on these settings with #
|
# Turn on these settings with #
|
||||||
@ -76,9 +59,7 @@ test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED
|
|||||||
###############################
|
###############################
|
||||||
|
|
||||||
# Releases should always be stamped with version control info
|
# Releases should always be stamped with version control info
|
||||||
# This command assumes node on the path and is a workaround for
|
build:release --workspace_status_command=./tools/bazel_stamp_vars.sh
|
||||||
# https://github.com/bazelbuild/bazel/issues/4802
|
|
||||||
build:release --workspace_status_command="node ./tools/bazel_stamp_vars.js"
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Output #
|
# Output #
|
||||||
@ -116,21 +97,16 @@ build --define=compile=legacy
|
|||||||
# --config=remote
|
# --config=remote
|
||||||
###############################
|
###############################
|
||||||
|
|
||||||
# Load default settings for Remote Build Execution.
|
# Load default settings for Remote Build Execution
|
||||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain
|
# When updating, the URLs of bazel_toolchains in packages/bazel/package.bzl
|
||||||
|
# may also need to be updated (see https://github.com/angular/angular/pull/27935)
|
||||||
|
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/bazel-0.21.0.bazelrc
|
||||||
|
|
||||||
# Increase the default number of jobs by 50% because our build has lots of
|
# Increase the default number of jobs by 50% because our build has lots of
|
||||||
# parallelism
|
# parallelism
|
||||||
build:remote --jobs=150
|
build:remote --jobs=150
|
||||||
|
|
||||||
# Toolchain and platform related flags
|
# Point to our custom execution platform; see tools/BUILD.bazel
|
||||||
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
|
|
||||||
build:remote --javabase=@rbe_ubuntu1604_angular//java:jdk
|
|
||||||
build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
|
||||||
build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
|
||||||
build:remote --crosstool_top=@rbe_ubuntu1604_angular//cc:toolchain
|
|
||||||
build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
|
|
||||||
build:remote --extra_toolchains=@rbe_ubuntu1604_angular//config:cc-toolchain
|
|
||||||
build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
||||||
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
||||||
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
||||||
@ -141,21 +117,3 @@ build:remote --remote_instance_name=projects/internal-200822/instances/default_i
|
|||||||
# Do not accept remote cache.
|
# Do not accept remote cache.
|
||||||
# We need to understand the security risks of using prior build artifacts.
|
# We need to understand the security risks of using prior build artifacts.
|
||||||
build:remote --remote_accept_cached=false
|
build:remote --remote_accept_cached=false
|
||||||
|
|
||||||
###############################
|
|
||||||
# NodeJS rules settings
|
|
||||||
# These settings are required for rules_nodejs
|
|
||||||
###############################
|
|
||||||
|
|
||||||
# Turn on managed directories feature in Bazel
|
|
||||||
# This allows us to avoid installing a second copy of node_modules
|
|
||||||
common --experimental_allow_incremental_repository_updates
|
|
||||||
|
|
||||||
####################################################
|
|
||||||
# User bazel configuration
|
|
||||||
# NOTE: This needs to be the *last* entry in the config.
|
|
||||||
####################################################
|
|
||||||
|
|
||||||
# Load any settings which are specific to the current user. Needs to be *last* statement
|
|
||||||
# in this config, as the user configuration should be able to overwrite flags from this file.
|
|
||||||
try-import .bazelrc.user
|
|
||||||
|
42
.buildkite/Dockerfile
Normal file
42
.buildkite/Dockerfile
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Heavily based on https://github.com/StefanScherer/dockerfiles-windows/ images.
|
||||||
|
# Combines the node windowsservercore image with the Bazel Prerequisites (https://docs.bazel.build/versions/master/install-windows.html).
|
||||||
|
# msys install taken from https://github.com/StefanScherer/dockerfiles-windows/issues/30
|
||||||
|
# VS redist install taken from https://github.com/StefanScherer/dockerfiles-windows/blob/master/apache/Dockerfile
|
||||||
|
# The nanoserver image won't work because MSYS2 does not run in it https://github.com/Alexpux/MSYS2-packages/issues/1493
|
||||||
|
|
||||||
|
# Before building this image, you must locally build node-windows:10.13.0-windowsservercore-1803.
|
||||||
|
# Clone https://github.com/StefanScherer/dockerfiles-windows/commit/4ce7101a766b9b880ac262479dd9126b64d656cf and build using
|
||||||
|
# docker build -t node-windows:10.13.0-windowsservercore-1803 --build-arg core=microsoft/windowsservercore:1803 --build-arg target=microsoft/windowsservercore:1803 .
|
||||||
|
FROM node-windows:10.13.0-windowsservercore-1803
|
||||||
|
|
||||||
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
|
# Install 7zip to extract msys2
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe
|
||||||
|
# For some reason the last letter in the destination directory is lost. So '/D=C:\\7zip0' will extract to '/D=C:\\7zip'.
|
||||||
|
RUN Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait
|
||||||
|
|
||||||
|
# Extract msys2
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz
|
||||||
|
RUN Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait
|
||||||
|
RUN Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait
|
||||||
|
RUN Remove-Item msys2.tar.xz
|
||||||
|
RUN Remove-Item msys2.tar
|
||||||
|
RUN Remove-Item 7z.exe
|
||||||
|
RUN Remove-Item -Recurse 7zip
|
||||||
|
|
||||||
|
# Add MSYS2 to PATH, and set BAZEL_SH
|
||||||
|
RUN [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine)
|
||||||
|
RUN [Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine)
|
||||||
|
|
||||||
|
# Install Microsoft Visual C++ Redistributable for Visual Studio 2015
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing 'https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe' -OutFile vc_redist.x64.exe
|
||||||
|
RUN Start-Process 'c:\\vc_redist.x64.exe' -ArgumentList '/Install', '/Passive', '/NoRestart' -NoNewWindow -Wait
|
||||||
|
RUN Remove-Item vc_redist.x64.exe
|
||||||
|
|
||||||
|
# Add a fix for https://github.com/docker/for-win/issues/2920 as entry point to the container.
|
||||||
|
SHELL ["cmd", "/c"]
|
||||||
|
COPY "fix-msys64.cmd" "C:\\fix-msys64.cmd"
|
||||||
|
ENTRYPOINT cmd /C C:\\fix-msys64.cmd && cmd /c
|
||||||
|
|
||||||
|
CMD ["cmd.exe"]
|
96
.buildkite/README.md
Normal file
96
.buildkite/README.md
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# BuildKite configuration
|
||||||
|
|
||||||
|
This folder contains configuration for the [BuildKite](https://buildkite.com) based CI checks for
|
||||||
|
this repository.
|
||||||
|
|
||||||
|
BuildKite is a CI provider that provides build coordination and reports while we provide the
|
||||||
|
infrastructure.
|
||||||
|
|
||||||
|
CI runs are triggered by new PRs and will show up on the GitHub checks interface, along with the
|
||||||
|
other current CI solutions.
|
||||||
|
|
||||||
|
Currently it is only used for tests on Windows platforms.
|
||||||
|
|
||||||
|
|
||||||
|
## The build pipeline
|
||||||
|
|
||||||
|
BuildKite uses a pipeline for each repository. The `pipeline.yml` file defines pipeline
|
||||||
|
[build steps](https://buildkite.com/docs/pipelines/defining-steps) for this repository.
|
||||||
|
|
||||||
|
Run results can be seen in the GitHub checks interface and in the
|
||||||
|
[pipeline dashboard](https://buildkite.com/angular/angular).
|
||||||
|
|
||||||
|
Although most configuration is done via `pipeline.yml`, some options are only available
|
||||||
|
in the online [pipeline settings](https://buildkite.com/angular/angular/settings).
|
||||||
|
|
||||||
|
|
||||||
|
## Infrastructure
|
||||||
|
|
||||||
|
BuildKite does not provide the host machines where the builds runs, providing instead the
|
||||||
|
[BuildKite Agent](https://buildkite.com/docs/agent/v3) that should be run our own infrastructure.
|
||||||
|
|
||||||
|
|
||||||
|
### Agents
|
||||||
|
|
||||||
|
This agent polls the BuildKite API for builds, runs them, and reports back the results.
|
||||||
|
Agents are the unit of concurrency: each agent can run one build at any given time.
|
||||||
|
Adding agents allows more builds to be ran at the same time.
|
||||||
|
|
||||||
|
Individual agents can have tags, and pipeline steps can target only agents with certain tags via the
|
||||||
|
`agents` field in `pipeline.yml`.
|
||||||
|
For example: agents on Windows machines are tagged as `windows`, and the Windows specific build
|
||||||
|
steps list `windows: true` in their `agents` field.
|
||||||
|
|
||||||
|
You can see the current agent pool, along with their tags, in the
|
||||||
|
[agents list](https://buildkite.com/organizations/angular/agents).
|
||||||
|
|
||||||
|
|
||||||
|
### Our host machines
|
||||||
|
|
||||||
|
We use [Google Cloud](https://cloud.google.com/) as our cloud provider, under the
|
||||||
|
[Angular project](https://console.cloud.google.com/home/dashboard?project=internal-200822).
|
||||||
|
To access this project you need need to be logged in with a Google account that's a member of
|
||||||
|
team@angular.io.
|
||||||
|
For googlers this may be your google.com account, for others it is an angular.io account.
|
||||||
|
|
||||||
|
In this project we have a number of Windows VMs running, each of them with several agents.
|
||||||
|
The `provision-windows-buildkite.ps1` file contains instructions on how to create new host VMs that
|
||||||
|
are fully configured to run the BuildKite agents as services.
|
||||||
|
|
||||||
|
Our pipeline uses [docker-buildkite-plugin](https://github.com/buildkite-plugins/docker-buildkite-plugin)
|
||||||
|
to run build steps inside docker containers.
|
||||||
|
This way we achieve isolation and hermeticity.
|
||||||
|
|
||||||
|
The `Dockerfile` file describes a custom Docker image that includes NodeJs, Yarn, and the Bazel
|
||||||
|
pre-requisites on Windows.
|
||||||
|
|
||||||
|
To upload a new version of the docker image, follow any build instructions in `Dockerfile` and then
|
||||||
|
run `docker build -t angular/node-bazel-windows:NEW_VERSION`, followed by
|
||||||
|
`docker push angular/node-bazel-windows:NEW_VERSION`.
|
||||||
|
After being pushed it should be available online, and you can use the new version in `pipeline.yml`.
|
||||||
|
|
||||||
|
|
||||||
|
## Caretaker
|
||||||
|
|
||||||
|
BuildKite status can be found at https://www.buildkitestatus.com/.
|
||||||
|
|
||||||
|
Issues related to the BuildKite setup should be escalated to the Tools Team via the current
|
||||||
|
caretaker, followed by Alex Eagle and Filipe Silva.
|
||||||
|
|
||||||
|
Support requests should be submitted via email to support@buildkite.com and cc Igor, Misko, Alex,
|
||||||
|
Jeremy and Manu
|
||||||
|
|
||||||
|
|
||||||
|
## Rollout strategy
|
||||||
|
|
||||||
|
At the moment our BuildKite CI uses 1 host VM running 4 agents, thus being capable of 4 concurrent
|
||||||
|
builds.
|
||||||
|
The only test running is `bazel test //tools/ts-api-guardian:all`, and the PR check is not
|
||||||
|
mandatory.
|
||||||
|
|
||||||
|
In the future we should add cache support to speed up the initial `yarn` install, and also Bazel
|
||||||
|
remote caching to speed up Bazel builds.
|
||||||
|
|
||||||
|
After the current setup is verified as stable and reliable the GitHub PR check can become mandatory.
|
||||||
|
|
||||||
|
The tests ran should also be expanded to cover most, if not all, of the Bazel tests.
|
6
.buildkite/fix-msys64.cmd
Normal file
6
.buildkite/fix-msys64.cmd
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
REM Fix for https://github.com/docker/for-win/issues/2920
|
||||||
|
REM echo "Fixing msys64 folder..."
|
||||||
|
REM Touch all .dll files inside C:\msys64\
|
||||||
|
forfiles /p C:\msys64\ /s /m *.dll /c "cmd /c Copy /B @path+,, >NUL"
|
||||||
|
REM echo "Fixed msys64 folder."
|
10
.buildkite/pipeline.yml
Normal file
10
.buildkite/pipeline.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
steps:
|
||||||
|
- label: windows-test
|
||||||
|
commands:
|
||||||
|
- "yarn install --frozen-lockfile --non-interactive --network-timeout 100000"
|
||||||
|
- "yarn bazel test //tools/ts-api-guardian:all --noshow_progress"
|
||||||
|
plugins:
|
||||||
|
- docker#v2.1.0:
|
||||||
|
image: "filipesilva/node-bazel-windows:0.0.2"
|
||||||
|
agents:
|
||||||
|
windows: true
|
92
.buildkite/provision-windows-buildkite.ps1
Normal file
92
.buildkite/provision-windows-buildkite.ps1
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
# PowerShell script to provision a Windows Server with BuildKite
|
||||||
|
# This script follows https://buildkite.com/docs/agent/v3/windows.
|
||||||
|
|
||||||
|
# Instructions
|
||||||
|
|
||||||
|
# VM creation:
|
||||||
|
# In Google Cloud Platform, create a Compute Engine instance.
|
||||||
|
# We recommend machine type n1-highcpu-16 (16 vCPUs, 14.4 GB memory).
|
||||||
|
# Use a windows boot disk with container support such as
|
||||||
|
# "Windows Server version 1803 Datacenter Core for Containers".
|
||||||
|
# Give it a name, then click "Create".
|
||||||
|
|
||||||
|
# VM setup:
|
||||||
|
# In the Compute Engine menu, select "VM Instances". Click on the VM name you chose before.
|
||||||
|
# Click "Set Windows Password" to choose a username and password.
|
||||||
|
# Click RDP to open a remote desktop via browser, using the username and password.
|
||||||
|
# In the Windows command prompt start an elevated powershell by inputing
|
||||||
|
# "powershell -Command "Start-Process PowerShell -Verb RunAs" followed by Enter.
|
||||||
|
# Download and execute this script from GitHub, passing the token (mandatory), tags (optional)
|
||||||
|
# and number of agents (optional) as args:
|
||||||
|
# ```
|
||||||
|
# Invoke-WebRequest -Uri https://raw.githubusercontent.com/angular/angular/master/.buildkite/provision-windows-buildkite.ps1 -OutFile provision.ps1
|
||||||
|
# .\provision.ps1 -token "MY_TOKEN" -tags "windows=true,another_tag=true" -agents 4
|
||||||
|
# ```
|
||||||
|
# The VM should restart and be fully configured.
|
||||||
|
|
||||||
|
# Creating extra VMs
|
||||||
|
# You can create an image of the current VM by following the instructions below.
|
||||||
|
# https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image
|
||||||
|
# Then create a new VM and choose "Custom images".
|
||||||
|
|
||||||
|
|
||||||
|
# Script proper.
|
||||||
|
|
||||||
|
# Get the token and tags from arguments.
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)][string]$token,
|
||||||
|
[string]$tags = ""
|
||||||
|
[Int]$agents = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Allow HTTPS
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
|
||||||
|
|
||||||
|
# Helper to add to PATH.
|
||||||
|
# Will take current PATH so avoid running it after anything to modifies only the powershell session path.
|
||||||
|
function Add-Path ([string]$newPathItem) {
|
||||||
|
$Env:Path+= ";" + $newPathItem + ";"
|
||||||
|
[Environment]::SetEnvironmentVariable("Path",$env:Path, [System.EnvironmentVariableTarget]::Machine)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install Git for Windows
|
||||||
|
Write-Host "Installing Git for Windows."
|
||||||
|
Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.19.1.windows.1/Git-2.19.1-64-bit.exe -OutFile git.exe
|
||||||
|
.\git.exe /VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh" /DIR="C:\git"
|
||||||
|
Add-Path "C:\git\bin"
|
||||||
|
Remove-Item git.exe
|
||||||
|
|
||||||
|
# Download NSSM (https://nssm.cc/) to run the BuildKite agent as a service.
|
||||||
|
Write-Host "Downloading NSSM."
|
||||||
|
Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -OutFile nssm.zip
|
||||||
|
Expand-Archive -Path nssm.zip -DestinationPath C:\nssm
|
||||||
|
Add-Path "C:\nssm\nssm-2.24-101-g897c7ad\win64"
|
||||||
|
Remove-Item nssm.zip
|
||||||
|
|
||||||
|
# Run the BuildKite agent install script
|
||||||
|
Write-Host "Installing BuildKite agent."
|
||||||
|
$env:buildkiteAgentToken = $token
|
||||||
|
$env:buildkiteAgentTags = $tags
|
||||||
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||||
|
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/buildkite/agent/master/install.ps1'))
|
||||||
|
|
||||||
|
# Configure the BuildKite agent clone and timestamp behavior
|
||||||
|
Add-Content C:\buildkite-agent\buildkite-agent.cfg "`ngit-clone-flags=--config core.autocrlf=input --config core.eol=lf --config core.longpaths=true --config core.symlinks=true`n"
|
||||||
|
Add-Content C:\buildkite-agent\buildkite-agent.cfg "`ntimestamp-lines=true`n"
|
||||||
|
|
||||||
|
# Register the BuildKite agent service using NSSM, so that it persists through restarts and is
|
||||||
|
# restarted if the process dies.
|
||||||
|
for ($i=1; $i -le $agents; $i++)
|
||||||
|
{
|
||||||
|
$agentName = "buildkite-agent-$i"
|
||||||
|
Write-Host "Registering $agentName as a service."
|
||||||
|
nssm.exe install $agentName "C:\buildkite-agent\bin\buildkite-agent.exe" "start"
|
||||||
|
nssm.exe set $agentName AppStdout "C:\buildkite-agent\$agentName.log"
|
||||||
|
nssm.exe set $agentName AppStderr "C:\buildkite-agent\$agentName.log"
|
||||||
|
nssm.exe status $agentName
|
||||||
|
nssm.exe start $agentName
|
||||||
|
nssm.exe status $agentName
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restart the machine.
|
||||||
|
Restart-Computer
|
@ -15,48 +15,27 @@
|
|||||||
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
||||||
# version that is compatible with the Chrome version in the image.
|
# version that is compatible with the Chrome version in the image.
|
||||||
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||||
var_1: &default_docker_image circleci/node:10.16
|
var_1: &default_docker_image circleci/node:10.12
|
||||||
var_2: &browsers_docker_image circleci/node:10.16-browsers
|
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
||||||
# We don't want to include the current branch name in the cache key because that would prevent
|
# We don't want to include the current branch name in the cache key because that would prevent
|
||||||
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
||||||
# The cache key should only consist of dynamic values that change whenever something in the
|
# The cache key should only consist of dynamic values that change whenever something in the
|
||||||
# cache changes. For example:
|
# cache changes. For example:
|
||||||
# 1) yarn lock file changes --> cached "node_modules" are different.
|
# 1) yarn lock file changes --> cached "node_modules" are different.
|
||||||
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
||||||
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
var_3: &cache_key v2-angular-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-node-10.12
|
||||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
|
||||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
|
||||||
var_3: &cache_key v3-angular-node-10.16-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
|
||||||
|
|
||||||
# Initializes the CI environment by setting up common environment variables.
|
# Define common ENV vars
|
||||||
var_4: &init_environment
|
var_4: &define_env_vars
|
||||||
run:
|
run:
|
||||||
name: Initializing environment (setting up variables, overwriting Yarn)
|
name: Define environment variables
|
||||||
# Overwrite the yarn installed in the docker container with our own version.
|
command: ./.circleci/env.sh
|
||||||
command: |
|
|
||||||
./.circleci/env.sh
|
|
||||||
ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.13.0/bin/yarn.js)
|
|
||||||
sudo chmod a+x $ourYarn
|
|
||||||
sudo ln -fs $ourYarn /usr/local/bin/yarn
|
|
||||||
echo "Yarn version: $(yarn --version)"
|
|
||||||
|
|
||||||
# Add GitHub to known hosts.
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
# use git+ssh instead of https
|
|
||||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
|
||||||
git config --global gc.auto 0 || true
|
|
||||||
|
|
||||||
|
|
||||||
var_5: &setup_bazel_remote_execution
|
var_5: &setup_bazel_remote_execution
|
||||||
run:
|
run:
|
||||||
name: "Setup bazel RBE remote execution"
|
name: "Setup bazel RBE remote execution"
|
||||||
command: |
|
command: |
|
||||||
# We need ensure that the same default digest is used for encoding and decoding
|
openssl aes-256-cbc -d -in .circleci/gcp_token -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
||||||
# with openssl. Openssl versions might have different default digests which can
|
|
||||||
# cause decryption failures based on the openssl version. https://stackoverflow.com/a/39641378/4317734
|
|
||||||
openssl aes-256-cbc -d -in .circleci/gcp_token -md md5 -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
|
||||||
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
||||||
sudo bash -c "echo 'build --config=remote' >> /etc/bazel.bazelrc"
|
sudo bash -c "echo 'build --config=remote' >> /etc/bazel.bazelrc"
|
||||||
|
|
||||||
@ -66,20 +45,11 @@ var_6: &job_defaults
|
|||||||
docker:
|
docker:
|
||||||
- image: *default_docker_image
|
- image: *default_docker_image
|
||||||
|
|
||||||
# After checkout, rebase on top of target branch.
|
# After checkout, rebase on top of master.
|
||||||
|
# Similar to travis behavior, but not quite the same.
|
||||||
|
# See https://discuss.circleci.com/t/1662
|
||||||
var_7: &post_checkout
|
var_7: &post_checkout
|
||||||
run:
|
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
|
||||||
name: Rebase PR on target branch
|
|
||||||
command: >
|
|
||||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
|
||||||
# User is required for rebase.
|
|
||||||
git config user.name "angular-ci"
|
|
||||||
git config user.email "angular-ci"
|
|
||||||
# Rebase PR on top of target branch.
|
|
||||||
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
|
|
||||||
else
|
|
||||||
echo "This build is not over a PR, nothing to do."
|
|
||||||
fi
|
|
||||||
|
|
||||||
var_8: &yarn_install
|
var_8: &yarn_install
|
||||||
run:
|
run:
|
||||||
@ -97,63 +67,17 @@ var_9: &setup_circleci_bazel_config
|
|||||||
name: Setting up CircleCI bazel configuration
|
name: Setting up CircleCI bazel configuration
|
||||||
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||||
|
|
||||||
var_10: &restore_cache
|
|
||||||
restore_cache:
|
|
||||||
keys:
|
|
||||||
- *cache_key
|
|
||||||
# This fallback should be the cache_key without variables.
|
|
||||||
- v3-angular-node-10.16-
|
|
||||||
|
|
||||||
# Branch filter that can be specified for jobs that should only run on publish branches
|
|
||||||
# (e.g. master or the patch branch)
|
|
||||||
var_12: &publish_branches_filter
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
# e.g. 7.0.x, 7.1.x, etc.
|
|
||||||
- /\d+\.\d+\.x/
|
|
||||||
|
|
||||||
# Workspace initially persisted by the `install` job, and then enhanced by `test_aio` and
|
|
||||||
# `build-npm-packages`.
|
|
||||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
|
||||||
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
|
||||||
var_13: &attach_workspace
|
|
||||||
attach_workspace:
|
|
||||||
at: ~/
|
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
|
||||||
<<: *job_defaults
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
- *post_checkout
|
|
||||||
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
|
||||||
- *yarn_install
|
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
|
||||||
# Make the bazel directories and add a file to them if they don't exist already so that
|
|
||||||
# persist_to_workspace does not fail.
|
|
||||||
- run: |
|
|
||||||
if [ ! -d ~/bazel_repository_cache ]; then
|
|
||||||
mkdir ~/bazel_repository_cache
|
|
||||||
touch ~/bazel_repository_cache/MARKER
|
|
||||||
fi
|
|
||||||
# Persist any changes at this point to be reused by further jobs.
|
|
||||||
# **NOTE 1 **: Folders persisted here should be kept in sync with `var_13: &attach_workspace`.
|
|
||||||
# **NOTE 2 **: To add new content to the workspace, always persist on the same root.
|
|
||||||
- persist_to_workspace:
|
|
||||||
root: ~/
|
|
||||||
paths:
|
|
||||||
- ./ng
|
|
||||||
- ./bazel_repository_cache
|
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
|
- *yarn_install
|
||||||
|
|
||||||
- run: 'yarn bazel:format -mode=check ||
|
- run: 'yarn bazel:format -mode=check ||
|
||||||
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
||||||
@ -161,38 +85,45 @@ jobs:
|
|||||||
- run: 'yarn bazel:lint ||
|
- run: 'yarn bazel:lint ||
|
||||||
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
||||||
|
|
||||||
- run: yarn gulp lint
|
- run: ./node_modules/.bin/gulp lint
|
||||||
|
|
||||||
test:
|
test:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
- *yarn_install
|
||||||
- setup_remote_docker
|
|
||||||
# Setup remote execution and run RBE-compatible tests.
|
# Setup remote execution and run RBE-compatible tests.
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-local
|
||||||
- run: mkdir ~/testlogs
|
# Now run RBE incompatible tests locally.
|
||||||
- run: cp -Lr dist/testlogs/* ~/testlogs
|
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||||
- store_test_results:
|
- run: yarn bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||||
# Bazel always writes test.xml files under this directory
|
|
||||||
path: ~/testlogs
|
- save_cache:
|
||||||
- store_artifacts:
|
key: *cache_key
|
||||||
path: ~/testlogs
|
paths:
|
||||||
|
- "node_modules"
|
||||||
|
- "~/bazel_repository_cache"
|
||||||
|
|
||||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||||
test_ivy_aot:
|
test_ivy_aot:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
- *yarn_install
|
||||||
- setup_remote_docker
|
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||||
@ -219,55 +150,31 @@ jobs:
|
|||||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||||
destination: core/todo/bundle.br
|
destination: core/todo/bundle.br
|
||||||
|
|
||||||
test_saucelabs_bazel:
|
|
||||||
<<: *job_defaults
|
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
|
||||||
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
|
||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
- *setup_circleci_bazel_config
|
|
||||||
- run:
|
|
||||||
name: Preparing environment for running tests on Saucelabs.
|
|
||||||
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
|
||||||
- run:
|
|
||||||
name: Starting Saucelabs tunnel
|
|
||||||
command: ./scripts/saucelabs/start-tunnel.sh
|
|
||||||
background: true
|
|
||||||
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
|
||||||
# too early without Saucelabs not being ready.
|
|
||||||
- run: ./scripts/saucelabs/wait-for-tunnel.sh
|
|
||||||
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
|
||||||
# as running each set of tests as a separate target will attempt to acquire too
|
|
||||||
# many browsers on Saucelabs (7 per target currently) and some tests will always
|
|
||||||
# fail to acquire browsers. For example:
|
|
||||||
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
|
|
||||||
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
|
||||||
- run: yarn bazel test --config=saucelabs //:test_web_all
|
|
||||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
# Build aio
|
# Build aio
|
||||||
- run: yarn --cwd aio build --progress=false
|
- run: yarn --cwd aio build --progress=false
|
||||||
# Lint the code
|
# Lint the code
|
||||||
- run: yarn --cwd aio lint
|
- run: yarn --cwd aio lint
|
||||||
|
# Run PWA-score tests
|
||||||
|
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||||
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
|
# Check the bundle sizes.
|
||||||
|
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||||
|
- run: yarn --cwd aio payload-size
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
# Run PWA-score tests
|
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
|
||||||
# Check the bundle sizes.
|
|
||||||
- run: yarn --cwd aio payload-size
|
|
||||||
# Run unit tests for Firebase redirects
|
# Run unit tests for Firebase redirects
|
||||||
- run: yarn --cwd aio redirects-test
|
- run: yarn --cwd aio redirects-test
|
||||||
|
|
||||||
@ -277,10 +184,13 @@ jobs:
|
|||||||
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
# Deploy angular.io to production (if necessary)
|
# Deploy angular.io to production (if necessary)
|
||||||
- run: setPublicVar_CI_STABLE_BRANCH
|
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
||||||
- run: yarn --cwd aio deploy-production
|
- run: yarn --cwd aio deploy-production
|
||||||
|
|
||||||
test_aio_local:
|
test_aio_local:
|
||||||
@ -289,43 +199,46 @@ jobs:
|
|||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
|
- *define_env_vars
|
||||||
# Build aio (with local Angular packages)
|
# Build aio (with local Angular packages)
|
||||||
- run: yarn --cwd aio build-local --progress=false
|
- run: yarn --cwd aio build-local --progress=false
|
||||||
|
# Run PWA-score tests
|
||||||
|
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||||
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
# Run PWA-score tests
|
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
|
||||||
# Check the bundle sizes.
|
|
||||||
- run: yarn --cwd aio payload-size aio-local
|
|
||||||
|
|
||||||
test_aio_local_ivy:
|
test_aio_local_ivy:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
|
||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
|
- *define_env_vars
|
||||||
# Build aio with Ivy (using local Angular packages)
|
# Build aio with Ivy (using local Angular packages)
|
||||||
- run: yarn --cwd aio build-with-ivy --progress=false
|
- run: yarn --cwd aio build-with-ivy --progress=false
|
||||||
# Run unit tests
|
|
||||||
- run: yarn --cwd aio test --progress=false --watch=false
|
|
||||||
# Run e2e tests
|
|
||||||
- run: yarn --cwd aio e2e --configuration=ci
|
|
||||||
# Run PWA-score tests
|
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
|
||||||
# Check the bundle sizes.
|
|
||||||
- run: yarn --cwd aio payload-size aio-local-ivy
|
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
|
- *define_env_vars
|
||||||
# Install
|
# Install
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
- run: yarn --cwd aio extract-cli-command-docs
|
- run: yarn --cwd aio extract-cli-command-docs
|
||||||
@ -338,43 +251,23 @@ jobs:
|
|||||||
docker:
|
docker:
|
||||||
# Needed because the example e2e tests depend on Chrome.
|
# Needed because the example e2e tests depend on Chrome.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
parallelism: 4
|
parallelism: 3
|
||||||
resource_class: xlarge
|
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
|
- *define_env_vars
|
||||||
|
# Install root
|
||||||
|
- *yarn_install
|
||||||
# Install aio
|
# Install aio
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||||
- run: yarn --cwd aio example-e2e --setup --local --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
- run: yarn --cwd aio example-e2e --setup --local --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||||
|
|
||||||
test_docs_examples_ivy:
|
|
||||||
<<: *job_defaults
|
|
||||||
docker:
|
|
||||||
# Needed because the example e2e tests depend on Chrome.
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
resource_class: xlarge
|
|
||||||
# We increase the parallelism here to five while the "test_docs_examples" job runs with
|
|
||||||
# a parallelism of four. This is necessary because this job also need to run NGCC which
|
|
||||||
# takes up more time and we don't want these jobs to impact the overall CI turnaround.
|
|
||||||
parallelism: 5
|
|
||||||
steps:
|
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
# Install aio
|
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
|
||||||
# Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO
|
|
||||||
# package installer picks up the locally built packages from that location.
|
|
||||||
# *Note*: We could also adjust the packages installer, but given we won't have
|
|
||||||
# two different folders of Angular distributions in the future, we should keep
|
|
||||||
# the packages installer unchanged.
|
|
||||||
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
|
||||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
|
||||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
|
||||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
|
||||||
- run: yarn --cwd aio example-e2e --setup --local --ivy --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
|
||||||
|
|
||||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
aio_preview:
|
aio_preview:
|
||||||
@ -382,8 +275,12 @@ jobs:
|
|||||||
environment:
|
environment:
|
||||||
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
|
- *yarn_install
|
||||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: *aio_preview_artifact_path
|
path: *aio_preview_artifact_path
|
||||||
@ -399,9 +296,12 @@ jobs:
|
|||||||
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
|
- run: yarn install --cwd aio --frozen-lockfile --non-interactive
|
||||||
- run:
|
- run:
|
||||||
name: Wait for preview and run tests
|
name: Wait for preview and run tests
|
||||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||||
@ -419,48 +319,47 @@ jobs:
|
|||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
- *yarn_install
|
||||||
- setup_remote_docker
|
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
- run: scripts/build-packages-dist.sh
|
- run: scripts/build-packages-dist.sh
|
||||||
|
|
||||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: ~/
|
root: dist
|
||||||
paths:
|
paths:
|
||||||
- ng/dist/packages-dist
|
- packages-dist
|
||||||
|
|
||||||
# Save dependencies and bazel repository cache to use on subsequent runs.
|
|
||||||
- save_cache:
|
|
||||||
key: *cache_key
|
|
||||||
paths:
|
|
||||||
- "node_modules"
|
|
||||||
- "aio/node_modules"
|
|
||||||
- "~/bazel_repository_cache"
|
|
||||||
|
|
||||||
# Build the ivy npm packages.
|
# Build the ivy npm packages.
|
||||||
build-ivy-npm-packages:
|
build-ivy-npm-packages:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
# Enable remote/sibling docker which is needed by auto-selection of toolchain configs for RBE.
|
- *yarn_install
|
||||||
- setup_remote_docker
|
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
- run: scripts/build-ivy-npm-packages.sh
|
- run: scripts/build-ivy-npm-packages.sh
|
||||||
|
|
||||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: ~/
|
root: dist
|
||||||
paths:
|
paths:
|
||||||
- ng/dist/packages-dist-ivy-aot
|
- packages-dist-ivy-aot
|
||||||
|
|
||||||
# We run the integration tests outside of Bazel for now.
|
# We run the integration tests outside of Bazel for now.
|
||||||
# They are a separate workflow job so that they can be easily re-run.
|
# They are a separate workflow job so that they can be easily re-run.
|
||||||
@ -479,8 +378,13 @@ jobs:
|
|||||||
# on a 4G worker so we use a larger machine here too.
|
# on a 4G worker so we use a larger machine here too.
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
|
- *define_env_vars
|
||||||
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
||||||
# amount of container nodes for this job is controlled by the "parallelism" option.
|
# amount of container nodes for this job is controlled by the "parallelism" option.
|
||||||
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
||||||
@ -490,75 +394,65 @@ jobs:
|
|||||||
publish_snapshot:
|
publish_snapshot:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
|
- checkout:
|
||||||
|
<<: *post_checkout
|
||||||
|
- *define_env_vars
|
||||||
# See below - ideally this job should not trigger for non-upstream builds.
|
# See below - ideally this job should not trigger for non-upstream builds.
|
||||||
# But since it does, we have to check this condition.
|
# But since it does, we have to check this condition.
|
||||||
- run:
|
- run:
|
||||||
name: Skip this job for Pull Requests and Fork builds
|
name: Skip this job for Pull Requests and Fork builds
|
||||||
# Note: Using `CIRCLE_*` env variables (instead of those defined in `env.sh` so that this
|
# Note, `|| true` on the end makes this step always exit 0
|
||||||
# step can be run before `init_environment`.
|
command: '[[
|
||||||
command: >
|
"$CI_PULL_REQUEST" != "false"
|
||||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]] ||
|
|| "$CI_REPO_OWNER" != "angular"
|
||||||
[[ "$CIRCLE_PROJECT_USERNAME" != "angular" ]] ||
|
|| "$CI_REPO_NAME" != "angular"
|
||||||
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
]] && circleci step halt || true'
|
||||||
circleci step halt
|
- attach_workspace:
|
||||||
fi
|
at: dist
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
# CircleCI has a config setting to force SSH for all github connections
|
# CircleCI has a config setting to force SSH for all github connections
|
||||||
# This is not compatible with our mechanism of using a Personal Access Token
|
# This is not compatible with our mechanism of using a Personal Access Token
|
||||||
# Clear the global setting
|
# Clear the global setting
|
||||||
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
||||||
- run:
|
- run:
|
||||||
name: Decrypt github credentials
|
name: Decrypt github credentials
|
||||||
# We need ensure that the same default digest is used for encoding and decoding with
|
command: 'openssl aes-256-cbc -d -in .circleci/github_token -k "${KEY}" -out ~/.git_credentials'
|
||||||
# openssl. Openssl versions might have different default digests which can cause
|
|
||||||
# decryption failures based on the installed openssl version. https://stackoverflow.com/a/39641378/4317734
|
|
||||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
|
|
||||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||||
|
|
||||||
aio_monitoring_stable:
|
aio_monitoring:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||||
# which does not load the browser through the Bazel webtesting rules.
|
# which does not load the browser through the Bazel webtesting rules.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
- run: setPublicVar_CI_STABLE_BRANCH
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
- run:
|
- run:
|
||||||
name: Check out `aio/` from the stable branch
|
name: Run tests against the deployed apps
|
||||||
command: |
|
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||||
git fetch origin $CI_STABLE_BRANCH
|
|
||||||
git checkout --force origin/$CI_STABLE_BRANCH -- aio/
|
|
||||||
- run:
|
|
||||||
name: Run tests against https://angular.io/
|
|
||||||
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
|
||||||
- run:
|
- run:
|
||||||
name: Notify caretaker about failure
|
name: Notify caretaker about failure
|
||||||
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL'
|
||||||
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
|
||||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL'
|
|
||||||
when: on_fail
|
when: on_fail
|
||||||
|
|
||||||
aio_monitoring_next:
|
legacy-unit-tests-local:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
|
||||||
# which does not load the browser through the Bazel webtesting rules.
|
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
- run:
|
- restore_cache:
|
||||||
name: Run tests against https://next.angular.io/
|
key: *cache_key
|
||||||
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
- *define_env_vars
|
||||||
- run:
|
- *yarn_install
|
||||||
name: Notify caretaker about failure
|
- run: yarn tsc -p packages
|
||||||
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
- run: yarn tsc -p packages/examples
|
||||||
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
- run: yarn tsc -p modules
|
||||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL'
|
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=ChromeNoSandbox
|
||||||
when: on_fail
|
|
||||||
|
|
||||||
legacy-unit-tests-saucelabs:
|
legacy-unit-tests-saucelabs:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
@ -567,8 +461,12 @@ jobs:
|
|||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
|
- *yarn_install
|
||||||
- run:
|
- run:
|
||||||
name: Preparing environment for running tests on Saucelabs.
|
name: Preparing environment for running tests on Saucelabs.
|
||||||
command: |
|
command: |
|
||||||
@ -579,6 +477,7 @@ jobs:
|
|||||||
command: ./scripts/saucelabs/start-tunnel.sh
|
command: ./scripts/saucelabs/start-tunnel.sh
|
||||||
background: true
|
background: true
|
||||||
- run: yarn tsc -p packages
|
- run: yarn tsc -p packages
|
||||||
|
- run: yarn tsc -p packages/examples
|
||||||
- run: yarn tsc -p modules
|
- run: yarn tsc -p modules
|
||||||
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
||||||
# too early without Saucelabs not being ready.
|
# too early without Saucelabs not being ready.
|
||||||
@ -586,122 +485,78 @@ jobs:
|
|||||||
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=${KARMA_JS_BROWSERS}
|
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=${KARMA_JS_BROWSERS}
|
||||||
- run: ./scripts/saucelabs/stop-tunnel.sh
|
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||||
|
|
||||||
|
legacy-e2e-tests:
|
||||||
|
<<: *job_defaults
|
||||||
|
docker:
|
||||||
|
- image: *browsers_docker_image
|
||||||
|
steps:
|
||||||
|
- checkout:
|
||||||
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
|
- *setup_circleci_bazel_config
|
||||||
|
- *yarn_install
|
||||||
|
- *setup_bazel_remote_execution
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
|
# Build the e2e tests using the existing Bazel "packages-dist" output that has been
|
||||||
|
# attached to this job. This avoids multiple rebuilds across various CI jobs.
|
||||||
|
- run: ./scripts/build-e2e-tests.sh --use-existing-packages-dist
|
||||||
|
- run:
|
||||||
|
name: Starting servers for e2e tests
|
||||||
|
command: yarn gulp serve serve-examples
|
||||||
|
background: true
|
||||||
|
- run: NODE_PATH=$NODE_PATH:./dist/all yarn protractor ./protractor-e2e.conf.js --bundles=true
|
||||||
|
- run: NODE_PATH=$NODE_PATH:./dist/all yarn protractor ./protractor-examples-e2e.conf.js --bundles=true
|
||||||
|
- run: NODE_PATH=$NODE_PATH:./dist/all yarn protractor ./protractor-perf.conf.js --bundles=true --dryrun
|
||||||
|
|
||||||
legacy-misc-tests:
|
legacy-misc-tests:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- *attach_workspace
|
- checkout:
|
||||||
- *init_environment
|
<<: *post_checkout
|
||||||
|
- restore_cache:
|
||||||
|
key: *cache_key
|
||||||
|
- *define_env_vars
|
||||||
|
- *yarn_install
|
||||||
|
- attach_workspace:
|
||||||
|
at: dist
|
||||||
- run: yarn gulp check-cycle
|
- run: yarn gulp check-cycle
|
||||||
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
||||||
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
||||||
# - run: yarn gulp source-map-test
|
# - run: yarn gulp source-map-test
|
||||||
|
|
||||||
# Job to run unit tests from angular/material2. Needs a browser since all
|
|
||||||
# component unit tests assume they're running in the browser environment.
|
|
||||||
material-unit-tests:
|
|
||||||
<<: *job_defaults
|
|
||||||
resource_class: xlarge
|
|
||||||
docker:
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
# The Material unit tests support splitting the browsers across multiple CircleCI
|
|
||||||
# instances. Since by default this job launches two browsers, we run each browser
|
|
||||||
# in its own container instance.
|
|
||||||
# https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L107-L110
|
|
||||||
parallelism: 2
|
|
||||||
environment:
|
|
||||||
# The Material unit tests also support launching the same browser multiple times by
|
|
||||||
# sharding individual specs across the defined multiple instances.
|
|
||||||
# See: https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L113-L116
|
|
||||||
KARMA_PARALLEL_BROWSERS: 3
|
|
||||||
steps:
|
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
- run:
|
|
||||||
name: "Cloning Material repository"
|
|
||||||
command: ./scripts/ci/clone_angular_material_repo.sh
|
|
||||||
- restore_cache:
|
|
||||||
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
|
||||||
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
|
||||||
keys:
|
|
||||||
- v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }}
|
|
||||||
- v2-angular-material-
|
|
||||||
- run:
|
|
||||||
name: Installing Material dependencies.
|
|
||||||
command: yarn --cwd ${MATERIAL_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
|
||||||
# Save the cache before we run the Material unit tests script. This is necessary
|
|
||||||
# because we don't want to cache the node modules which have been modified to contain
|
|
||||||
# the attached Ivy package output.
|
|
||||||
- save_cache:
|
|
||||||
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
|
||||||
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
|
||||||
key: v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }}
|
|
||||||
paths:
|
|
||||||
- "/tmp/material2/node_modules"
|
|
||||||
- run:
|
|
||||||
name: "Running Material unit tests"
|
|
||||||
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
|
||||||
|
|
||||||
test_zonejs:
|
|
||||||
<<: *job_defaults
|
|
||||||
steps:
|
|
||||||
- *attach_workspace
|
|
||||||
- *init_environment
|
|
||||||
# Install
|
|
||||||
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
|
||||||
# Run zone.js tools tests
|
|
||||||
- run: yarn --cwd packages/zone.js promisetest
|
|
||||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
default_workflow:
|
default_workflow:
|
||||||
jobs:
|
jobs:
|
||||||
- setup
|
- lint
|
||||||
- lint:
|
- test
|
||||||
requires:
|
- test_ivy_aot
|
||||||
- setup
|
- build-npm-packages
|
||||||
- test:
|
- test_aio
|
||||||
requires:
|
- legacy-unit-tests-local
|
||||||
- setup
|
- legacy-unit-tests-saucelabs
|
||||||
- test_ivy_aot:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- build-npm-packages:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- build-ivy-npm-packages:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- test_aio:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- legacy-unit-tests-saucelabs:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- deploy_aio:
|
- deploy_aio:
|
||||||
requires:
|
requires:
|
||||||
- test_aio
|
- test_aio
|
||||||
|
- legacy-e2e-tests:
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
- legacy-misc-tests:
|
- legacy-misc-tests:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_aio_local:
|
- test_aio_local:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_aio_local_ivy:
|
|
||||||
requires:
|
|
||||||
- build-npm-packages
|
|
||||||
- test_aio_tools:
|
- test_aio_tools:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_docs_examples:
|
- test_docs_examples:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_docs_examples_ivy:
|
|
||||||
requires:
|
|
||||||
- build-ivy-npm-packages
|
|
||||||
- aio_preview:
|
- aio_preview:
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
@ -724,51 +579,23 @@ workflows:
|
|||||||
- integration_test
|
- integration_test
|
||||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||||
- test_aio_local
|
- test_aio_local
|
||||||
- test_aio_local_ivy
|
# - test_aio_local_ivy
|
||||||
- test_docs_examples
|
- test_docs_examples
|
||||||
- test_docs_examples_ivy
|
# Get the artifacts to publish from the build-npm-packages job
|
||||||
# Get the artifacts to publish from the build-packages-dist job
|
|
||||||
# since the publishing script expects the legacy outputs layout.
|
# since the publishing script expects the legacy outputs layout.
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- build-ivy-npm-packages
|
- legacy-e2e-tests
|
||||||
- legacy-unit-tests-saucelabs
|
|
||||||
- legacy-misc-tests
|
- legacy-misc-tests
|
||||||
- material-unit-tests:
|
- legacy-unit-tests-local
|
||||||
requires:
|
- legacy-unit-tests-saucelabs
|
||||||
- build-ivy-npm-packages
|
|
||||||
- test_zonejs:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
|
|
||||||
saucelabs_tests:
|
|
||||||
jobs:
|
|
||||||
- setup
|
|
||||||
- test_saucelabs_bazel:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
triggers:
|
|
||||||
- schedule:
|
|
||||||
# Runs the Saucelabs legacy tests every hour. We still want to run Saucelabs
|
|
||||||
# frequently as the caretaker needs up-to-date results when merging PRs or creating
|
|
||||||
# a new release. Also we primarily moved the Saucelabs job into a cronjob that doesn't
|
|
||||||
# run for PRs, in order to ensure that PRs are not affected by Saucelabs flakiness or
|
|
||||||
# incidents. This is still guaranteed (even if we run the job every hour).
|
|
||||||
cron: "0 * * * *"
|
|
||||||
filters: *publish_branches_filter
|
|
||||||
|
|
||||||
aio_monitoring:
|
aio_monitoring:
|
||||||
jobs:
|
jobs:
|
||||||
- setup
|
- aio_monitoring
|
||||||
- aio_monitoring_stable:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
- aio_monitoring_next:
|
|
||||||
requires:
|
|
||||||
- setup
|
|
||||||
triggers:
|
triggers:
|
||||||
- schedule:
|
- schedule:
|
||||||
# Runs AIO monitoring jobs at 10:00AM every day.
|
cron: "0 0 * * *"
|
||||||
cron: "0 10 * * *"
|
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
@ -36,38 +36,3 @@ function setSecretVar() {
|
|||||||
# Restore original shell options.
|
# Restore original shell options.
|
||||||
eval "$originalShellOptions";
|
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;
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
|
readonly envHelpersPath="`dirname $0`/env-helpers.inc.sh";
|
||||||
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
|
readonly getCommitRangePath="`dirname $0`/get-commit-range.js";
|
||||||
readonly getCommitRangePath="$projectDir/.circleci/get-commit-range.js";
|
|
||||||
|
|
||||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||||
source $envHelpersPath;
|
source $envHelpersPath;
|
||||||
@ -15,7 +14,7 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
setPublicVar PROJECT_ROOT "$projectDir";
|
setPublicVar PROJECT_ROOT "$(pwd)";
|
||||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||||
@ -23,7 +22,7 @@ setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
|||||||
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
||||||
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
||||||
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
||||||
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 75.0.3770.90";
|
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 2.45";
|
||||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be
|
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be
|
||||||
# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and
|
# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and
|
||||||
@ -34,18 +33,13 @@ setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
|||||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_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.
|
# Define SECRET environment variables for CircleCI.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||||
|
# Defined in https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||||
|
setSecretVar CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL "$SLACK_CARETAKER_WEBHOOK_URL";
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
@ -61,7 +55,6 @@ else
|
|||||||
setPublicVar SAUCE_USERNAME "angular-ci";
|
setPublicVar SAUCE_USERNAME "angular-ci";
|
||||||
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
||||||
fi
|
fi
|
||||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
|
||||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||||
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||||
@ -69,15 +62,6 @@ setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_
|
|||||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||||
|
|
||||||
####################################################################################################
|
|
||||||
# Define environment variables for the Angular Material unit tests job.
|
|
||||||
####################################################################################################
|
|
||||||
# We specifically use a directory within "/tmp" here because we want the cloned repo to be
|
|
||||||
# completely isolated from angular/angular in order to avoid any bad interactions between
|
|
||||||
# their separate build setups.
|
|
||||||
setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2"
|
|
||||||
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
|
|
||||||
setPublicVar MATERIAL_REPO_BRANCH "ivy-2019"
|
|
||||||
|
|
||||||
# Source `$BASH_ENV` to make the variables available immediately.
|
# Source `$BASH_ENV` to make the variables available immediately.
|
||||||
source $BASH_ENV;
|
source $BASH_ENV;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
* node get-commit-range <build-number> [<compare-url> [<circle-token>]]
|
* node get-commit-range <build-number> [<compare-url> [<circle-token>]]
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Returns the commit range, either extracting it from `compare-url` (if defined), which is of the
|
* Returns the value of the `CIRCLE_COMPARE_URL` environment variable (if defined) or, if this is
|
||||||
* format of the `CIRCLE_COMPARE_URL` environment variable, or by retrieving the equivalent of
|
* not a PR build (i.e. `CIRCLE_PR_NUMBER` is not defined), retrieves the equivalent of
|
||||||
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow and extracting it from there.
|
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow.
|
||||||
*
|
*
|
||||||
* **Context:**
|
* **Context:**
|
||||||
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
||||||
@ -141,7 +141,7 @@ function getJson(url) {
|
|||||||
const opts = {headers: {Accept: 'application/json'}};
|
const opts = {headers: {Accept: 'application/json'}};
|
||||||
const onResponse = res => {
|
const onResponse = res => {
|
||||||
const statusCode = res.statusCode || -1;
|
const statusCode = res.statusCode || -1;
|
||||||
const isSuccess = (200 <= statusCode) && (statusCode < 400);
|
const isSuccess = (200 <= statusCode) && (statusCode <= 400);
|
||||||
let responseText = '';
|
let responseText = '';
|
||||||
|
|
||||||
res.
|
res.
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
# escape=`
|
|
||||||
|
|
||||||
ARG core=mcr.microsoft.com/windows/servercore:1809
|
|
||||||
ARG target=mcr.microsoft.com/powershell:windowsservercore-1809
|
|
||||||
|
|
||||||
FROM $core as download
|
|
||||||
|
|
||||||
ARG node_version=10.13.0
|
|
||||||
ARG yarn_version=1.13.0
|
|
||||||
|
|
||||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
|
||||||
|
|
||||||
ENV GPG_VERSION 2.3.4
|
|
||||||
|
|
||||||
RUN Invoke-WebRequest $('https://files.gpg4win.org/gpg4win-vanilla-{0}.exe' -f $env:GPG_VERSION) -OutFile 'gpg4win.exe' -UseBasicParsing ; `
|
|
||||||
Start-Process .\gpg4win.exe -ArgumentList '/S' -NoNewWindow -Wait
|
|
||||||
|
|
||||||
RUN @( `
|
|
||||||
'94AE36675C464D64BAFA68DD7434390BDBE9B9C5', `
|
|
||||||
'FD3A5288F042B6850C66B31F09FE44734EB7990E', `
|
|
||||||
'71DCFD284A79C3B38668286BC97EC7A07EDE3FC1', `
|
|
||||||
'DD8F2338BAE7501E3DD5AC78C273792F7D83545D', `
|
|
||||||
'C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8', `
|
|
||||||
'B9AE9905FFD7803F25714661B63B535A4C206CA9', `
|
|
||||||
'77984A986EBC2AA786BC0F66B01FBB92821C587A', `
|
|
||||||
'8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600', `
|
|
||||||
'4ED778F539E3634C779C87C6D7062848A1AB005C', `
|
|
||||||
'A48C2BEE680E841632CD4E44F07496B3EB3C1762', `
|
|
||||||
'B9E2F5981AA6E0CD28160D9FF13993A75599653C' `
|
|
||||||
) | foreach { `
|
|
||||||
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys $_ ; `
|
|
||||||
}
|
|
||||||
|
|
||||||
ENV NODE_VERSION=$node_version
|
|
||||||
|
|
||||||
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/SHASUMS256.txt.asc' -f $env:NODE_VERSION) -OutFile 'SHASUMS256.txt.asc' -UseBasicParsing ; `
|
|
||||||
gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc
|
|
||||||
|
|
||||||
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/node-v{0}-win-x64.zip' -f $env:NODE_VERSION) -OutFile 'node.zip' -UseBasicParsing ; `
|
|
||||||
$sum = $(cat SHASUMS256.txt.asc | sls $(' node-v{0}-win-x64.zip' -f $env:NODE_VERSION)) -Split ' ' ; `
|
|
||||||
if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $sum[0]) { Write-Error 'SHA256 mismatch' } ; `
|
|
||||||
Expand-Archive node.zip -DestinationPath C:\ ; `
|
|
||||||
Rename-Item -Path $('C:\node-v{0}-win-x64' -f $env:NODE_VERSION) -NewName 'C:\nodejs'
|
|
||||||
|
|
||||||
ENV YARN_VERSION=$yarn_version
|
|
||||||
|
|
||||||
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
|
|
||||||
Invoke-WebRequest $('https://yarnpkg.com/downloads/{0}/yarn-{0}.msi' -f $env:YARN_VERSION) -OutFile yarn.msi -UseBasicParsing ; `
|
|
||||||
$sig = Get-AuthenticodeSignature yarn.msi ; `
|
|
||||||
if ($sig.Status -ne 'Valid') { Write-Error 'Authenticode signature is not valid' } ; `
|
|
||||||
Write-Output $sig.SignerCertificate.Thumbprint ; `
|
|
||||||
if (@( `
|
|
||||||
'7E253367F8A102A91D04829E37F3410F14B68A5F', `
|
|
||||||
'AF764E1EA56C762617BDC757C8B0F3780A0CF5F9' `
|
|
||||||
) -notcontains $sig.SignerCertificate.Thumbprint) { Write-Error 'Unknown signer certificate' } ; `
|
|
||||||
Start-Process msiexec.exe -ArgumentList '/i', 'yarn.msi', '/quiet', '/norestart' -NoNewWindow -Wait
|
|
||||||
|
|
||||||
ENV GIT_VERSION 2.20.1
|
|
||||||
ENV GIT_DOWNLOAD_URL https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/MinGit-${GIT_VERSION}-busybox-64-bit.zip
|
|
||||||
ENV GIT_SHA256 9817ab455d9cbd0b09d8664b4afbe4bbf78d18b556b3541d09238501a749486c
|
|
||||||
|
|
||||||
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
|
|
||||||
Invoke-WebRequest -UseBasicParsing $env:GIT_DOWNLOAD_URL -OutFile git.zip; `
|
|
||||||
if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_SHA256) {exit 1} ; `
|
|
||||||
Expand-Archive git.zip -DestinationPath C:\git; `
|
|
||||||
Remove-Item git.zip
|
|
||||||
|
|
||||||
FROM $target as baseimage
|
|
||||||
|
|
||||||
ENV NPM_CONFIG_LOGLEVEL info
|
|
||||||
|
|
||||||
COPY --from=download /nodejs /nodejs
|
|
||||||
COPY --from=download [ "/Program Files (x86)/yarn", "/yarn" ]
|
|
||||||
COPY --from=download /git /git
|
|
||||||
|
|
||||||
ARG SETX=/M
|
|
||||||
RUN setx %SETX% PATH "%PATH%;C:\nodejs;C:\yarn\bin;C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin"
|
|
||||||
|
|
||||||
CMD [ "node.exe" ]
|
|
||||||
|
|
||||||
FROM baseimage
|
|
||||||
|
|
||||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
|
||||||
|
|
||||||
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe; `
|
|
||||||
Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait; `
|
|
||||||
Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz; `
|
|
||||||
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait; `
|
|
||||||
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait; `
|
|
||||||
Remove-Item msys2.tar.xz; `
|
|
||||||
Remove-Item msys2.tar; `
|
|
||||||
Remove-Item 7z.exe; `
|
|
||||||
Remove-Item -Recurse 7zip; `
|
|
||||||
[Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine); `
|
|
||||||
[Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine)
|
|
||||||
|
|
||||||
# Install VS Build Tools
|
|
||||||
RUN Invoke-WebRequest -UseBasicParsing https://download.visualstudio.microsoft.com/download/pr/df649173-11e9-4af2-8eb7-0eb02ba8958a/cadb5bdac41e55bb8f6a6b7c45273370/vs_buildtools.exe -OutFile vs_BuildTools.exe; `
|
|
||||||
# Installer won't detect DOTNET_SKIP_FIRST_TIME_EXPERIENCE if ENV is used, must use setx /M
|
|
||||||
setx /M DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1; `
|
|
||||||
Start-Process vs_BuildTools.exe `
|
|
||||||
-ArgumentList `
|
|
||||||
'--add', 'Microsoft.VisualStudio.Workload.VCTools', `
|
|
||||||
'--add', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', `
|
|
||||||
'--add', 'Microsoft.Component.VC.Runtime.UCRTSDK', `
|
|
||||||
'--add', 'Microsoft.VisualStudio.Component.Windows10SDK.17763', `
|
|
||||||
'--quiet', '--norestart', '--nocache' `
|
|
||||||
-NoNewWindow -Wait; `
|
|
||||||
Remove-Item -Force vs_buildtools.exe; `
|
|
||||||
Remove-Item -Force -Recurse \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\"; `
|
|
||||||
Remove-Item -Force -Recurse ${Env:TEMP}\*; `
|
|
||||||
Remove-Item -Force -Recurse \"${Env:ProgramData}\Package Cache\"; `
|
|
||||||
[Environment]::SetEnvironmentVariable('BAZEL_VC', \"${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\", [System.EnvironmentVariableTarget]::Machine)
|
|
||||||
|
|
||||||
# Install Python
|
|
||||||
RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile python-3.5.1.exe; `
|
|
||||||
Start-Process python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait; `
|
|
||||||
Remove-Item -Force python-3.5.1.exe
|
|
||||||
|
|
||||||
CMD ["cmd.exe"]
|
|
@ -1,33 +0,0 @@
|
|||||||
# CodeFresh configuration
|
|
||||||
|
|
||||||
[](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
|
|
||||||
|
|
||||||
This folder contains configuration for the [CodeFresh](<https://codefresh.io/>) based CI checks for this repository.
|
|
||||||
|
|
||||||
## The build pipeline
|
|
||||||
|
|
||||||
CodeFresh uses a several pipeline for each repository. The `codefresh.yml` file defines pipeline [build steps](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for this repository.
|
|
||||||
|
|
||||||
Run results can be seen in the GitHub checks interface and in the [public pipeline](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
|
|
||||||
|
|
||||||
Although most configuration is done via `pipeline.yml`, some options are only available in the online [pipeline settings](https://g.codefresh.io/pipelines/angular/services?repoOwner=angular&repoName=angular&project=angular%2Fangular&context=github&serviceName=angular%2Fangular), which needs a login to access.
|
|
||||||
|
|
||||||
|
|
||||||
## Caretaker
|
|
||||||
|
|
||||||
CodeFresh status can be found at <http://status.codefresh.io/>.
|
|
||||||
|
|
||||||
Issues related to the CodeFresh setup should be escalated to the Tools Team via the current caretaker, followed by Alex Eagle and Filipe Silva.
|
|
||||||
|
|
||||||
## Rollout strategy
|
|
||||||
|
|
||||||
Currently it is only used for tests on Windows platforms, on the master branch, and without pushing user-facing reports. It's only possible to see current builds in the [public pipeline dashboard](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular).
|
|
||||||
|
|
||||||
After a week or two of running like this, we should reassess how stable and reliable it is.
|
|
||||||
|
|
||||||
Next steps include:
|
|
||||||
- building PRs
|
|
||||||
- showing build status publicly
|
|
||||||
- blocking PRs that break the build
|
|
||||||
- expanding the test suite
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
# 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
|
|
||||||
|
|
||||||
# Save built files and downloaded repositories in a location that can be cached by CodeFresh and
|
|
||||||
# shared between builds. This helps speed up the analysis time significantly with Bazel managed node
|
|
||||||
# dependencies on the CI.
|
|
||||||
# https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/#caching-the-artifacts-of-your-build-system
|
|
||||||
build --repository_cache=C:/codefresh/volume/bazel_repository_cache
|
|
||||||
# Setting the output_base to a Docker volume is currently broken because of a Docker bug on Windows:
|
|
||||||
# https://github.com/moby/moby/issues/37024
|
|
||||||
# This affects Bazel because bazel_output_base\external\bazel_tools is an absolute path junction.
|
|
||||||
# When its fixed we can uncomment this line, and use a different output_base for Ivy tests (they
|
|
||||||
# use a separate compiler and destructively replace the cache).
|
|
||||||
# startup --output_base=C:/codefresh/volume/bazel_output_base
|
|
||||||
|
|
||||||
# Don't be spammy in the logs
|
|
||||||
# TODO(gmagolan): Hide progress again once build performance improves
|
|
||||||
# Presently, CircleCI can timeout during bazel test ... with the following
|
|
||||||
# error: Too long with no output (exceeded 10m0s)
|
|
||||||
build --noshow_progress
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# 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 CodeFresh VMs
|
|
||||||
# TODO(filipesilva): determine the correct memory limit
|
|
||||||
build --local_resources=10240,8.0,1.0
|
|
||||||
|
|
||||||
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
|
||||||
test --flaky_test_attempts=2
|
|
||||||
|
|
||||||
# More details on failures
|
|
||||||
build --verbose_failures=true
|
|
@ -1,28 +0,0 @@
|
|||||||
version: '1.0'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
BuildImage:
|
|
||||||
title: Build Docker image
|
|
||||||
type: build
|
|
||||||
image_name: node-bazel-windows
|
|
||||||
working_directory: ./.codefresh
|
|
||||||
no_cf_cache: true
|
|
||||||
build_arguments:
|
|
||||||
- node_version=10.13.0
|
|
||||||
- yarn_version=1.13.0
|
|
||||||
dockerfile: ./Dockerfile.win-1809
|
|
||||||
|
|
||||||
RunTests:
|
|
||||||
title: Run Bazel tests
|
|
||||||
image: ${{BuildImage}}
|
|
||||||
commands:
|
|
||||||
# Install dependencies
|
|
||||||
- yarn install --frozen-lockfile --non-interactive --network-timeout 100000 --no-progress
|
|
||||||
# Add Bazel CI config
|
|
||||||
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
|
||||||
# Run tests
|
|
||||||
# At the moment 'browser:chromium-local' are broken in CI while locally they work
|
|
||||||
# VE
|
|
||||||
- yarn bazel test --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-browser:chromium-local //...
|
|
||||||
# Ivy
|
|
||||||
- yarn bazel test --define=compile=aot --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot --test_tag_filters=-no-ivy-aot,-fixme-ivy-aot,-browser:chromium-local //...
|
|
@ -1,22 +0,0 @@
|
|||||||
# Image metadata and config.
|
|
||||||
FROM circleci/node:10-browsers
|
|
||||||
|
|
||||||
LABEL name="Angular dev environment" \
|
|
||||||
description="This image can be used to create a dev environment for building Angular." \
|
|
||||||
vendor="angular" \
|
|
||||||
version="1.0"
|
|
||||||
|
|
||||||
EXPOSE 4000 4200 4433 5000 8080 9876
|
|
||||||
|
|
||||||
|
|
||||||
# Switch to `root` (CircleCI images use `circleci` as the user).
|
|
||||||
USER root
|
|
||||||
|
|
||||||
|
|
||||||
# Configure `Node.js`/`npm` and install utilities.
|
|
||||||
RUN npm config --global set user root
|
|
||||||
RUN npm install --global yarn@1.13.0 # This needs to be in sync with what we use on CI.
|
|
||||||
|
|
||||||
|
|
||||||
# Go! (And keep going.)
|
|
||||||
CMD ["tail", "--follow", "/dev/null"]
|
|
@ -1,16 +0,0 @@
|
|||||||
// Reference: https://code.visualstudio.com/docs/remote/containers#_devcontainerjson-reference
|
|
||||||
{
|
|
||||||
"name": "Angular dev container",
|
|
||||||
"dockerFile": "Dockerfile",
|
|
||||||
"appPort": [4000, 4200, 4433, 5000, 8080, 9876],
|
|
||||||
"postCreateCommand": "yarn install",
|
|
||||||
"extensions": [
|
|
||||||
"devondcarew.bazel-code",
|
|
||||||
"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",
|
|
||||||
],
|
|
||||||
}
|
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -5,8 +5,5 @@
|
|||||||
*.js eol=lf
|
*.js eol=lf
|
||||||
*.ts eol=lf
|
*.ts eol=lf
|
||||||
|
|
||||||
# API guardian patch must always use LF for tests to work
|
|
||||||
*.patch eol=lf
|
|
||||||
|
|
||||||
# Must keep Windows line ending to be parsed correctly
|
# Must keep Windows line ending to be parsed correctly
|
||||||
scripts/windows/packages.txt eol=crlf
|
scripts/windows/packages.txt eol=crlf
|
||||||
|
187
.github/CODEOWNERS
vendored
187
.github/CODEOWNERS
vendored
@ -39,14 +39,12 @@
|
|||||||
# (just to make this file easier to understand)
|
# (just to make this file easier to understand)
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
# alan-agius4 - Alan Agius
|
|
||||||
# alexeagle - Alex Eagle
|
# alexeagle - Alex Eagle
|
||||||
# alxhub - Alex Rickabaugh
|
# alxhub - Alex Rickabaugh
|
||||||
# AndrewKushnir - Andrew Kushnir
|
# AndrewKushnir - Andrew Kushnir
|
||||||
# andrewseguin - Andrew Seguin
|
# andrewseguin - Andrew Seguin
|
||||||
# benlesh - Ben Lesh
|
# benlesh - Ben Lesh
|
||||||
# brandonroberts - Brandon Roberts
|
# brandonroberts - Brandon Roberts
|
||||||
# devversion - Paul Gschwendtner
|
|
||||||
# filipesilva - Filipe Silva
|
# filipesilva - Filipe Silva
|
||||||
# gkalpak - George Kalpakas
|
# gkalpak - George Kalpakas
|
||||||
# hansl - Hans Larsen
|
# hansl - Hans Larsen
|
||||||
@ -88,7 +86,6 @@
|
|||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - kara
|
# - kara
|
||||||
# - mhevery
|
# - mhevery
|
||||||
# - alexeagle
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -179,7 +176,6 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - kara
|
# - kara
|
||||||
# - jasonaden
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -219,7 +215,6 @@
|
|||||||
#
|
#
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
# - jasonaden
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -277,7 +272,6 @@
|
|||||||
# @angular/fw-docs-intro
|
# @angular/fw-docs-intro
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - jenniferfell
|
|
||||||
# - brandonroberts
|
# - brandonroberts
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - stephenfluin
|
# - stephenfluin
|
||||||
@ -299,29 +293,6 @@
|
|||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
|
||||||
# @angular/tools-docs-libraries
|
|
||||||
# ===========================================================
|
|
||||||
#
|
|
||||||
# - alan-agius4
|
|
||||||
# - alexeagle
|
|
||||||
# - hansl
|
|
||||||
# - IgorMinar
|
|
||||||
# - mgechev
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
|
||||||
# @angular/tools-docs-schematics
|
|
||||||
# ===========================================================
|
|
||||||
#
|
|
||||||
# - alan-agius4
|
|
||||||
# - alexeagle
|
|
||||||
# - hansl
|
|
||||||
# - IgorMinar
|
|
||||||
# - mgechev
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
# @angular/fw-docs-marketing
|
# @angular/fw-docs-marketing
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -342,9 +313,6 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
# - alexeagle
|
||||||
# - devversion
|
|
||||||
# - filipesilva
|
|
||||||
# - gkalpak
|
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
|
||||||
|
|
||||||
@ -379,19 +347,10 @@
|
|||||||
|
|
||||||
/packages/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-browser/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-browser/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/complex-animation-sequences.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/reusable-animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/route-animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/transition-and-triggers.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -414,22 +373,20 @@
|
|||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# packages/compiler-cli/ngcc/
|
# packages/compiler-cli/src/ngcc/
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/compiler-cli/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers
|
/packages/compiler-cli/src/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Framework/cli integration
|
# @angular/compiler-cli/ngtools
|
||||||
#
|
#
|
||||||
# a rule to control API changes between @angular/compiler-cli and @angular/cli
|
# a rule to control API changes between @angular/compiler-cli and @angular/cli
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
||||||
/aio/content/guide/ivy.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/web-worker.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -448,15 +405,6 @@
|
|||||||
/packages/platform-browser-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-browser-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/examples/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/architecture-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/architecture-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/architecture-next-steps.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/architecture-services.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/architecture.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/architecture/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/architecture/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/attribute-directives.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/attribute-directives.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -465,8 +413,6 @@
|
|||||||
/aio/content/guide/bootstrapping.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/bootstrapping.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/bootstrapping/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/bootstrapping/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/cheatsheet.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/component-interaction.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/component-interaction.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -482,13 +428,7 @@
|
|||||||
/aio/content/examples/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/dependency-injection-navtree.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/dependency-injection-pattern.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/dependency-injection-providers.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/displaying-data.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/displaying-data/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/displaying-data/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/dynamic-component-loader.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/dynamic-component-loader.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -515,9 +455,12 @@
|
|||||||
/aio/content/images/guide/lifecycle-hooks/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/lifecycle-hooks/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/examples/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/ngmodule/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/ngmodule/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/ngmodule-api.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ngmodule-api.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
@ -529,20 +472,8 @@
|
|||||||
/aio/content/guide/module-types.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/module-types.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/template-syntax.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/template-syntax.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/built-in-template-functions/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/event-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/interpolation/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/binding-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/property-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/attribute-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/two-way-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/built-in-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/template-reference-variables/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/inputs-outputs/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/template-expression-operators/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -563,10 +494,6 @@
|
|||||||
/aio/content/examples/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/user-input.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/user-input/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/user-input/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -592,7 +519,6 @@
|
|||||||
/aio/content/guide/elements.md @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/elements.md @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# @angular/forms
|
# @angular/forms
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -654,7 +580,6 @@
|
|||||||
/packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/service-worker-getting-started.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/service-worker-getting-started.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/service-worker-getting-started/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/service-worker-getting-started/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/app-shell.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/service-worker-communications.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/service-worker-communications.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/service-worker-config.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/service-worker-config.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/service-worker-devops.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/service-worker-devops.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -668,10 +593,8 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/common/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/packages/examples/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/examples/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/upgrade.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/upgrade.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/upgrade-lazy-load-ajs/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/upgrade-module/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/upgrade-module/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/upgrade-phonecat-1-typescript/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/upgrade-phonecat-1-typescript/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -726,7 +649,6 @@ testing/** @angular/fw-test
|
|||||||
/packages/platform-browser/src/security/** @angular/fw-security
|
/packages/platform-browser/src/security/** @angular/fw-security
|
||||||
/aio/content/guide/security.md @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/security.md @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -752,20 +674,11 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
/aio/* @angular/docs-infra @angular/framework-global-approvers
|
/aio/* @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/aio-builds-setup/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/aio-builds-setup/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/content/examples/* @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/scripts/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/scripts/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/src/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/src/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/tests/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/tests/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
|
||||||
# Hidden docs
|
|
||||||
/aio/content/guide/change-log.md @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/content/guide/docs-style-guide.md @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/content/examples/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/content/images/guide/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/content/guide/visual-studio-2015.md @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
/aio/content/examples/visual-studio-2015/** @angular/docs-infra @angular/framework-global-approvers
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -773,36 +686,25 @@ testing/** @angular/fw-test
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/toh/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt1/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt2/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt3/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt4/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt5/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/toh-pt6/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/getting-started-v0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/getting-started/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Docs: observables
|
# Docs: observables
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/guide/observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/comparing-observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/comparing-observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/observables-in-angular.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/observables-in-angular.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/practical-observable-usage/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/practical-observable-usage/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/rx-library.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/rx-library/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/rx-library/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/rx-library.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -813,37 +715,12 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/setup-systemjs-anatomy.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/build.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/build/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/file-structure.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/workspace-config.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/deprecations.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
|
||||||
# Docs: libraries
|
|
||||||
# ================================================
|
|
||||||
|
|
||||||
/aio/content/guide/creating-libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/using-libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
|
||||||
# Docs: schematics
|
|
||||||
# ================================================
|
|
||||||
|
|
||||||
/aio/content/guide/schematics.md @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/schematics-authoring.md @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/schematics-for-libraries.md @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/schematics/** @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/examples/schematics-for-libraries/** @angular/tools-docs-schematics @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -852,7 +729,6 @@ testing/** @angular/fw-test
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/bios/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/navigation.json @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/navigation.json @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/license.md @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/license.md @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -866,51 +742,20 @@ testing/** @angular/fw-test
|
|||||||
/* @angular/fw-dev-infra
|
/* @angular/fw-dev-infra
|
||||||
/.buildkite/** @angular/fw-dev-infra
|
/.buildkite/** @angular/fw-dev-infra
|
||||||
/.circleci/** @angular/fw-dev-infra
|
/.circleci/** @angular/fw-dev-infra
|
||||||
/.codefresh/** @angular/fw-dev-infra
|
|
||||||
/.devcontainer/** @angular/fw-dev-infra
|
|
||||||
/.github/** @angular/fw-dev-infra
|
/.github/** @angular/fw-dev-infra
|
||||||
/.vscode/** @angular/fw-dev-infra
|
|
||||||
/docs/BAZEL.md @angular/fw-dev-infra
|
/docs/BAZEL.md @angular/fw-dev-infra
|
||||||
/packages/* @angular/fw-dev-infra
|
|
||||||
/scripts/** @angular/fw-dev-infra
|
/scripts/** @angular/fw-dev-infra
|
||||||
/third_party/** @angular/fw-dev-infra
|
/third_party/** @angular/fw-dev-infra
|
||||||
/tools/build/** @angular/fw-dev-infra
|
/tools/** @angular/fw-dev-infra
|
||||||
/tools/cjs-jasmine/** @angular/fw-dev-infra
|
|
||||||
/tools/gulp-tasks/** @angular/fw-dev-infra
|
|
||||||
/tools/ngcontainer/** @angular/fw-dev-infra
|
|
||||||
/tools/npm/** @angular/fw-dev-infra
|
|
||||||
/tools/npm_workspace/** @angular/fw-dev-infra
|
|
||||||
/tools/public_api_guard/** @angular/fw-dev-infra
|
|
||||||
/tools/rxjs/** @angular/fw-dev-infra
|
|
||||||
/tools/source-map-test/** @angular/fw-dev-infra
|
|
||||||
/tools/symbol-extractor/** @angular/fw-dev-infra
|
|
||||||
/tools/testing/** @angular/fw-dev-infra
|
|
||||||
/tools/ts-api-guardian/** @angular/fw-dev-infra
|
|
||||||
/tools/tslint/** @angular/fw-dev-infra
|
|
||||||
/tools/validate-commit-message/** @angular/fw-dev-infra
|
|
||||||
/tools/yarn/** @angular/fw-dev-infra
|
|
||||||
/tools/*
|
|
||||||
*.bzl @angular/fw-dev-infra
|
*.bzl @angular/fw-dev-infra
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
|
||||||
# Material CI
|
|
||||||
# ================================================
|
|
||||||
|
|
||||||
/tools/material-ci/** @angular/fw-core @angular/framework-global-approvers
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Public API
|
# Public API
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/tools/public_api_guard/** @angular/fw-public-api
|
/tools/public_api_guard/** @angular/fw-public-api
|
||||||
/aio/content/guide/glossary.md @angular/fw-public-api
|
|
||||||
/aio/content/guide/styleguide.md @angular/fw-public-api
|
|
||||||
/aio/content/examples/styleguide/** @angular/fw-public-api
|
|
||||||
/aio/content/images/guide/styleguide/** @angular/fw-public-api
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
4
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -37,9 +37,7 @@ Please create and share minimal reproduction of the issue starting with this tem
|
|||||||
<!-- ✍️--> https://stackblitz.com/...
|
<!-- ✍️--> https://stackblitz.com/...
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
|
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue. Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
||||||
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
|
|
||||||
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
|
||||||
|
|
||||||
Issues that don't have enough info and can't be reproduced will be closed.
|
Issues that don't have enough info and can't be reproduced will be closed.
|
||||||
|
|
||||||
|
20
.github/angular-robot.yml
vendored
20
.github/angular-robot.yml
vendored
@ -35,19 +35,17 @@ merge:
|
|||||||
# this list must be manually kept in sync with google3/third_party/javascript/angular2/copy.bara.sky
|
# this list must be manually kept in sync with google3/third_party/javascript/angular2/copy.bara.sky
|
||||||
include:
|
include:
|
||||||
- "LICENSE"
|
- "LICENSE"
|
||||||
- "modules/benchmarks/**"
|
- "modules/**"
|
||||||
- "modules/system.d.ts"
|
|
||||||
- "packages/**"
|
- "packages/**"
|
||||||
# list of patterns to ignore for the files changed by the PR
|
# list of patterns to ignore for the files changed by the PR
|
||||||
exclude:
|
exclude:
|
||||||
- "packages/*"
|
- "packages/*"
|
||||||
- "packages/bazel/*"
|
- "packages/bazel/*"
|
||||||
- "packages/bazel/src/api-extractor/**"
|
|
||||||
- "packages/bazel/src/builders/**"
|
- "packages/bazel/src/builders/**"
|
||||||
- "packages/bazel/src/ng_package/**"
|
- "packages/bazel/src/ng_package/**"
|
||||||
- "packages/bazel/src/protractor/**"
|
- "packages/bazel/src/protractor/**"
|
||||||
- "packages/bazel/src/schematics/**"
|
- "packages/bazel/src/schematics/**"
|
||||||
- "packages/compiler-cli/ngcc/**"
|
- "packages/compiler-cli/src/ngcc/**"
|
||||||
- "packages/docs/**"
|
- "packages/docs/**"
|
||||||
- "packages/elements/schematics/**"
|
- "packages/elements/schematics/**"
|
||||||
- "packages/examples/**"
|
- "packages/examples/**"
|
||||||
@ -58,9 +56,9 @@ merge:
|
|||||||
- "**/.gitkeep"
|
- "**/.gitkeep"
|
||||||
- "**/yarn.lock"
|
- "**/yarn.lock"
|
||||||
- "**/package.json"
|
- "**/package.json"
|
||||||
- "**/third_party/**"
|
|
||||||
- "**/tsconfig-build.json"
|
- "**/tsconfig-build.json"
|
||||||
- "**/tsconfig.json"
|
- "**/tsconfig.json"
|
||||||
|
- "**/rollup.config.js"
|
||||||
- "**/BUILD.bazel"
|
- "**/BUILD.bazel"
|
||||||
- "**/*.md"
|
- "**/*.md"
|
||||||
- "packages/**/integrationtest/**"
|
- "packages/**/integrationtest/**"
|
||||||
@ -105,11 +103,6 @@ merge:
|
|||||||
requiredStatuses:
|
requiredStatuses:
|
||||||
- "ci/circleci: build"
|
- "ci/circleci: build"
|
||||||
- "ci/circleci: lint"
|
- "ci/circleci: lint"
|
||||||
- "ci/circleci: publish_snapshot"
|
|
||||||
- "ci/angular: size"
|
|
||||||
- "cla/google"
|
|
||||||
- "google3"
|
|
||||||
|
|
||||||
|
|
||||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||||
@ -167,10 +160,3 @@ triagePR:
|
|||||||
- "effort*"
|
- "effort*"
|
||||||
- "risk*"
|
- "risk*"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
|
|
||||||
# options for rerunning CI
|
|
||||||
rerunCircleCI:
|
|
||||||
# set to true to disable
|
|
||||||
disabled: false
|
|
||||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
|
||||||
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
|
||||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,22 +1,19 @@
|
|||||||
.DS_STORE
|
.DS_STORE
|
||||||
|
|
||||||
/dist/
|
/dist/
|
||||||
/bazel-out
|
/bazel-out/
|
||||||
/integration/bazel/bazel-*
|
/integration/bazel/bazel-*
|
||||||
e2e_test.*
|
e2e_test.*
|
||||||
node_modules
|
node_modules
|
||||||
|
bower_components
|
||||||
tools/gulp-tasks/cldr/cldr-data/
|
tools/gulp-tasks/cldr/cldr-data/
|
||||||
|
|
||||||
# Include when developing application packages.
|
# Include when developing application packages.
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
.c9
|
.c9
|
||||||
.idea/
|
.idea/
|
||||||
.devcontainer/*
|
|
||||||
!.devcontainer/recommended-devcontainer.json
|
|
||||||
!.devcontainer/recommended-Dockerfile
|
|
||||||
.settings/
|
.settings/
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/settings.json
|
|
||||||
*.swo
|
*.swo
|
||||||
modules/.settings
|
modules/.settings
|
||||||
modules/.vscode
|
modules/.vscode
|
||||||
|
23
.vscode/README.md
vendored
23
.vscode/README.md
vendored
@ -1,23 +0,0 @@
|
|||||||
# VSCode Configuration
|
|
||||||
|
|
||||||
This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings) and [Extension Recommendations](https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions) that the Angular team recommends using when working on this repository.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
To use the recommended settings follow the steps below:
|
|
||||||
|
|
||||||
- install <https://marketplace.visualstudio.com/items?itemName=xaver.clang-format>
|
|
||||||
- copy `.vscode/recommended-settings.json` to `.vscode/settings.json`
|
|
||||||
- restart the editor
|
|
||||||
|
|
||||||
If you already have your custom workspace settings you should instead manually merge the file content.
|
|
||||||
|
|
||||||
This isn't an automatic process so you will need to repeat it when settings are updated.
|
|
||||||
|
|
||||||
To see the recommended extensions select "Extensions: Show Recommended Extensions" in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
|
||||||
|
|
||||||
## Editing `.vscode/recommended-settings.json`
|
|
||||||
|
|
||||||
If you wish to add extra configuration items please keep in mind any settings you add here will be used by many users.
|
|
||||||
|
|
||||||
Try to keep these settings to things that help facilitate the development process and avoid altering the user workflow whenever possible.
|
|
15
.vscode/extensions.json
vendored
15
.vscode/extensions.json
vendored
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
|
||||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
|
||||||
|
|
||||||
// List of extensions which should be recommended for users of this workspace.
|
|
||||||
"recommendations": [
|
|
||||||
"devondcarew.bazel-code",
|
|
||||||
"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",
|
|
||||||
],
|
|
||||||
}
|
|
31
.vscode/recommended-settings.json
vendored
31
.vscode/recommended-settings.json
vendored
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
// 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,
|
|
||||||
"**/.git/subtree-cache/**": true,
|
|
||||||
"**/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,
|
|
||||||
},
|
|
||||||
"git.ignoreLimitWarning": true,
|
|
||||||
}
|
|
15
.vscode/settings.json
vendored
Normal file
15
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"files.watcherExclude": {
|
||||||
|
"**/.git/objects/**": true,
|
||||||
|
"**/.git/subtree-cache/**": true,
|
||||||
|
"**/node_modules/**": true,
|
||||||
|
"**/bazel-out/**": true,
|
||||||
|
"**/dist/**": true,
|
||||||
|
},
|
||||||
|
"search.exclude": {
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/bower_components": true,
|
||||||
|
"**/bazel-out": true,
|
||||||
|
"**/dist": true,
|
||||||
|
},
|
||||||
|
}
|
99
BUILD.bazel
99
BUILD.bazel
@ -1,32 +1,22 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
load("//tools:defaults.bzl", "karma_web_test")
|
load("@build_bazel_rules_nodejs//:defs.bzl", "node_modules_filegroup")
|
||||||
|
|
||||||
exports_files([
|
exports_files([
|
||||||
|
"tsconfig.json",
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"protractor-perf.conf.js",
|
"protractor-perf.conf.js",
|
||||||
"karma-js.conf.js",
|
|
||||||
"browser-providers.conf.js",
|
|
||||||
])
|
])
|
||||||
|
|
||||||
alias(
|
|
||||||
name = "tsconfig.json",
|
|
||||||
actual = "//packages:tsconfig-build.json",
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "web_test_bootstrap_scripts",
|
name = "web_test_bootstrap_scripts",
|
||||||
# do not sort
|
# do not sort
|
||||||
srcs = [
|
srcs = [
|
||||||
"@npm//node_modules/core-js:client/core.js",
|
"@ngdeps//node_modules/reflect-metadata:Reflect.js",
|
||||||
"@npm//node_modules/zone.js:dist/zone.js",
|
"@ngdeps//node_modules/zone.js:dist/zone.js",
|
||||||
"@npm//node_modules/zone.js:dist/zone-testing.js",
|
"@ngdeps//node_modules/zone.js:dist/zone-testing.js",
|
||||||
"@npm//node_modules/zone.js:dist/task-tracking.js",
|
"@ngdeps//node_modules/zone.js:dist/task-tracking.js",
|
||||||
"//:test-events.js",
|
"//:test-events.js",
|
||||||
"//:shims_for_IE.js",
|
|
||||||
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
|
||||||
"@npm//node_modules/systemjs:dist/system.src.js",
|
|
||||||
"@npm//node_modules/reflect-metadata:Reflect.js",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,59 +25,32 @@ filegroup(
|
|||||||
srcs = [
|
srcs = [
|
||||||
# We also declare the unminfied AngularJS files since these can be used for
|
# We also declare the unminfied AngularJS files since these can be used for
|
||||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||||
"@npm//node_modules/angular:angular.js",
|
"@ngdeps//node_modules/angular:angular.js",
|
||||||
"@npm//node_modules/angular:angular.min.js",
|
"@ngdeps//node_modules/angular:angular.min.js",
|
||||||
"@npm//node_modules/angular-1.5:angular.js",
|
"@ngdeps//node_modules/angular-1.5:angular.js",
|
||||||
"@npm//node_modules/angular-1.5:angular.min.js",
|
"@ngdeps//node_modules/angular-1.5:angular.min.js",
|
||||||
"@npm//node_modules/angular-1.6:angular.js",
|
"@ngdeps//node_modules/angular-1.6:angular.js",
|
||||||
"@npm//node_modules/angular-1.6:angular.min.js",
|
"@ngdeps//node_modules/angular-1.6:angular.min.js",
|
||||||
"@npm//node_modules/angular-mocks:angular-mocks.js",
|
"@ngdeps//node_modules/angular-mocks:angular-mocks.js",
|
||||||
"@npm//node_modules/angular-mocks-1.5:angular-mocks.js",
|
"@ngdeps//node_modules/angular-mocks-1.5:angular-mocks.js",
|
||||||
"@npm//node_modules/angular-mocks-1.6:angular-mocks.js",
|
"@ngdeps//node_modules/angular-mocks-1.6:angular-mocks.js",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# To run a karma_web_test target locally on SauceLabs:
|
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||||
# 1) have SAUCE_USERNAME, SAUCE_ACCESS_KEY (and optionally a SAUCE_TUNNEL_IDENTIFIER) set in your environment
|
|
||||||
# 2) open a sauce connection with `./scripts/saucelabs/start-tunnel.sh`
|
# A nodejs_binary for @angular/bazel/ngc-wrapped to use by default in
|
||||||
# NOTE: start-tunnel.sh uses `node_modules/sauce-connect` which is current linux specific:
|
# ng_module that depends on @npm//@angular/bazel instead of the
|
||||||
# "sauce-connect": "https://saucelabs.com/downloads/sc-4.5.3-linux.tar.gz".
|
# output of the //packages/bazel/src/ngc-wrapped ts_library rule. This
|
||||||
# On OSX or Windows you'll need to use the appropriate sauce-connect binary.
|
# default is for downstream users that depend on the @angular/bazel npm
|
||||||
# 3) run target with `yarn bazel test --config=saucelabs <target>`
|
# package. The generated @npm//@angular/bazel/ngc-wrapped target
|
||||||
# NOTE: --config=saucelabs is required as it makes the SAUCE_XXX environment variables available to
|
# does not work because it does not have the node `--expose-gc` flag
|
||||||
# the action. See /.bazelrc.
|
# set which is required to support the call to `global.gc()`.
|
||||||
karma_web_test(
|
nodejs_binary(
|
||||||
name = "test_web_all",
|
name = "@angular/bazel/ngc-wrapped",
|
||||||
tags = [
|
configuration_env_vars = ["compile"],
|
||||||
"local",
|
data = ["@npm//@angular/bazel"],
|
||||||
"manual",
|
entry_point = "@angular/bazel/src/ngc-wrapped/index.js",
|
||||||
"saucelabs",
|
install_source_map_support = False,
|
||||||
],
|
templated_args = ["--node_options=--expose-gc"],
|
||||||
deps = [
|
|
||||||
# We combine all tests into a single karma_web_test target
|
|
||||||
# as running them as seperate targets in parallel leads to too many
|
|
||||||
# browsers being acquired at once in SauceLabs and the tests flake out
|
|
||||||
# TODO: this is an example subset of tests below, add all remaining angular tests
|
|
||||||
"//packages/common/http/test:test_lib",
|
|
||||||
"//packages/common/http/testing/test:test_lib",
|
|
||||||
"//packages/common/test:test_lib",
|
|
||||||
"//packages/core/test:test_lib",
|
|
||||||
"//packages/forms/test:test_lib",
|
|
||||||
"//packages/http/test:test_lib",
|
|
||||||
"//packages/zone.js/test:karma_jasmine_test_ci",
|
|
||||||
# "//packages/router/test:test_lib",
|
|
||||||
# //packages/router/test:test_lib fails with:
|
|
||||||
# IE 11.0.0 (Windows 8.1.0.0) bootstrap should restore the scrolling position FAILED
|
|
||||||
# Expected undefined to equal 5000.
|
|
||||||
# at stack (eval code:2338:11)
|
|
||||||
# at buildExpectationResult (eval code:2305:5)
|
|
||||||
# at expectationResultFactory (eval code:858:11)
|
|
||||||
# at Spec.prototype.addExpectationResult (eval code:487:5)
|
|
||||||
# at addExpectationResult (eval code:802:9)
|
|
||||||
# at Anonymous function (eval code:2252:7)
|
|
||||||
# at Anonymous function (eval code:339:25)
|
|
||||||
# at step (eval code:133:17)
|
|
||||||
# at Anonymous function (eval code:114:50)
|
|
||||||
# at fulfilled (eval code:104:47)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
998
CHANGELOG.md
998
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
[](https://circleci.com/gh/angular/angular/tree/master)
|
||||||
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
||||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://www.npmjs.com/@angular/core)
|
[](https://www.npmjs.com/@angular/core)
|
||||||
@ -23,6 +23,6 @@ guidelines for [contributing][contributing] and then check out one of our issues
|
|||||||
|
|
||||||
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
|
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
|
||||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||||
[quickstart]: https://angular.io/start
|
[quickstart]: https://angular.io/guide/quickstart
|
||||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||||
[ng]: https://angular.io
|
[ng]: https://angular.io
|
||||||
|
173
WORKSPACE
173
WORKSPACE
@ -1,9 +1,17 @@
|
|||||||
workspace(
|
workspace(name = "angular")
|
||||||
name = "angular",
|
|
||||||
managed_directories = {"@npm": ["node_modules"]},
|
|
||||||
)
|
|
||||||
|
|
||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
load(
|
||||||
|
"//packages/bazel:package.bzl",
|
||||||
|
"rules_angular_dependencies",
|
||||||
|
"rules_angular_dev_dependencies",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "io_bazel_rules_go",
|
||||||
|
sha256 = "b7a62250a3a73277ade0ce306d22f122365b513f5402222403e507f2f997d421",
|
||||||
|
url = "https://github.com/bazelbuild/rules_go/releases/download/0.16.3/rules_go-0.16.3.tar.gz",
|
||||||
|
)
|
||||||
|
|
||||||
# Uncomment for local bazel rules development
|
# Uncomment for local bazel rules development
|
||||||
#local_repository(
|
#local_repository(
|
||||||
@ -11,138 +19,101 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|||||||
# path = "../rules_nodejs",
|
# path = "../rules_nodejs",
|
||||||
#)
|
#)
|
||||||
#local_repository(
|
#local_repository(
|
||||||
# name = "npm_bazel_typescript",
|
# name = "build_bazel_rules_typescript",
|
||||||
# path = "../rules_typescript",
|
# path = "../rules_typescript",
|
||||||
#)
|
#)
|
||||||
|
|
||||||
# Fetch rules_nodejs so we can install our npm dependencies
|
# Angular Bazel users will call this function
|
||||||
|
rules_angular_dependencies()
|
||||||
|
|
||||||
|
# Install transitive deps of rules_nodejs
|
||||||
|
load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
|
||||||
|
|
||||||
|
rules_nodejs_dependencies()
|
||||||
|
|
||||||
|
# These are the dependencies only for us
|
||||||
|
rules_angular_dev_dependencies()
|
||||||
|
|
||||||
|
# Install transitive deps of rules_typescript
|
||||||
|
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
|
||||||
|
|
||||||
|
rules_typescript_dependencies()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Point Bazel to WORKSPACEs that live in subdirectories
|
||||||
|
#
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "rxjs",
|
||||||
sha256 = "e04a82a72146bfbca2d0575947daa60fda1878c8d3a3afe868a8ec39a6b968bb",
|
sha256 = "72b0b4e517f43358f554c125e40e39f67688cd2738a8998b4a266981ed32f403",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.31.1/rules_nodejs-0.31.1.tar.gz"],
|
strip_prefix = "package/src",
|
||||||
|
url = "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the bazel version and download npm dependencies
|
# Point to the integration test workspace just so that Bazel doesn't descend into it
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
# when expanding the //... pattern
|
||||||
|
local_repository(
|
||||||
|
name = "bazel_integration_test",
|
||||||
|
path = "integration/bazel",
|
||||||
|
)
|
||||||
|
|
||||||
# Bazel version must be at least the following version because:
|
#
|
||||||
# - 0.26.0 managed_directories feature added which is required for nodejs rules 0.30.0
|
# Load and install our dependencies downloaded above.
|
||||||
check_bazel_version(
|
#
|
||||||
message = """
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||||
|
|
||||||
|
# Bazel version must be at least v0.21.0 because:
|
||||||
|
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
|
||||||
|
# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
||||||
|
check_bazel_version("0.21.0", """
|
||||||
You no longer need to install Bazel on your machine.
|
You no longer need to install Bazel on your machine.
|
||||||
Angular has a dependency on the @bazel/bazel package which supplies it.
|
Angular has a dependency on the @bazel/bazel package which supplies it.
|
||||||
Try running `yarn bazel` instead.
|
Try running `yarn bazel` instead.
|
||||||
(If you did run that, check that you've got a fresh `yarn install`)
|
(If you did run that, check that you've got a fresh `yarn install`)
|
||||||
|
|
||||||
""",
|
""")
|
||||||
minimum_bazel_version = "0.26.0",
|
|
||||||
)
|
|
||||||
|
|
||||||
# The NodeJS rules version must be at least the following version because:
|
|
||||||
# - 0.15.2 Re-introduced the prod_only attribute on yarn_install
|
|
||||||
# - 0.15.3 Includes a fix for the `jasmine_node_test` rule ignoring target tags
|
|
||||||
# - 0.16.8 Supports npm installed bazel workspaces
|
|
||||||
# - 0.26.0 Fix for data files in yarn_install and npm_install
|
|
||||||
# - 0.27.12 Adds NodeModuleSources provider for transtive npm deps support
|
|
||||||
# - 0.30.0 yarn_install now uses symlinked node_modules with new managed directories Bazel 0.26.0 feature
|
|
||||||
# - 0.31.1 entry_point attribute of nodejs_binary & rollup_bundle is now a label
|
|
||||||
check_rules_nodejs_version(minimum_version_string = "0.31.1")
|
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
|
||||||
node_repositories(
|
node_repositories(
|
||||||
node_repositories = {
|
node_version = "10.9.0",
|
||||||
"10.16.0-darwin_amd64": ("node-v10.16.0-darwin-x64.tar.gz", "node-v10.16.0-darwin-x64", "6c009df1b724026d84ae9a838c5b382662e30f6c5563a0995532f2bece39fa9c"),
|
|
||||||
"10.16.0-linux_amd64": ("node-v10.16.0-linux-x64.tar.xz", "node-v10.16.0-linux-x64", "1827f5b99084740234de0c506f4dd2202a696ed60f76059696747c34339b9d48"),
|
|
||||||
"10.16.0-windows_amd64": ("node-v10.16.0-win-x64.zip", "node-v10.16.0-win-x64", "aa22cb357f0fb54ccbc06b19b60e37eefea5d7dd9940912675d3ed988bf9a059"),
|
|
||||||
},
|
|
||||||
node_version = "10.16.0",
|
|
||||||
package_json = ["//:package.json"],
|
package_json = ["//:package.json"],
|
||||||
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
|
preserve_symlinks = True,
|
||||||
# ```
|
|
||||||
# ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty)
|
|
||||||
# ```
|
|
||||||
# See https://github.com/angular/angular/pull/29431 for more information.
|
|
||||||
# It possible that versions of yarn past 1.13.0 do not have this issue, however, before
|
|
||||||
# advancing this version we need to test manually on Windows that the above error does not
|
|
||||||
# happen as the issue is not caught by CI.
|
|
||||||
yarn_version = "1.12.1",
|
yarn_version = "1.12.1",
|
||||||
)
|
)
|
||||||
|
|
||||||
yarn_install(
|
local_repository(
|
||||||
name = "npm",
|
name = "npm",
|
||||||
data = [
|
path = "tools/npm_workspace",
|
||||||
"//:tools/npm/@angular_bazel/index.js",
|
|
||||||
"//:tools/npm/@angular_bazel/package.json",
|
|
||||||
"//:tools/postinstall-patches.js",
|
|
||||||
"//:tools/yarn/check-yarn.js",
|
|
||||||
],
|
|
||||||
package_json = "//:package.json",
|
|
||||||
# Don't install devDependencies, they are large and not used under Bazel
|
|
||||||
prod_only = True,
|
|
||||||
# Temporarily disable node_modules symlinking until the fix for
|
|
||||||
# https://github.com/bazelbuild/bazel/issues/8487 makes it into a
|
|
||||||
# future Bazel release
|
|
||||||
symlink_node_modules = False,
|
|
||||||
yarn_lock = "//:yarn.lock",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install all bazel dependencies of the @npm npm packages
|
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||||
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
|
||||||
|
|
||||||
install_bazel_dependencies()
|
go_rules_dependencies()
|
||||||
|
|
||||||
# Load angular dependencies
|
go_register_toolchains()
|
||||||
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
|
||||||
|
|
||||||
rules_angular_dev_dependencies()
|
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||||
|
|
||||||
# Load karma dependencies
|
|
||||||
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
|
||||||
|
|
||||||
rules_karma_dependencies()
|
|
||||||
|
|
||||||
# Setup the rules_webtesting toolchain
|
|
||||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
|
|
||||||
|
|
||||||
web_test_repositories()
|
web_test_repositories()
|
||||||
|
|
||||||
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
browser_repositories(
|
||||||
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
chromium = True,
|
||||||
load("//:browser_repositories.bzl", "browser_repositories")
|
firefox = True,
|
||||||
|
)
|
||||||
|
|
||||||
browser_repositories()
|
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||||
|
|
||||||
# Setup the rules_typescript tooolchain
|
|
||||||
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
|
||||||
|
|
||||||
ts_setup_workspace()
|
ts_setup_workspace()
|
||||||
|
|
||||||
# Setup the rules_sass toolchain
|
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||||
|
|
||||||
|
ng_setup_workspace()
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# Skylark documentation generation
|
||||||
|
|
||||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||||
|
|
||||||
sass_repositories()
|
sass_repositories()
|
||||||
|
|
||||||
# Setup the skydoc toolchain
|
|
||||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||||
|
|
||||||
skydoc_repositories()
|
skydoc_repositories()
|
||||||
|
|
||||||
load("@bazel_toolchains//rules:environments.bzl", "clang_env")
|
|
||||||
load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
|
|
||||||
|
|
||||||
rbe_autoconfig(
|
|
||||||
name = "rbe_ubuntu1604_angular",
|
|
||||||
# The sha256 of marketplace.gcr.io/google/rbe-ubuntu16-04 container that is
|
|
||||||
# used by rbe_autoconfig() to pair toolchain configs in the @bazel_toolchains repo.
|
|
||||||
base_container_digest = "sha256:677c1317f14c6fd5eba2fd8ec645bfdc5119f64b3e5e944e13c89e0525cc8ad1",
|
|
||||||
# Note that if you change the `digest`, you might also need to update the
|
|
||||||
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
|
||||||
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
|
||||||
# the same Clang and JDK installed.
|
|
||||||
# Clang is needed because of the dependency on @com_google_protobuf.
|
|
||||||
# Java is needed for the Bazel's test executor Java tool.
|
|
||||||
digest = "sha256:74a8e9dca4781d5f277a7bd8e7ea7ed0f5906c79c9cd996205b6d32f090c62f3",
|
|
||||||
env = clang_env(),
|
|
||||||
registry = "marketplace.gcr.io",
|
|
||||||
repository = "google/rbe-ubuntu16-04-webtest",
|
|
||||||
)
|
|
||||||
|
2
aio/.gitignore
vendored
2
aio/.gitignore
vendored
@ -26,13 +26,11 @@
|
|||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
/.firebase/
|
|
||||||
/.sass-cache
|
/.sass-cache
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage
|
/coverage
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
debug.log
|
debug.log
|
||||||
firebase-debug.log
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
testem.log
|
testem.log
|
||||||
/typings
|
/typings
|
||||||
|
@ -41,6 +41,16 @@ Here are the most important tasks you might need to use:
|
|||||||
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
||||||
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
||||||
|
|
||||||
|
## Developing on Windows
|
||||||
|
The `packages/` directory may contain Linux-specific symlinks, which are not recognized by Windows.
|
||||||
|
These unresolved links cause the docs generation process to fail because it cannot locate certain files.
|
||||||
|
|
||||||
|
> Hint: The following steps require administration rights or [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) enabled!
|
||||||
|
|
||||||
|
To fix this problem, run `scripts/windows/create-symlinks.sh`. This command creates temporary files where the symlinks used to be. Make sure not to commit those files with your documentation changes.
|
||||||
|
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
|
||||||
|
|
||||||
|
It's necessary to remove the temporary files, because otherwise they're displayed as local changes in your git working copy and certain operations are blocked.
|
||||||
|
|
||||||
## Using ServiceWorker locally
|
## Using ServiceWorker locally
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Image metadata and config
|
# Image metadata and config
|
||||||
FROM debian:stretch
|
FROM debian:jessie
|
||||||
|
|
||||||
LABEL name="angular.io PR preview" \
|
LABEL name="angular.io PR preview" \
|
||||||
description="This image implements the PR preview functionality for angular.io." \
|
description="This image implements the PR preview functionality for angular.io." \
|
||||||
@ -26,8 +26,8 @@ ARG AIO_GITHUB_ORGANIZATION=angular
|
|||||||
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
||||||
ARG AIO_GITHUB_REPO=angular
|
ARG AIO_GITHUB_REPO=angular
|
||||||
ARG TEST_AIO_GITHUB_REPO=test-repo
|
ARG TEST_AIO_GITHUB_REPO=test-repo
|
||||||
ARG AIO_GITHUB_TEAM_SLUGS=aio-auto-previews,aio-contributors
|
ARG AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=test-team-1,test-team-2
|
ARG TEST_AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||||
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
||||||
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
||||||
ARG AIO_NGINX_PORT_HTTP=80
|
ARG AIO_NGINX_PORT_HTTP=80
|
||||||
@ -40,7 +40,7 @@ ARG AIO_TRUSTED_PR_LABEL="aio: preview"
|
|||||||
ARG TEST_AIO_TRUSTED_PR_LABEL="aio: preview"
|
ARG TEST_AIO_TRUSTED_PR_LABEL="aio: preview"
|
||||||
ARG AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
|
ARG AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
|
||||||
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
|
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
|
||||||
ARG AIO_ARTIFACT_MAX_SIZE=26214400
|
ARG AIO_ARTIFACT_MAX_SIZE=20971520
|
||||||
ARG TEST_AIO_ARTIFACT_MAX_SIZE=200
|
ARG TEST_AIO_ARTIFACT_MAX_SIZE=200
|
||||||
ARG AIO_PREVIEW_SERVER_PORT=3000
|
ARG AIO_PREVIEW_SERVER_PORT=3000
|
||||||
ARG TEST_AIO_PREVIEW_SERVER_PORT=3001
|
ARG TEST_AIO_PREVIEW_SERVER_PORT=3001
|
||||||
@ -76,20 +76,21 @@ RUN apt-get update -y && apt-get install -y curl
|
|||||||
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_10.x | bash -
|
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_10.x | bash -
|
||||||
RUN curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
RUN curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||||
RUN echo "deb http://ftp.debian.org/debian stretch-backports main" | tee /etc/apt/sources.list.d/backports.list
|
RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/backports.list
|
||||||
|
|
||||||
|
|
||||||
# Install packages
|
# Install packages
|
||||||
RUN apt-get update -y && apt-get install -y \
|
RUN apt-get update -y && apt-get install -y \
|
||||||
cron=3.0pl1-128+deb9u1 \
|
chkconfig \
|
||||||
dnsmasq=2.76-5+deb9u2 \
|
cron \
|
||||||
nano=2.7.4-1 \
|
dnsmasq \
|
||||||
nginx=1.10.3-1+deb9u2 \
|
nano \
|
||||||
nodejs=10.15.3-1nodesource1 \
|
nodejs \
|
||||||
openssl=1.1.0j-1~deb9u1 \
|
openssl \
|
||||||
rsyslog=8.24.0-1 \
|
rsyslog \
|
||||||
yarn=1.15.2-1
|
yarn
|
||||||
RUN yarn global add pm2@3.5.0
|
RUN apt-get install -t jessie-backports -y nginx
|
||||||
|
RUN yarn global add pm2@2
|
||||||
|
|
||||||
|
|
||||||
# Set up log rotation
|
# Set up log rotation
|
||||||
@ -150,7 +151,8 @@ RUN sed -i "s|{{\$AIO_PREVIEW_SERVER_PORT}}|$TEST_AIO_PREVIEW_SERVER_PORT|g" /et
|
|||||||
|
|
||||||
|
|
||||||
# Set up pm2
|
# Set up pm2
|
||||||
RUN pm2 startup --user root > /dev/null
|
RUN pm2 startup systemv -u root > /dev/null
|
||||||
|
RUN chkconfig pm2-root on
|
||||||
|
|
||||||
|
|
||||||
# Set up the shell scripts
|
# Set up the shell scripts
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Imports
|
// Imports
|
||||||
import * as cp from 'child_process';
|
import * as cp from 'child_process';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import * as http from 'http';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as shell from 'shelljs';
|
import * as shell from 'shelljs';
|
||||||
import {AIO_DOWNLOADS_DIR, HIDDEN_DIR_PREFIX} from '../common/constants';
|
import {AIO_DOWNLOADS_DIR, HIDDEN_DIR_PREFIX} from '../common/constants';
|
||||||
@ -104,7 +105,18 @@ class Helper {
|
|||||||
Object.keys(this.portPerScheme).forEach(scheme => suiteFactory(scheme, this.portPerScheme[scheme]));
|
Object.keys(this.portPerScheme).forEach(scheme => suiteFactory(scheme, this.portPerScheme[scheme]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public verifyResponse(status: number, regex: string | RegExp = /^/): VerifyCmdResultFn {
|
public verifyResponse(status: number | [number, string], regex: string | RegExp = /^/): VerifyCmdResultFn {
|
||||||
|
let statusCode: number;
|
||||||
|
let statusText: string;
|
||||||
|
|
||||||
|
if (Array.isArray(status)) {
|
||||||
|
statusCode = status[0];
|
||||||
|
statusText = status[1];
|
||||||
|
} else {
|
||||||
|
statusCode = status;
|
||||||
|
statusText = http.STATUS_CODES[statusCode] || 'UNKNOWN_STATUS_CODE';
|
||||||
|
}
|
||||||
|
|
||||||
return (result: CmdResult) => {
|
return (result: CmdResult) => {
|
||||||
const [headers, body] = result.stdout.
|
const [headers, body] = result.stdout.
|
||||||
split(/(?:\r?\n){2,}/).
|
split(/(?:\r?\n){2,}/).
|
||||||
@ -119,7 +131,7 @@ class Helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(headers).toMatch(new RegExp(`HTTP/(?:1\\.1|2) ${status} `));
|
expect(headers).toContain(`${statusCode} ${statusText}`);
|
||||||
expect(body).toMatch(regex);
|
expect(body).toMatch(regex);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -259,10 +259,10 @@ describe(`nginx`, () => {
|
|||||||
|
|
||||||
it('should disallow non-GET requests', async () => {
|
it('should disallow non-GET requests', async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
h.runCmd(`curl -iLX POST ${baseUrl}/42`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX POST ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX PUT ${baseUrl}/42`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX PUT ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX PATCH ${baseUrl}/42`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX PATCH ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX DELETE ${baseUrl}/42`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX DELETE ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -295,10 +295,10 @@ describe(`nginx`, () => {
|
|||||||
const url = `${scheme}://${host}/circle-build`;
|
const url = `${scheme}://${host}/circle-build`;
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
]).then(done);
|
]).then(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -334,10 +334,10 @@ describe(`nginx`, () => {
|
|||||||
|
|
||||||
it('should disallow non-POST requests', done => {
|
it('should disallow non-POST requests', done => {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
|
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||||
]).then(done);
|
]).then(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
"$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"cli": {
|
"cli": {
|
||||||
"packageManager": "yarn",
|
"packageManager": "yarn",
|
||||||
@ -13,13 +13,6 @@
|
|||||||
"root": "",
|
"root": "",
|
||||||
"sourceRoot": "src",
|
"sourceRoot": "src",
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"prefix": "aio",
|
|
||||||
"schematics": {
|
|
||||||
"@schematics/angular:component": {
|
|
||||||
"inlineStyle": true,
|
|
||||||
"style": "scss"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"architect": {
|
"architect": {
|
||||||
"build": {
|
"build": {
|
||||||
"builder": "@angular-devkit/build-angular:browser",
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
@ -27,9 +20,7 @@
|
|||||||
"outputPath": "dist",
|
"outputPath": "dist",
|
||||||
"index": "src/index.html",
|
"index": "src/index.html",
|
||||||
"main": "src/main.ts",
|
"main": "src/main.ts",
|
||||||
"polyfills": "src/polyfills.ts",
|
"tsConfig": "src/tsconfig.app.json",
|
||||||
"tsConfig": "tsconfig.app.json",
|
|
||||||
"webWorkerTsConfig": "tsconfig.worker.json",
|
|
||||||
"aot": true,
|
"aot": true,
|
||||||
"optimization": true,
|
"optimization": true,
|
||||||
"buildOptimizer": true,
|
"buildOptimizer": true,
|
||||||
@ -40,9 +31,11 @@
|
|||||||
"extractLicenses": true,
|
"extractLicenses": true,
|
||||||
"namedChunks": true,
|
"namedChunks": true,
|
||||||
"vendorChunk": false,
|
"vendorChunk": false,
|
||||||
|
"polyfills": "src/polyfills.ts",
|
||||||
"assets": [
|
"assets": [
|
||||||
"src/assets",
|
"src/assets",
|
||||||
"src/generated",
|
"src/generated",
|
||||||
|
"src/app/search/search-worker.js",
|
||||||
"src/pwa-manifest.json",
|
"src/pwa-manifest.json",
|
||||||
"src/google385281288605d160.html",
|
"src/google385281288605d160.html",
|
||||||
{
|
{
|
||||||
@ -68,8 +61,8 @@
|
|||||||
"next": {
|
"next": {
|
||||||
"fileReplacements": [
|
"fileReplacements": [
|
||||||
{
|
{
|
||||||
"replace": "src/environments/environment.ts",
|
"src": "src/environments/environment.ts",
|
||||||
"with": "src/environments/environment.next.ts"
|
"replaceWith": "src/environments/environment.next.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"serviceWorker": true
|
"serviceWorker": true
|
||||||
@ -77,8 +70,8 @@
|
|||||||
"stable": {
|
"stable": {
|
||||||
"fileReplacements": [
|
"fileReplacements": [
|
||||||
{
|
{
|
||||||
"replace": "src/environments/environment.ts",
|
"src": "src/environments/environment.ts",
|
||||||
"with": "src/environments/environment.stable.ts"
|
"replaceWith": "src/environments/environment.stable.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"serviceWorker": true
|
"serviceWorker": true
|
||||||
@ -86,8 +79,8 @@
|
|||||||
"archive": {
|
"archive": {
|
||||||
"fileReplacements": [
|
"fileReplacements": [
|
||||||
{
|
{
|
||||||
"replace": "src/environments/environment.ts",
|
"src": "src/environments/environment.ts",
|
||||||
"with": "src/environments/environment.archive.ts"
|
"replaceWith": "src/environments/environment.archive.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"serviceWorker": true
|
"serviceWorker": true
|
||||||
@ -127,13 +120,17 @@
|
|||||||
"builder": "@angular-devkit/build-angular:karma",
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
"options": {
|
"options": {
|
||||||
"main": "src/test.ts",
|
"main": "src/test.ts",
|
||||||
|
"karmaConfig": "src/karma.conf.js",
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"tsConfig": "tsconfig.spec.json",
|
"tsConfig": "src/tsconfig.spec.json",
|
||||||
"webWorkerTsConfig": "tsconfig.worker.json",
|
"scripts": [],
|
||||||
"karmaConfig": "karma.conf.js",
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
"assets": [
|
"assets": [
|
||||||
"src/assets",
|
"src/assets",
|
||||||
"src/generated",
|
"src/generated",
|
||||||
|
"src/app/search/search-worker.js",
|
||||||
"src/pwa-manifest.json",
|
"src/pwa-manifest.json",
|
||||||
"src/google385281288605d160.html",
|
"src/google385281288605d160.html",
|
||||||
{
|
{
|
||||||
@ -146,27 +143,27 @@
|
|||||||
"input": "node_modules/@webcomponents/custom-elements/src",
|
"input": "node_modules/@webcomponents/custom-elements/src",
|
||||||
"output": "/assets/js"
|
"output": "/assets/js"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"styles": [
|
|
||||||
"src/styles.scss"
|
|
||||||
],
|
|
||||||
"scripts": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
"options": {
|
"options": {
|
||||||
"tsConfig": [
|
"tsConfig": [
|
||||||
"tsconfig.app.json",
|
"src/tsconfig.app.json",
|
||||||
"tsconfig.spec.json",
|
"src/tsconfig.spec.json"
|
||||||
"tsconfig.worker.json",
|
|
||||||
"tests/e2e/tsconfig.json"
|
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": []
|
||||||
"**/node_modules/**"
|
}
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"site-e2e": {
|
||||||
|
"root": "",
|
||||||
|
"projectType": "application",
|
||||||
|
"cli": {},
|
||||||
|
"schematics": {},
|
||||||
|
"architect": {
|
||||||
"e2e": {
|
"e2e": {
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
"builder": "@angular-devkit/build-angular:protractor",
|
||||||
"options": {
|
"options": {
|
||||||
@ -178,9 +175,27 @@
|
|||||||
"devServerTarget": "site:serve:ci"
|
"devServerTarget": "site:serve:ci"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"tests/e2e/tsconfig.e2e.json"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultProject": "site"
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"inlineStyle": true,
|
||||||
|
"prefix": "aio",
|
||||||
|
"styleext": "scss"
|
||||||
|
},
|
||||||
|
"@schematics/angular:directive": {
|
||||||
|
"prefix": "aio"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
|
||||||
# For additional information regarding the format and rule options, please see:
|
|
||||||
# https://github.com/browserslist/browserslist#queries
|
|
||||||
|
|
||||||
# Googlebot uses an older version of Chrome
|
|
||||||
# For additional information see: https://developers.google.com/search/docs/guides/rendering
|
|
||||||
|
|
||||||
> 0.5%
|
|
||||||
last 2 major versions
|
|
||||||
Firefox ESR
|
|
||||||
not dead
|
|
||||||
IE 11
|
|
@ -1,4 +1,4 @@
|
|||||||
# CLI Overview and Command Reference
|
<h1 class="no-toc">CLI Command Reference</h1>
|
||||||
|
|
||||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
||||||
|
|
||||||
@ -101,9 +101,3 @@ Options that specify files can be given as absolute paths, or as paths relative
|
|||||||
The [ng generate](cli/generate) and [ng add](cli/add) commands take as an argument the artifact or library to be generated or added to the current project.
|
The [ng generate](cli/generate) and [ng add](cli/add) commands take as an argument the artifact or library to be generated or added to the current project.
|
||||||
In addition to any general options, each artifact or library defines its own options in a *schematic*.
|
In addition to any general options, each artifact or library defines its own options in a *schematic*.
|
||||||
Schematic options are supplied to the command in the same format as immediate command options.
|
Schematic options are supplied to the command in the same format as immediate command options.
|
||||||
|
|
||||||
|
|
||||||
### Building with Bazel
|
|
||||||
|
|
||||||
Optionally, you can configure the Angular CLI to use [Bazel](https://docs.bazel.build) as the build tool. For more information, see [Building with Bazel](guide/bazel).
|
|
||||||
|
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
# Gathering and Viewing Usage Analytics
|
|
||||||
|
|
||||||
Users can opt in to share their Angular CLI usage data with [Google Analytics](https://support.google.com/analytics/answer/1008015?hl=en), using the [`ng analytics` CLI command](analytics).
|
|
||||||
The data is also shared with the Angular team, and used to improve the CLI.
|
|
||||||
|
|
||||||
The gathering of CLI analytics data is disabled by default, and must be enabled at the project level by individual users.
|
|
||||||
It cannot be enabled at the project level for all users.
|
|
||||||
|
|
||||||
Data gathered in this way can be viewed on the Google Analytics site, but is not automatically visible on your own organization's Analytics site.
|
|
||||||
As an administrator for an Angular development group, you can configure your instance of Angular CLI to be able to see analytics data for your own team's usage of the Angular CLI.
|
|
||||||
This configuration option is separate from and in addition to other usage analytics that your users may be sharing with Google.
|
|
||||||
|
|
||||||
## Enable access to CLI usage data
|
|
||||||
|
|
||||||
To configure access to your own users' CLI usage data, use the `ng config` command to add a key to your global [`angular.json` workspace configuration file](guide/workspace-config).
|
|
||||||
The key goes under `cli.analyticsSharing` at the top level of the file, outside the `projects` sections.
|
|
||||||
The value of the key is your organization's tracking ID, as assigned by Google Analytics.
|
|
||||||
This ID is a string that looks like `UA-123456-12`.
|
|
||||||
|
|
||||||
You can choose to use a descriptive string as the key value, or be assigned a random key when you run the CLI command.
|
|
||||||
For example, the following command adds a configuration key named "tracking".
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
ng config --global cli.analyticsSharing.tracking UA-123456-12
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
To turn off this feature, run the following command:
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
ng config --global --remove cli.analyticsSharing
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
## Per user tracking
|
|
||||||
|
|
||||||
You can add a custom user ID to the global configuration, in order to identify unique usage of commands and flags.
|
|
||||||
If that user enables CLI analytics for their own project, your analytics display tracks and labels their individual usage.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
ng config --global cli.analyticsSharing.user SOME_USER_NAME
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
To generate a new random user ID, run the following command:
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
ng config --global cli.analyticsSharing.user ""
|
|
||||||
</code-example>
|
|
12
aio/content/examples/.gitignore
vendored
12
aio/content/examples/.gitignore
vendored
@ -23,9 +23,6 @@
|
|||||||
**/bs-config.e2e.json
|
**/bs-config.e2e.json
|
||||||
**/bs-config.json
|
**/bs-config.json
|
||||||
**/package.json
|
**/package.json
|
||||||
**/tsconfig.json
|
|
||||||
**/tsconfig.app.json
|
|
||||||
**/tsconfig.spec.json
|
|
||||||
**/tslint.json
|
**/tslint.json
|
||||||
**/karma-test-shim.js
|
**/karma-test-shim.js
|
||||||
**/browser-test-shim.js
|
**/browser-test-shim.js
|
||||||
@ -60,9 +57,7 @@ dist/
|
|||||||
|
|
||||||
# aot
|
# aot
|
||||||
**/*.ngsummary.json
|
**/*.ngsummary.json
|
||||||
upgrade-module/tsconfig-aot.json
|
|
||||||
!rollup-config.js
|
!rollup-config.js
|
||||||
upgrade-module/rollup-config.js
|
|
||||||
aot-compiler/**/*.d.ts
|
aot-compiler/**/*.d.ts
|
||||||
aot-compiler/**/*.factory.d.ts
|
aot-compiler/**/*.factory.d.ts
|
||||||
upgrade-phonecat-2-hybrid/aot/**/*
|
upgrade-phonecat-2-hybrid/aot/**/*
|
||||||
@ -89,12 +84,5 @@ upgrade-phonecat-2-hybrid/aot/**/*
|
|||||||
*stackblitz.no-link.html
|
*stackblitz.no-link.html
|
||||||
|
|
||||||
# ngUpgrade testing
|
# ngUpgrade testing
|
||||||
upgrade-phonecat-1-typescript/tsconfig-aot.json
|
|
||||||
upgrade-phonecat-1-typescript/rollup-config.js
|
|
||||||
upgrade-phonecat-3-final/tsconfig-aot.json
|
|
||||||
upgrade-phonecat-3-final/rollup-config.js
|
|
||||||
!upgrade-phonecat-*/**/karma.conf.js
|
!upgrade-phonecat-*/**/karma.conf.js
|
||||||
!upgrade-phonecat-*/**/karma-test-shim.js
|
!upgrade-phonecat-*/**/karma-test-shim.js
|
||||||
|
|
||||||
# schematics
|
|
||||||
!schematics-for-libraries/projects/my-lib/package.json
|
|
@ -67,8 +67,8 @@ describe('AngularJS to Angular Quick Reference Tests', function () {
|
|||||||
testFavoriteHero('Magneta', 'No movie, sorry!');
|
testFavoriteHero('Magneta', 'No movie, sorry!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a movie for Dr Nice', function () {
|
it('should display a movie for Mr. Nice', function () {
|
||||||
testFavoriteHero('Dr Nice', 'Excellent choice!');
|
testFavoriteHero('Mr. Nice', 'Excellent choice!');
|
||||||
});
|
});
|
||||||
|
|
||||||
function testImagesAreDisplayed(isDisplayed: boolean) {
|
function testImagesAreDisplayed(isDisplayed: boolean) {
|
||||||
|
@ -20,7 +20,7 @@ export class AppComponent {
|
|||||||
movies: IMovie[] = [];
|
movies: IMovie[] = [];
|
||||||
showImage = true;
|
showImage = true;
|
||||||
title = 'AngularJS to Angular Quick Ref Cookbook';
|
title = 'AngularJS to Angular Quick Ref Cookbook';
|
||||||
toggleImage(event?: UIEvent) {
|
toggleImage(event: UIEvent) {
|
||||||
this.showImage = !this.showImage;
|
this.showImage = !this.showImage;
|
||||||
this.eventType = (event && event.type) || 'not provided';
|
this.eventType = (event && event.type) || 'not provided';
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import { Injectable, Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
// #docregion date-pipe
|
||||||
|
@Pipe({name: 'date', pure: true})
|
||||||
|
export class StringSafeDatePipe extends DatePipe implements PipeTransform {
|
||||||
|
transform(value: any, format: string): string {
|
||||||
|
value = typeof value === 'string' ?
|
||||||
|
Date.parse(value) : value;
|
||||||
|
return super.transform(value, format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion date-pipe
|
@ -18,12 +18,12 @@ export class MovieService {
|
|||||||
approvalRating: .97
|
approvalRating: .97
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hero: 'Dr Nice',
|
hero: 'Mr. Nice',
|
||||||
imageurl: 'assets/images/villain.png',
|
imageurl: 'assets/images/villain.png',
|
||||||
movieId: 2,
|
movieId: 2,
|
||||||
mpaa: 'pg-13',
|
mpaa: 'pg-13',
|
||||||
releaseDate: '2015-12-18T00:00:00',
|
releaseDate: '2015-12-18T00:00:00',
|
||||||
title: 'No More Dr Nice',
|
title: 'No More Mr. Nice Guy',
|
||||||
price: 14.95,
|
price: 14.95,
|
||||||
starRating: 4.6,
|
starRating: 4.6,
|
||||||
approvalRating: .94
|
approvalRating: .94
|
||||||
|
@ -19,7 +19,6 @@ import { HeroListAutoCalcPageComponent } from './hero-list-auto-page.component';
|
|||||||
import { HeroListAutoComponent } from './hero-list-auto.component';
|
import { HeroListAutoComponent } from './hero-list-auto.component';
|
||||||
import { HomeComponent } from './home.component';
|
import { HomeComponent } from './home.component';
|
||||||
import { AboutComponent } from './about.component';
|
import { AboutComponent } from './about.component';
|
||||||
import { InsertRemoveComponent } from './insert-remove.component';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -57,7 +56,6 @@ import { InsertRemoveComponent } from './insert-remove.component';
|
|||||||
HeroListAutoCalcPageComponent,
|
HeroListAutoCalcPageComponent,
|
||||||
HeroListAutoComponent,
|
HeroListAutoComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
InsertRemoveComponent,
|
|
||||||
AboutComponent
|
AboutComponent
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
|
|
||||||
export const HEROES: Hero[] = [
|
export const HEROES: Hero[] = [
|
||||||
{ id: 11, name: 'Dr Nice' },
|
{ id: 11, name: 'Mr. Nice' },
|
||||||
{ id: 12, name: 'Narco' },
|
{ id: 12, name: 'Narco' },
|
||||||
{ id: 13, name: 'Bombasto' },
|
{ id: 13, name: 'Bombasto' },
|
||||||
{ id: 14, name: 'Celeritas' },
|
{ id: 14, name: 'Celeritas' },
|
||||||
|
@ -31,7 +31,7 @@ describe('Architecture', () => {
|
|||||||
|
|
||||||
function heroTests() {
|
function heroTests() {
|
||||||
|
|
||||||
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
|
const targetHero: Hero = { id: 2, name: 'Mr. Nice' };
|
||||||
|
|
||||||
it('has the right number of heroes', () => {
|
it('has the right number of heroes', () => {
|
||||||
let page = getPageElts();
|
let page = getPageElts();
|
||||||
|
@ -5,7 +5,7 @@ import { Hero } from './hero';
|
|||||||
|
|
||||||
const HEROES = [
|
const HEROES = [
|
||||||
new Hero('Windstorm', 'Weather mastery'),
|
new Hero('Windstorm', 'Weather mastery'),
|
||||||
new Hero('Dr Nice', 'Killing them with kindness'),
|
new Hero('Mr. Nice', 'Killing them with kindness'),
|
||||||
new Hero('Magneta', 'Manipulates metallic objects')
|
new Hero('Magneta', 'Manipulates metallic objects')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { Component } from '@angular/core';
|
|||||||
// #enddocregion import-core-component
|
// #enddocregion import-core-component
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'my-app',
|
||||||
template: 'Welcome to Angular'
|
template: 'Welcome to Angular'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
'use strict'; // necessary for es6 output in node
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('Attribute binding example', function () {
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display Property Binding with Angular', function () {
|
|
||||||
expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display a table', function() {
|
|
||||||
expect(element.all(by.css('table')).isPresent()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display an Aria button', function () {
|
|
||||||
expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display a blue background on div', function () {
|
|
||||||
expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display a blue div with a red border', function () {
|
|
||||||
expect(element.all(by.css('div')).get(4).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display a div with replaced classes', function () {
|
|
||||||
expect(element.all(by.css('div')).get(5).getAttribute('class')).toEqual('new-class');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display four buttons', function() {
|
|
||||||
let redButton = element.all(by.css('button')).get(1);
|
|
||||||
let saveButton = element.all(by.css('button')).get(2);
|
|
||||||
let bigButton = element.all(by.css('button')).get(3);
|
|
||||||
let smallButton = element.all(by.css('button')).get(4);
|
|
||||||
|
|
||||||
expect(redButton.getCssValue('color')).toEqual('rgba(255, 0, 0, 1)');
|
|
||||||
expect(saveButton.getCssValue('background-color')).toEqual('rgba(0, 255, 255, 1)');
|
|
||||||
expect(bigButton.getText()).toBe('Big');
|
|
||||||
expect(smallButton.getText()).toBe('Small');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -1,22 +0,0 @@
|
|||||||
.special {
|
|
||||||
background-color: #1976d2;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.clearance {
|
|
||||||
border: 2px solid #d41e2e;
|
|
||||||
|
|
||||||
}
|
|
||||||
.item-clearance {
|
|
||||||
font-style: italic;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-class {
|
|
||||||
background-color: #ed1b2f;
|
|
||||||
font-style: italic;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
<h1>Attribute, class, and style bindings</h1>
|
|
||||||
<h2>Attribute binding</h2>
|
|
||||||
<!-- #docregion attrib-binding-colspan -->
|
|
||||||
<table border=1>
|
|
||||||
<!-- expression calculates colspan=2 -->
|
|
||||||
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
|
|
||||||
|
|
||||||
<!-- ERROR: There is no `colspan` property to set!
|
|
||||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
|
||||||
-->
|
|
||||||
<!-- #docregion colSpan -->
|
|
||||||
<!-- Notice the colSpan property is camel case -->
|
|
||||||
<tr><td [colSpan]="1 + 1">Three-Four</td></tr>
|
|
||||||
<!-- #enddocregion colSpan -->
|
|
||||||
|
|
||||||
<tr><td>Five</td><td>Six</td></tr>
|
|
||||||
</table>
|
|
||||||
<!-- #enddocregion attrib-binding-colspan -->
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<!-- #docregion attrib-binding-aria -->
|
|
||||||
<!-- create and set an aria attribute for assistive technology -->
|
|
||||||
<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>
|
|
||||||
<!-- #enddocregion attrib-binding-aria -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>Class binding</h2>
|
|
||||||
|
|
||||||
<!-- #docregion is-special -->
|
|
||||||
<h3>toggle the "special" class on/off with a property:</h3>
|
|
||||||
<div [class.special]="isSpecial">The class binding is special.</div>
|
|
||||||
|
|
||||||
<h3>binding to class.special overrides the class attribute:</h3>
|
|
||||||
<div class="special" [class.special]="!isSpecial">This one is not so special.</div>
|
|
||||||
|
|
||||||
<h3>Using the bind- syntax:</h3>
|
|
||||||
<div bind-class.special="isSpecial">This class binding is special too.</div>
|
|
||||||
<!-- #enddocregion is-special -->
|
|
||||||
|
|
||||||
<!-- #docregion add-class -->
|
|
||||||
<h3>Add a class:</h3>
|
|
||||||
<div class="item clearance special" [class.item-clearance]="itemClearance">Add another class</div>
|
|
||||||
<!-- #enddocregion add-class -->
|
|
||||||
|
|
||||||
<!-- #docregion class-override -->
|
|
||||||
<h3>Overwrite all existing classes with a new class:</h3>
|
|
||||||
<div class="item clearance special" [attr.class]="resetClasses">Reset all classes at once</div>
|
|
||||||
<!-- #enddocregion class-override -->
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h2>Style binding</h2>
|
|
||||||
|
|
||||||
<!-- #docregion style-binding-->
|
|
||||||
<button [style.color]="isSpecial ? 'red': 'green'">Red</button>
|
|
||||||
<button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>
|
|
||||||
<!-- #enddocregion style-binding -->
|
|
||||||
|
|
||||||
<!-- #docregion style-binding-condition-->
|
|
||||||
<button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button>
|
|
||||||
<button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button>
|
|
||||||
<!-- #enddocregion style-binding-condition-->
|
|
@ -1,27 +0,0 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
it('should create the app', async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.debugElement.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
}));
|
|
||||||
it(`should have as title 'app'`, async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.debugElement.componentInstance;
|
|
||||||
expect(app.title).toEqual('app');
|
|
||||||
}));
|
|
||||||
it('should render title in a h1 tag', async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
fixture.detectChanges();
|
|
||||||
const compiled = fixture.debugElement.nativeElement;
|
|
||||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
|
||||||
}));
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.css']
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
actionName = 'Go for it';
|
|
||||||
isSpecial = true;
|
|
||||||
itemClearance = true;
|
|
||||||
resetClasses = 'new-class';
|
|
||||||
canSave = true;
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
imports: [
|
|
||||||
BrowserModule
|
|
||||||
],
|
|
||||||
providers: [],
|
|
||||||
bootstrap: [AppComponent]
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>AttributeBinding</title>
|
|
||||||
<base href="/">
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<app-root></app-root>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||||||
import { enableProdMode } from '@angular/core';
|
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
import { environment } from './environments/environment';
|
|
||||||
|
|
||||||
if (environment.production) {
|
|
||||||
enableProdMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
|
||||||
.catch(err => console.log(err));
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Attribute Binding",
|
|
||||||
"files": [
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[1,2].*"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["Attribute Binding"]
|
|
||||||
}
|
|
@ -2,31 +2,30 @@
|
|||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Attribute directives', () => {
|
describe('Attribute directives', function () {
|
||||||
|
|
||||||
let _title = 'My First Attribute Directive';
|
let _title = 'My First Attribute Directive';
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should display correct title: ${_title}`, () => {
|
it(`should display correct title: ${_title}`, function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual(_title);
|
expect(element(by.css('h1')).getText()).toEqual(_title);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to select green highlight', () => {
|
it('should be able to select green highlight', function () {
|
||||||
const highlightedEle = element(by.cssContainingText('p', 'Highlight me!'));
|
let highlightedEle = element(by.cssContainingText('p', 'Highlight me!'));
|
||||||
const lightGreen = 'rgba(144, 238, 144, 1)';
|
let lightGreen = 'rgba(144, 238, 144, 1)';
|
||||||
const getBgColor = () => highlightedEle.getCssValue('background-color');
|
|
||||||
|
|
||||||
expect(highlightedEle.getCssValue('background-color')).not.toEqual(lightGreen);
|
expect(highlightedEle.getCssValue('background-color')).not.toEqual(lightGreen);
|
||||||
|
// let greenRb = element(by.cssContainingText('input', 'Green'));
|
||||||
|
let greenRb = element.all(by.css('input')).get(0);
|
||||||
|
greenRb.click().then(function() {
|
||||||
|
// TypeScript Todo: find the right type for highlightedEle
|
||||||
|
browser.actions().mouseMove(highlightedEle as any).perform();
|
||||||
|
expect(highlightedEle.getCssValue('background-color')).toEqual(lightGreen);
|
||||||
|
});
|
||||||
|
|
||||||
const greenRb = element.all(by.css('input')).get(0);
|
|
||||||
greenRb.click();
|
|
||||||
browser.actions().mouseMove(highlightedEle).perform();
|
|
||||||
|
|
||||||
// Wait for up to 2s for the background color to be updated,
|
|
||||||
// to account for slow environments (e.g. CI).
|
|
||||||
browser.wait(() => highlightedEle.getCssValue('background-color').then(c => c === lightGreen), 2000);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<h1>My First Attribute Directive</h1>
|
<h1>My First Attribute Directive</h1>
|
||||||
<!-- #docregion applied -->
|
<!-- #docregion applied -->
|
||||||
<p appHighlight>Highlight me!</p>
|
<p appHighlight>Highlight me!</p>
|
||||||
<!-- #enddocregion applied -->
|
<!-- #enddocregion applied, -->
|
||||||
|
|
||||||
<!-- #docregion color-1 -->
|
<!-- #docregion color-1 -->
|
||||||
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<!-- #docregion unsupported -->
|
|
||||||
<p app:Highlight>This is invalid</p>
|
|
||||||
<!-- #enddocregion unsupported -->
|
|
@ -1,76 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { logging } from 'selenium-webdriver';
|
|
||||||
|
|
||||||
describe('Binding syntax e2e tests', () => {
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// helper function used to test what's logged to the console
|
|
||||||
async function logChecker(button, contents) {
|
|
||||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
|
||||||
const message = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
|
|
||||||
expect(message.length).toBeGreaterThan(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
it('should display Binding syntax', function () {
|
|
||||||
expect(element(by.css('h1')).getText()).toEqual('Binding syntax');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display Save button', function () {
|
|
||||||
expect(element.all(by.css('button')).get(0).getText()).toBe('Save');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display HTML attributes and DOM properties', function () {
|
|
||||||
expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display 1. Use the inspector...', function () {
|
|
||||||
expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display Disabled property vs. attribute', function () {
|
|
||||||
expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should log a message including Sarah', async () => {
|
|
||||||
let attributeButton = element.all(by.css('button')).get(1);
|
|
||||||
await attributeButton.click();
|
|
||||||
const contents = 'Sarah';
|
|
||||||
logChecker(attributeButton, contents);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log a message including Sarah for DOM property', async () => {
|
|
||||||
let DOMPropertyButton = element.all(by.css('button')).get(2);
|
|
||||||
await DOMPropertyButton.click();
|
|
||||||
const contents = 'Sarah';
|
|
||||||
logChecker(DOMPropertyButton, contents);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log a message including Sally for DOM property', async () => {
|
|
||||||
let DOMPropertyButton = element.all(by.css('button')).get(2);
|
|
||||||
let input = element(by.css('input'));
|
|
||||||
input.sendKeys('Sally');
|
|
||||||
await DOMPropertyButton.click();
|
|
||||||
const contents = 'Sally';
|
|
||||||
logChecker(DOMPropertyButton, contents);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log a message that Test Button works', async () => {
|
|
||||||
let testButton = element.all(by.css('button')).get(3);
|
|
||||||
await testButton.click();
|
|
||||||
const contents = 'Test';
|
|
||||||
logChecker(testButton, contents);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should toggle Test Button disabled', async () => {
|
|
||||||
let toggleButton = element.all(by.css('button')).get(4);
|
|
||||||
await toggleButton.click();
|
|
||||||
const contents = 'true';
|
|
||||||
logChecker(toggleButton, contents);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,3 +0,0 @@
|
|||||||
div {
|
|
||||||
padding: .25rem 0;
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
|
|
||||||
<div>
|
|
||||||
<h1>Binding syntax</h1>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h2>Button disabled state bound to isUnchanged property</h2>
|
|
||||||
<!-- #docregion disabled-button -->
|
|
||||||
<!-- Bind button disabled state to `isUnchanged` property -->
|
|
||||||
<button [disabled]="isUnchanged">Save</button>
|
|
||||||
<!-- #enddocregion disabled-button -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div (keyup)="0">
|
|
||||||
<h2>HTML attributes and DOM properties</h2>
|
|
||||||
<p>1. Use the inspector to see the HTML attribute and DOM property values. Click the buttons to log values to the console.</p>
|
|
||||||
|
|
||||||
<label>HTML Attribute Initializes to "Sarah":
|
|
||||||
<input type="text" value="Sarah" #bindingInput></label>
|
|
||||||
<div>
|
|
||||||
<button (click)="getHTMLAttributeValue()">Get HTML attribute value</button> Won't change.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button (click)="getDOMPropertyValue()">Get DOM property value</button> Changeable. Angular works with these.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>2. Change the name in the input and click the buttons again.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3>Disabled property vs. attribute</h3>
|
|
||||||
<p>Use the inspector to see the Test Button work and its disabled property toggle.</p>
|
|
||||||
<div>
|
|
||||||
<button id="testButton" (click)="working()">Test Button</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button (click)="toggleDisabled()">Toggle disabled property for Test Button</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
@ -1,27 +0,0 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
it('should create the app', async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.debugElement.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
}));
|
|
||||||
it(`should have as title 'app'`, async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.debugElement.componentInstance;
|
|
||||||
expect(app.title).toEqual('app');
|
|
||||||
}));
|
|
||||||
it('should render title in a h1 tag', async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
fixture.detectChanges();
|
|
||||||
const compiled = fixture.debugElement.nativeElement;
|
|
||||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
|
||||||
}));
|
|
||||||
});
|
|
@ -1,33 +0,0 @@
|
|||||||
import { Component, ViewChild, ElementRef } from '@angular/core';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.css']
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
|
|
||||||
@ViewChild('bindingInput', { static: false }) bindingInput: ElementRef;
|
|
||||||
|
|
||||||
isUnchanged = true;
|
|
||||||
|
|
||||||
getHTMLAttributeValue(): any {
|
|
||||||
console.warn('HTML attribute value: ' + this.bindingInput.nativeElement.getAttribute('value'));
|
|
||||||
}
|
|
||||||
|
|
||||||
getDOMPropertyValue(): any {
|
|
||||||
console.warn('DOM property value: ' + this.bindingInput.nativeElement.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
working(): any {
|
|
||||||
console.warn('Test Button works!');
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleDisabled(): any {
|
|
||||||
|
|
||||||
let testButton = <HTMLInputElement> document.getElementById('testButton');
|
|
||||||
testButton.disabled = !testButton.disabled;
|
|
||||||
console.warn(testButton.disabled);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
imports: [
|
|
||||||
BrowserModule
|
|
||||||
],
|
|
||||||
providers: [],
|
|
||||||
bootstrap: [AppComponent]
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Binding Syntax",
|
|
||||||
"files": [
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[1,2].*"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["Binding Syntax"]
|
|
||||||
}
|
|
@ -9,6 +9,6 @@ describe('feature-modules App', () => {
|
|||||||
|
|
||||||
it('should display message saying app works', () => {
|
it('should display message saying app works', () => {
|
||||||
page.navigateTo();
|
page.navigateTo();
|
||||||
expect(page.getTitleText()).toEqual('app works!');
|
expect(page.getParagraphText()).toEqual('app works!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('Built-in Directives', function () {
|
|
||||||
|
|
||||||
beforeAll(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have title Built-in Directives', function () {
|
|
||||||
let title = element.all(by.css('h1')).get(0);
|
|
||||||
expect(title.getText()).toEqual('Built-in Directives');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should change first Teapot header', async () => {
|
|
||||||
let firstLabel = element.all(by.css('p')).get(0);
|
|
||||||
let firstInput = element.all(by.css('input')).get(0);
|
|
||||||
|
|
||||||
expect(firstLabel.getText()).toEqual('Current item name: Teapot');
|
|
||||||
firstInput.sendKeys('abc');
|
|
||||||
expect(firstLabel.getText()).toEqual('Current item name: Teapotabc');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should modify sentence when modified checkbox checked', function () {
|
|
||||||
let modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
|
|
||||||
let modifiedSentence = element.all(by.css('div')).get(1);
|
|
||||||
|
|
||||||
modifiedChkbxLabel.click();
|
|
||||||
expect(modifiedSentence.getText()).toContain('modified');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should modify sentence when normal checkbox checked', function () {
|
|
||||||
let normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
|
|
||||||
let normalSentence = element.all(by.css('div')).get(7);
|
|
||||||
|
|
||||||
normalChkbxLabel.click();
|
|
||||||
expect(normalSentence.getText()).toContain('normal weight and, extra large');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should toggle app-item-detail', function () {
|
|
||||||
let toggleButton = element.all(by.css('button')).get(3);
|
|
||||||
let toggledDiv = element.all(by.css('app-item-detail')).get(0);
|
|
||||||
|
|
||||||
toggleButton.click();
|
|
||||||
expect(toggledDiv.isDisplayed()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should hide app-item-detail', function () {
|
|
||||||
let hiddenMessage = element.all(by.css('p')).get(11);
|
|
||||||
let hiddenDiv = element.all(by.css('app-item-detail')).get(2);
|
|
||||||
|
|
||||||
expect(hiddenMessage.getText()).toContain('in the DOM');
|
|
||||||
expect(hiddenDiv.isDisplayed()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have 10 lists each containing the string Teapot', function () {
|
|
||||||
let listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
|
|
||||||
expect(listDiv.count()).toBe(10);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should switch case', function () {
|
|
||||||
let tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
|
|
||||||
let tvDiv = element(by.css('app-lost-item'));
|
|
||||||
|
|
||||||
let fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
|
|
||||||
let fishbowlDiv = element(by.css('app-unknown-item'));
|
|
||||||
|
|
||||||
tvRadioButton.click();
|
|
||||||
expect(tvDiv.getText()).toContain('Television');
|
|
||||||
fishbowlRadioButton.click();
|
|
||||||
expect(fishbowlDiv.getText()).toContain('mysterious');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
|||||||
|
|
||||||
button {
|
|
||||||
font-size: 100%;
|
|
||||||
margin: 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div[ng-reflect-ng-switch], app-unknown-item {
|
|
||||||
margin: .5rem 0;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#noTrackByCnt,
|
|
||||||
#withTrackByCnt {
|
|
||||||
color: darkred;
|
|
||||||
max-width: 450px;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.box {
|
|
||||||
border: 1px solid black;
|
|
||||||
padding: 6px;
|
|
||||||
max-width: 450px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.child-div {
|
|
||||||
margin-left: 1em;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context {
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parent-div {
|
|
||||||
margin-top: 1em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.course {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: x-large;
|
|
||||||
}
|
|
||||||
|
|
||||||
.helpful {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.saveable {
|
|
||||||
color: limegreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
.study,
|
|
||||||
.modified {
|
|
||||||
font-family: "Brush Script MT";
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toe {
|
|
||||||
margin-left: 1em;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.to-toc {
|
|
||||||
margin-top: 10px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
@ -1,253 +0,0 @@
|
|||||||
<h1>Built-in Directives</h1>
|
|
||||||
|
|
||||||
<h2>Built-in attribute directives</h2>
|
|
||||||
|
|
||||||
<h3 id="ngModel">NgModel (two-way) Binding</h3>
|
|
||||||
|
|
||||||
<fieldset><h4>NgModel examples</h4>
|
|
||||||
<p>Current item name: {{currentItem.name}}</p>
|
|
||||||
<p>
|
|
||||||
<!-- #docregion without-NgModel -->
|
|
||||||
<label for="without">without NgModel:</label>
|
|
||||||
<input [value]="currentItem.name" (input)="currentItem.name=$event.target.value" id="without">
|
|
||||||
<!-- #enddocregion without-NgModel -->
|
|
||||||
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<!-- #docregion NgModel-1 -->
|
|
||||||
<label for="example-ngModel">[(ngModel)]:</label>
|
|
||||||
<input [(ngModel)]="currentItem.name" id="example-ngModel">
|
|
||||||
<!-- #enddocregion NgModel-1 -->
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label for="example-bindon">bindon-ngModel: </label>
|
|
||||||
<input bindon-ngModel="currentItem.name" id="example-bindon">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<!-- #docregion NgModelChange -->
|
|
||||||
<label for="example-change">(ngModelChange)="...name=$event":</label>
|
|
||||||
<input [ngModel]="currentItem.name" (ngModelChange)="currentItem.name=$event" id="example-change">
|
|
||||||
<!-- #enddocregion NgModelChange -->
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label for="example-uppercase">(ngModelChange)="setUppercaseName($event)"
|
|
||||||
<!-- #docregion uppercase -->
|
|
||||||
<input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase">
|
|
||||||
<!-- #enddocregion uppercase -->
|
|
||||||
</label>
|
|
||||||
</p>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<hr><h2 id="ngClass">NgClass Binding</h2>
|
|
||||||
|
|
||||||
<p>currentClasses is {{currentClasses | json}}</p>
|
|
||||||
<!-- #docregion NgClass-1 -->
|
|
||||||
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
|
|
||||||
<!-- #enddocregion NgClass-1 -->
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<label for="saveable">saveable</label>
|
|
||||||
<input type="checkbox" [(ngModel)]="canSave" id="saveable">
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<label for="modified">modified:</label>
|
|
||||||
<input type="checkbox" [value]="!isUnchanged" (change)="isUnchanged=!isUnchanged" id="modified"></li>
|
|
||||||
<li>
|
|
||||||
<label for="special">special: <input type="checkbox" [(ngModel)]="isSpecial" id="special"></label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<button (click)="setCurrentClasses()">Refresh currentClasses</button>
|
|
||||||
|
|
||||||
<div [ngClass]="currentClasses">
|
|
||||||
This div should be {{ canSave ? "": "not"}} saveable,
|
|
||||||
{{ isUnchanged ? "unchanged" : "modified" }} and
|
|
||||||
{{ isSpecial ? "": "not"}} special after clicking "Refresh".</div>
|
|
||||||
<br><br>
|
|
||||||
<!-- #docregion special-div -->
|
|
||||||
<!-- toggle the "special" class on/off with a property -->
|
|
||||||
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
|
|
||||||
<!-- #enddocregion special-div -->
|
|
||||||
<div class="helpful study course">Helpful study course</div>
|
|
||||||
<div [ngClass]="{'helpful':false, 'study':true, 'course':true}">Study course</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- NgStyle binding -->
|
|
||||||
<hr><h3>NgStyle Binding</h3>
|
|
||||||
<!-- #docregion without-ng-style -->
|
|
||||||
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">
|
|
||||||
This div is x-large or smaller.
|
|
||||||
</div>
|
|
||||||
<!-- #enddocregion without-ng-style -->
|
|
||||||
|
|
||||||
|
|
||||||
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
|
|
||||||
<p>currentStyles is {{currentStyles | json}}</p>
|
|
||||||
|
|
||||||
<!-- #docregion NgStyle-2 -->
|
|
||||||
<div [ngStyle]="currentStyles">
|
|
||||||
This div is initially italic, normal weight, and extra large (24px).
|
|
||||||
</div>
|
|
||||||
<!-- #enddocregion NgStyle-2 -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<label>italic: <input type="checkbox" [(ngModel)]="canSave"></label> |
|
|
||||||
<label>normal: <input type="checkbox" [(ngModel)]="isUnchanged"></label> |
|
|
||||||
<label>xlarge: <input type="checkbox" [(ngModel)]="isSpecial"></label>
|
|
||||||
<button (click)="setCurrentStyles()">Refresh currentStyles</button>
|
|
||||||
<br><br>
|
|
||||||
<div [ngStyle]="currentStyles">
|
|
||||||
This div should be {{ canSave ? "italic": "plain"}},
|
|
||||||
{{ isUnchanged ? "normal weight" : "bold" }} and,
|
|
||||||
{{ isSpecial ? "extra large": "normal size"}} after clicking "Refresh".</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2>Built-in structural directives</h2>
|
|
||||||
<h3 id="ngIf">NgIf Binding</h3>
|
|
||||||
<div>
|
|
||||||
<p>If isActive is true, app-item-detail will render: </p>
|
|
||||||
<!-- #docregion NgIf-1 -->
|
|
||||||
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
|
|
||||||
<!-- #enddocregion NgIf-1 -->
|
|
||||||
|
|
||||||
<button (click)="isActiveToggle()">Toggle app-item-detail</button>
|
|
||||||
</div>
|
|
||||||
<p>If currentCustomer isn't null, say hello to Laura:</p>
|
|
||||||
<!-- #docregion NgIf-2 -->
|
|
||||||
<div *ngIf="currentCustomer">Hello, {{currentCustomer.name}}</div>
|
|
||||||
<!-- #enddocregion NgIf-2 -->
|
|
||||||
<p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p>
|
|
||||||
<!-- #docregion NgIf-2b -->
|
|
||||||
<div *ngIf="nullCustomer">Hello, <span>{{nullCustomer}}</span></div>
|
|
||||||
<!-- #enddocregion NgIf-2b -->
|
|
||||||
<button (click)="giveNullCustomerValue()">Give nullCustomer a value</button>
|
|
||||||
|
|
||||||
|
|
||||||
<h4>NgIf binding with template (no *)</h4>
|
|
||||||
|
|
||||||
<ng-template [ngIf]="currentItem">Add {{currentItem.name}} with template</ng-template>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h4>Show/hide vs. NgIf</h4>
|
|
||||||
<!-- #docregion NgIf-3 -->
|
|
||||||
<!-- isSpecial is true -->
|
|
||||||
<div [class.hidden]="!isSpecial">Show with class</div>
|
|
||||||
<div [class.hidden]="isSpecial">Hide with class</div>
|
|
||||||
|
|
||||||
<p>ItemDetail is in the DOM but hidden</p>
|
|
||||||
<app-item-detail [class.hidden]="isSpecial"></app-item-detail>
|
|
||||||
|
|
||||||
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
|
|
||||||
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
|
||||||
<!-- #enddocregion NgIf-3 -->
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2 id="ngFor">NgFor Binding</h2>
|
|
||||||
|
|
||||||
<div class="box">
|
|
||||||
<!-- #docregion NgFor-1, NgFor-1-2 -->
|
|
||||||
<div *ngFor="let item of items">{{item.name}}</div>
|
|
||||||
<!-- #enddocregion NgFor-1, NgFor-1-2 -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>*ngFor with ItemDetailComponent element</p>
|
|
||||||
<div class="box">
|
|
||||||
<!-- #docregion NgFor-2, NgFor-1-2 -->
|
|
||||||
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
|
|
||||||
<!-- #enddocregion NgFor-2, NgFor-1-2 -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h4 id="ngFor-index">*ngFor with index</h4>
|
|
||||||
<p>with <i>semi-colon</i> separator</p>
|
|
||||||
<div class="box">
|
|
||||||
<!-- #docregion NgFor-3 -->
|
|
||||||
<div *ngFor="let item of items; let i=index">{{i + 1}} - {{item.name}}</div>
|
|
||||||
<!-- #enddocregion NgFor-3 -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>with <i>comma</i> separator</p>
|
|
||||||
<div class="box">
|
|
||||||
<div *ngFor="let item of items, let i=index">{{i + 1}} - {{item.name}}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4 id="ngFor-trackBy">*ngFor trackBy</h4>
|
|
||||||
<button (click)="resetList()">Reset items</button>
|
|
||||||
<button (click)="changeIds()">Change ids</button>
|
|
||||||
<button (click)="clearTrackByCounts()">Clear counts</button>
|
|
||||||
|
|
||||||
<p><i>without</i> trackBy</p>
|
|
||||||
<div class="box">
|
|
||||||
<div #noTrackBy *ngFor="let item of items">({{item.id}}) {{item.name}}</div>
|
|
||||||
|
|
||||||
<div id="noTrackByCnt" *ngIf="itemsNoTrackByCount" >
|
|
||||||
Item DOM elements change #{{itemsNoTrackByCount}} without trackBy
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>with trackBy</p>
|
|
||||||
<div class="box">
|
|
||||||
<div #withTrackBy *ngFor="let item of items; trackBy: trackByItems">({{item.id}}) {{item.name}}</div>
|
|
||||||
|
|
||||||
<div id="withTrackByCnt" *ngIf="itemsWithTrackByCount">
|
|
||||||
Item DOM elements change #{{itemsWithTrackByCount}} with trackBy
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br><br><br>
|
|
||||||
|
|
||||||
<p>with trackBy and <i>semi-colon</i> separator</p>
|
|
||||||
<div class="box">
|
|
||||||
<!-- #docregion trackBy -->
|
|
||||||
<div *ngFor="let item of items; trackBy: trackByItems">
|
|
||||||
({{item.id}}) {{item.name}}
|
|
||||||
</div>
|
|
||||||
<!-- #enddocregion trackBy -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>with trackBy and <i>comma</i> separator</p>
|
|
||||||
<div class="box">
|
|
||||||
<div *ngFor="let item of items, trackBy: trackByItems">({{item.id}}) {{item.name}}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>with trackBy and <i>space</i> separator</p>
|
|
||||||
<div class="box">
|
|
||||||
<div *ngFor="let item of items trackBy: trackByItems">({{item.id}}) {{item.name}}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>with <i>generic</i> trackById function</p>
|
|
||||||
<div class="box">
|
|
||||||
<div *ngFor="let item of items, trackBy: trackById">({{item.id}}) {{item.name}}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr><h2>NgSwitch Binding</h2>
|
|
||||||
|
|
||||||
<p>Pick your favorite item</p>
|
|
||||||
<div>
|
|
||||||
<label *ngFor="let i of items">
|
|
||||||
<div><input type="radio" name="items" [(ngModel)]="currentItem" [value]="i">{{i.name}}
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- #docregion NgSwitch -->
|
|
||||||
<div [ngSwitch]="currentItem.feature">
|
|
||||||
<app-stout-item *ngSwitchCase="'stout'" [item]="currentItem"></app-stout-item>
|
|
||||||
<app-device-item *ngSwitchCase="'slim'" [item]="currentItem"></app-device-item>
|
|
||||||
<app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem"></app-lost-item>
|
|
||||||
<app-best-item *ngSwitchCase="'bright'" [item]="currentItem"></app-best-item>
|
|
||||||
<!-- #enddocregion NgSwitch -->
|
|
||||||
<!-- #docregion NgSwitch-div -->
|
|
||||||
<div *ngSwitchCase="'bright'"> Are you as bright as {{currentItem.name}}?</div>
|
|
||||||
<!-- #enddocregion NgSwitch-div -->
|
|
||||||
<!-- #docregion NgSwitch -->
|
|
||||||
<app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item>
|
|
||||||
</div>
|
|
||||||
<!-- #enddocregion NgSwitch -->
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { Item } from './item';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.css']
|
|
||||||
})
|
|
||||||
export class AppComponent implements OnInit {
|
|
||||||
|
|
||||||
canSave = true;
|
|
||||||
isSpecial = true;
|
|
||||||
isUnchanged = true;
|
|
||||||
|
|
||||||
isActive = true;
|
|
||||||
nullCustomer = null;
|
|
||||||
currentCustomer = {
|
|
||||||
name: 'Laura'
|
|
||||||
};
|
|
||||||
|
|
||||||
item: Item; // defined to demonstrate template context precedence
|
|
||||||
items: Item[];
|
|
||||||
|
|
||||||
currentItem: Item;
|
|
||||||
|
|
||||||
|
|
||||||
// trackBy change counting
|
|
||||||
itemsNoTrackByCount = 0;
|
|
||||||
itemsWithTrackByCount = 0;
|
|
||||||
itemsWithTrackByCountReset = 0;
|
|
||||||
itemIdIncrement = 1;
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.resetItems();
|
|
||||||
this.setCurrentClasses();
|
|
||||||
this.setCurrentStyles();
|
|
||||||
this.itemsNoTrackByCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUppercaseName(name: string) {
|
|
||||||
this.currentItem.name = name.toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// #docregion setClasses
|
|
||||||
currentClasses: {};
|
|
||||||
setCurrentClasses() {
|
|
||||||
// CSS classes: added/removed per current state of component properties
|
|
||||||
this.currentClasses = {
|
|
||||||
'saveable': this.canSave,
|
|
||||||
'modified': !this.isUnchanged,
|
|
||||||
'special': this.isSpecial
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// #enddocregion setClasses
|
|
||||||
|
|
||||||
// #docregion setStyles
|
|
||||||
currentStyles: {};
|
|
||||||
setCurrentStyles() {
|
|
||||||
// CSS styles: set per current state of component properties
|
|
||||||
this.currentStyles = {
|
|
||||||
'font-style': this.canSave ? 'italic' : 'normal',
|
|
||||||
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
|
|
||||||
'font-size': this.isSpecial ? '24px' : '12px'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// #enddocregion setStyles
|
|
||||||
|
|
||||||
isActiveToggle() {
|
|
||||||
this.isActive = !this.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
giveNullCustomerValue() {
|
|
||||||
!(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null);
|
|
||||||
}
|
|
||||||
|
|
||||||
resetNullItem() {
|
|
||||||
this.nullCustomer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetItems() {
|
|
||||||
this.items = Item.items.map(item => item.clone());
|
|
||||||
this.currentItem = this.items[0];
|
|
||||||
this.item = this.currentItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetList() {
|
|
||||||
this.resetItems()
|
|
||||||
this.itemsWithTrackByCountReset = 0;
|
|
||||||
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
changeIds() {
|
|
||||||
|
|
||||||
this.items.forEach(i => i.id += 1 * this.itemIdIncrement);
|
|
||||||
this.itemsWithTrackByCountReset = -1;
|
|
||||||
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
|
|
||||||
this.itemsWithTrackByCount = ++this.itemsWithTrackByCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearTrackByCounts() {
|
|
||||||
this.resetItems();
|
|
||||||
this.itemsNoTrackByCount = 0;
|
|
||||||
this.itemsWithTrackByCount = 0;
|
|
||||||
this.itemIdIncrement = 1;
|
|
||||||
}
|
|
||||||
// #docregion trackByItems
|
|
||||||
trackByItems(index: number, item: Item): number { return item.id; }
|
|
||||||
// #enddocregion trackByItems
|
|
||||||
|
|
||||||
trackById(index: number, item: any): number { return item['id']; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
// #docregion import-forms-module
|
|
||||||
import { FormsModule } from '@angular/forms'; // <--- JavaScript import from Angular
|
|
||||||
// #enddocregion import-forms-module
|
|
||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
import { ItemDetailComponent } from './item-detail/item-detail.component';
|
|
||||||
import { ItemSwitchComponents } from './item-switch.component';
|
|
||||||
|
|
||||||
|
|
||||||
// #docregion import-forms-module
|
|
||||||
@NgModule({
|
|
||||||
// #enddocregion import-forms-module
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
ItemDetailComponent,
|
|
||||||
ItemSwitchComponents
|
|
||||||
],
|
|
||||||
// #docregion import-forms-module
|
|
||||||
|
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
FormsModule // <--- import into the NgModule
|
|
||||||
],
|
|
||||||
// #enddocregion import-forms-module
|
|
||||||
providers: [],
|
|
||||||
bootstrap: [AppComponent]
|
|
||||||
// #docregion import-forms-module
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
||||||
// #enddocregion import-forms-module
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
<div>
|
|
||||||
<span>{{item?.name}}</span>
|
|
||||||
</div>
|
|
@ -1,25 +0,0 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { ItemDetailComponent } from './item-detail.component';
|
|
||||||
|
|
||||||
describe('ItemDetailComponent', () => {
|
|
||||||
let component: ItemDetailComponent;
|
|
||||||
let fixture: ComponentFixture<ItemDetailComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ ItemDetailComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ItemDetailComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,17 +0,0 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
|
||||||
|
|
||||||
import { Item } from '../item';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-item-detail',
|
|
||||||
templateUrl: './item-detail.component.html',
|
|
||||||
styleUrls: ['./item-detail.component.css']
|
|
||||||
})
|
|
||||||
export class ItemDetailComponent {
|
|
||||||
|
|
||||||
|
|
||||||
@Input() item: Item;
|
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
|
||||||
import { Item } from './item';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-stout-item',
|
|
||||||
template: `I'm a little {{item.name}}, short and stout!`
|
|
||||||
})
|
|
||||||
export class StoutItemComponent {
|
|
||||||
@Input() item: Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-best-item',
|
|
||||||
template: `This is the brightest {{item.name}} in town.`
|
|
||||||
})
|
|
||||||
export class BestItemComponent {
|
|
||||||
@Input() item: Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-device-item',
|
|
||||||
template: `Which is the slimmest {{item.name}}?`
|
|
||||||
})
|
|
||||||
export class DeviceItemComponent {
|
|
||||||
@Input() item: Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-lost-item',
|
|
||||||
template: `Has anyone seen my {{item.name}}?`
|
|
||||||
})
|
|
||||||
export class LostItemComponent {
|
|
||||||
@Input() item: Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-unknown-item',
|
|
||||||
template: `{{message}}`
|
|
||||||
})
|
|
||||||
export class UnknownItemComponent {
|
|
||||||
@Input() item: Item;
|
|
||||||
get message() {
|
|
||||||
return this.item && this.item.name ?
|
|
||||||
`${this.item.name} is strange and mysterious.` :
|
|
||||||
'A mystery wrapped in a fishbowl.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ItemSwitchComponents =
|
|
||||||
[ StoutItemComponent, BestItemComponent, DeviceItemComponent, LostItemComponent, UnknownItemComponent ];
|
|
@ -1,30 +0,0 @@
|
|||||||
export class Item {
|
|
||||||
static nextId = 0;
|
|
||||||
|
|
||||||
static items: Item[] = [
|
|
||||||
new Item(
|
|
||||||
null,
|
|
||||||
'Teapot',
|
|
||||||
'stout'
|
|
||||||
),
|
|
||||||
new Item(1, 'Lamp', 'bright'),
|
|
||||||
new Item(2, 'Phone', 'slim' ),
|
|
||||||
new Item(3, 'Television', 'vintage' ),
|
|
||||||
new Item(4, 'Fishbowl')
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public id?: number,
|
|
||||||
public name?: string,
|
|
||||||
public feature?: string,
|
|
||||||
public url?: string,
|
|
||||||
public rate = 100,
|
|
||||||
) {
|
|
||||||
this.id = id ? id : Item.nextId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
clone(): Item {
|
|
||||||
return Object.assign(new Item(), this);
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 32 KiB |
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>BuiltInDirectives</title>
|
|
||||||
<base href="/">
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<app-root></app-root>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Built-in Directives",
|
|
||||||
"files": [
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[1,2].*"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["Built-in Directives"]
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
'use strict'; // necessary for es6 output in node
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('Built Template Functions Example', function () {
|
|
||||||
beforeAll(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have title Built-in Template Functions', function () {
|
|
||||||
let title = element.all(by.css('h1')).get(0);
|
|
||||||
expect(title.getText()).toEqual('Built-in Template Functions');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display $any( ) in h2', function () {
|
|
||||||
let header = element(by.css('h2'));
|
|
||||||
expect(header.getText()).toContain('$any( )');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
<h1>{{title}}</h1>
|
|
||||||
|
|
||||||
<h2><code>$any( )</code> type cast function and an undeclared member</h2>
|
|
||||||
|
|
||||||
<p>There is no such member as <code>bestByDate</code> in the following two examples, so nothing renders:</p>
|
|
||||||
<!-- #docregion any-type-cast-function-1 -->
|
|
||||||
<p>The item's undeclared best by date is: {{$any(item).bestByDate}}</p>
|
|
||||||
<!-- #enddocregion any-type-cast-function-1 -->
|
|
||||||
|
|
||||||
<h2>using <code>this</code></h2>
|
|
||||||
<!-- #docregion any-type-cast-function-2 -->
|
|
||||||
<p>The item's undeclared best by date is: {{$any(this).bestByDate}}</p>
|
|
||||||
<!-- #enddocregion any-type-cast-function-2 -->
|
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
import { TestBed, async } from '@angular/core/testing';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
it('should create the app', async(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.debugElement.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
}));
|
|
||||||
});
|
|
@ -1,16 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.css']
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
title = 'Built-in Template Functions';
|
|
||||||
|
|
||||||
item = {
|
|
||||||
name : 'Telephone',
|
|
||||||
origin : 'Sweden',
|
|
||||||
price: 98
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
imports: [
|
|
||||||
BrowserModule
|
|
||||||
],
|
|
||||||
providers: [],
|
|
||||||
bootstrap: [AppComponent]
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,14 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Built-in Template Functions Example</title>
|
|
||||||
<base href="/">
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<app-root>Loading...</app-root>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Built-in Template Functions",
|
|
||||||
"files": [
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[1,2].*"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["Built-in Template Functions"]
|
|
||||||
}
|
|
11
aio/content/examples/cli-quickstart/bs-config.cli.json
Normal file
11
aio/content/examples/cli-quickstart/bs-config.cli.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"open": false,
|
||||||
|
"logLevel": "silent",
|
||||||
|
"port": 8080,
|
||||||
|
"server": {
|
||||||
|
"baseDir": "dist",
|
||||||
|
"middleware": {
|
||||||
|
"0": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
aio/content/examples/cli-quickstart/e2e/src/app.e2e-spec.ts
Normal file
14
aio/content/examples/cli-quickstart/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('cli-quickstart App', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
return browser.get('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display message saying app works', () => {
|
||||||
|
let pageTitle = element(by.css('app-root h1')).getText();
|
||||||
|
expect(pageTitle).toEqual('Welcome to My First Angular App!!');
|
||||||
|
});
|
||||||
|
});
|
4
aio/content/examples/cli-quickstart/example-config.json
Normal file
4
aio/content/examples/cli-quickstart/example-config.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"build": "build:cli",
|
||||||
|
"run": "serve:cli"
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/* #docregion */
|
||||||
|
h1 {
|
||||||
|
color: #369;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 250%;
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<!--The content below is only a placeholder and can be replaced.-->
|
||||||
|
<div style="text-align:center">
|
||||||
|
<h1>
|
||||||
|
Welcome to {{ title }}!
|
||||||
|
</h1>
|
||||||
|
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
|
||||||
|
</div>
|
||||||
|
<h2>Here are some links to help you start: </h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
||||||
|
</li>
|
||||||
|
</ul>
|
@ -8,20 +8,23 @@ describe('AppComponent', () => {
|
|||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should create the app', async(() => {
|
it('should create the app', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.debugElement.componentInstance;
|
const app = fixture.debugElement.componentInstance;
|
||||||
expect(app).toBeTruthy();
|
expect(app).toBeTruthy();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it(`should have as title 'app'`, async(() => {
|
it(`should have as title 'app'`, async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.debugElement.componentInstance;
|
const app = fixture.debugElement.componentInstance;
|
||||||
expect(app.title).toEqual('app');
|
expect(app.title).toMatch(/app/i);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should render title in a h1 tag', async(() => {
|
it('should render title in a h1 tag', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const compiled = fixture.debugElement.nativeElement;
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
expect(compiled.querySelector('h1').textContent).toMatch(/app/i);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
16
aio/content/examples/cli-quickstart/src/app/app.component.ts
Normal file
16
aio/content/examples/cli-quickstart/src/app/app.component.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// #docregion import
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
// #enddocregion import
|
||||||
|
|
||||||
|
// #docregion metadata, component
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
// #enddocregion metadata
|
||||||
|
// #docregion title, class
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'My First Angular App!';
|
||||||
|
}
|
||||||
|
// #enddocregion title, class, component
|
@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>EventBinding</title>
|
<title>MyApp</title>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
9
aio/content/examples/cli-quickstart/zipper.json
Normal file
9
aio/content/examples/cli-quickstart/zipper.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[0-9].*",
|
||||||
|
"angular.json",
|
||||||
|
"protractor.conf.js"
|
||||||
|
]
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user