Compare commits

..

353 Commits

Author SHA1 Message Date
9b812dc729 release: cut the v8.0.3 release 2019-06-26 13:41:07 -07:00
2eee8d59fe ci: target default pool for linux RBE executions (#31297)
PR Close #31297
2019-06-26 13:31:37 -07:00
f0dc8cfc05 docs: add "ivy" to known scopes in contributing guide (#31293)
Currently the contributing guide misses the ivy scope. This
commit adds ivy to the contributing guide as it is useful
for new contributors to know which scopes are supported.

Note: this is the patch version of #31291

PR Close #31293
2019-06-26 13:31:17 -07:00
79471f7610 docs: correct indention for code example in deployment guide (#31255)
PR Close #31255
2019-06-25 14:44:34 -07:00
54f68c342b docs(core): update code sample for "outputs" attribute (#31199)
The current code sample for (directive) "outputs" attribute is incorrect as it does not provide the usage of "outputs" attribute rather it provides the usage of "exportAs" attribute. This commit update the code sample by correcting the code sample with correct usage of "outputs" attribute.

Fixes https://github.com/angular/angular/issues/29523
Related work https://github.com/angular/angular/pull/30014

This commit continues from the unfinished (https://github.com/angular/angular/pull/30014#issuecomment-485419124, https://github.com/angular/angular/issues/29523#issuecomment-497333146) work.

PR Close #31199
2019-06-25 14:44:09 -07:00
86bfb0172b docs: change note about cli (#31216)
PR Close #31216
2019-06-25 11:58:07 -07:00
52186165ee docs: add note about cli commands (#31216)
PR Close #31216
2019-06-25 11:58:07 -07:00
e9ae885982 ci: add owners for zone.js to CODEOWNERS (#31203)
Follow-up to #30962.

PR Close #31203
2019-06-25 11:20:01 -07:00
8a1bd2c401 docs: fix formatting (#31120)
PR Close #31120
2019-06-25 10:28:51 -07:00
018b695ef2 docs: fix testing example (#31120)
PR Close #31120
2019-06-25 10:28:51 -07:00
1d193df360 ci: enable remote build caching for CI jobs (#31204)
Enables remote caching for CI jobs.

This configuration:

always reads from build cache on CI
only write to build cache for local builds for non-PR CI run

PR Close #31204
2019-06-25 10:26:44 -07:00
0a46b2acfb fix(docs-infra): separate vendor-specific CSS selectors (#31252)
In #31118, some vendor-specific selectors were combined in one rule-set.
As pointed out in [this comment][1], this would result in the whole
rule-set being ignored by all browsers, since one invalid/unrecognized
selector invalidates the declaration block.

This commit fixes it by defining a separate rule-set per selector. The
list of vendor-specific selectors is also adjusted to better target the
currently supported browsers.

[1]: https://github.com/angular/angular/pull/31118/files#r296923652

PR Close #31252
2019-06-25 10:25:32 -07:00
b63aa4e7ef style(docs-infra): clean up some styles (#31252)
PR Close #31252
2019-06-25 10:25:32 -07:00
6aae19633b build: use checked-in configuration from bazel-toolchains (#31251)
No longer uses docker in order to pull down the toolchain configs
for remote build execution. We don't need to make docker a prerequisite
for working on the Angular repository since we can leverage the checked-in
toolchain configurations from the `@bazel-toolchains` repository.

PR Close #31251
2019-06-25 10:24:44 -07:00
00242e8d6d docs(core): change from CSS Event to DOM event (#31229)
PR Close #31229
2019-06-25 10:22:35 -07:00
4ea231fdbe fix(docs-infra): return full width highlight to sidenav (#31246)
PR Close #31246
2019-06-24 20:17:27 -07:00
6bad2ca586 fix(bazel): exclude all angular schematics folders from metadata build (#31237)
Fixes #31235

PR Close #31237
2019-06-24 18:48:45 -07:00
dabf1325ed ci: upgrade clang-format to 1.0.27 to match master (#31247)
PR Close #31247
2019-06-24 16:50:06 -07:00
987b18596b ci(docs-infra): re-enable payload size checking for test_aio_local and test_aio_local_ivy (#31243)
Previously, payload size checking for `test_aio_local` and
`test_aio_local_ivy` was disabled on the 8.0.x branch (in #31064),
because the numbers (which were cherry-picked from master) did not match
the actual sizes.

This commit updates the numbers for the 8.0.x branch and re-enables the
checks.

PR Close #31243
2019-06-24 15:00:00 -07:00
f470e69fba fix(service-worker): registration failed on Safari (#31140)
Since Angular v8, and commit b3dda0e, `parseUrl()` can be called without
`relativeTo`, thus `new URL()` can be called with `relativeTo = undefined`.

Safari does not like it and the service worker registration fails:
```js
new URL('https://angular.io/') // OK
new URL('https://angular.io/', undefined) // TypeError
```

Closes #31061

PR Close #31140
2019-06-24 14:58:59 -07:00
980bcaf176 fix(bazel): remove unsupported Css pre-processors from ng new (#31234)
Under Bazel, we don't yet support Stylus and Less, and thus we should not offer the users to generate applications which are known not to work.

Closes #31209

PR Close #31234
2019-06-24 14:57:07 -07:00
48f7f65bf4 fix(bazel): update ng new schema to match the current ng new schema of @schematics/angular (#31234)
The schema used in ng-new bazel, includes several outdated options. With this update we match the current version of @schematics/angular: https://github.com/angular/angular-cli/blob/master/packages/schematics/angular/ng-new/schema.json

Relates to #31233

PR Close #31234
2019-06-24 14:57:07 -07:00
7fe95b1882 ci: send failure notifications from saucelabs_tests to dev-infra-ci-failures (#31202)
PR Close #31202
2019-06-21 15:29:36 -07:00
266871baf4 ci: make logic for failure notifications more re-usable (#31202)
PR Close #31202
2019-06-21 15:29:36 -07:00
bc54ecf66e ci: send aio_monitoring failure notifications to the dev-infra-ci-failures channel (#31202)
PR Close #31202
2019-06-21 15:29:36 -07:00
274833ee94 ci: add josephperrott to dev-infra owners (#31205)
PR Close #31205
2019-06-21 15:29:10 -07:00
ff5934597a build: Set up Build Event Service Configuration for RBE executed bazel (#31197)
The Build Event Service (https://docs.bazel.build/versions/master/build-event-protocol.html#the-build-event-service),
allows for build events from bazel builds to be transmitted as opaque bytes to be processed.

Our usage is to send our build events to a Build Event Service an Angular team owned Google Cloud Project which collects
build results and makes each invocation available via a provided URL to view.  The information uploaded includes information
about the build environment, configuration, build status/events, build options, results and actions.

Build Event Protocol Proto: https://github.com/bazelbuild/bazel/blob/0.27.0/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto

PR Close #31197
2019-06-21 15:28:51 -07:00
09b60ed36a feat(docs-infra): change typography font sizes to be rem based (#31118)
PR Close #31118
2019-06-21 14:22:21 -07:00
0bb83b2ba6 docs: update node minimum version (#31192)
Docs for for Travis CI setup suggest using node version 8 when the minimum should be 10. This commit updates the documentation by specifying the minimum required version as 10.

Fixes https://github.com/angular/angular/issues/31185

PR Close #31192
2019-06-21 12:02:39 -07:00
de04741863 docs: clarify wording in Template Syntax (#31119)
PR Close #31119
2019-06-21 10:23:38 -07:00
8ea91887ca docs: mark interfaces as public (#30955)
PR Close #30955
2019-06-21 10:21:13 -07:00
ff184b56eb docs: fix javascript module link (#31181)
PR Close #31181
2019-06-21 10:14:40 -07:00
15d138fdd3 docs: fix typo in browser-support.md (ES1015 --> ES2015) (#31157)
PR Close #31157
2019-06-21 10:14:24 -07:00
1699b54860 docs: add Mosaic library to resources (#31026)
PR Close #31026
2019-06-21 10:14:04 -07:00
07f6b2c018 build: user bazelrc should be able to overwrite all flags (#31164)
After eb00a37eb8 we accidentally regressed due to some
recent changes where more flags were added at the end of the bazelrc. This means that all
flags which were added after the `try-import` can no longer be overwritten easily in the
user project bazelrc file. Technically developers can always overwrite flags though the
command line, but it's a productivity blocker if developers can't permanently overwrite these
flags  through the user config

PR Close #31164
2019-06-20 11:18:13 -07:00
4a193580fe build(docs-infra): upgrade @angular/cli to 8.1.0-beta.2 (#31137)
PR Close #31137
2019-06-20 11:16:36 -07:00
9c222350f9 ci: re-enable payload size tracking (#31138)
Payload size tracking was temporarily disabled in #31057, due to
`CIRCLE_COMPARE_URL` stopping being available. It turned out this was
related to turning on the new [Pipelines][1] feature, which was required
for testing Windows on CircleCI.

Since then, we have turned `Pipelines` off and got `CIRCLE_COMPARE_URL`
back (e.g. see [build 362971][2]). According to CircleCI, failing to
populate `CIRCLE_COMPARE_URL` with `Pipelines` on is a bug and they are
working on fixing it.

[1]: https://circleci.com/docs/2.0/build-processing/
[2]: https://circleci.com/gh/angular/angular/362971

Fixes #31121

PR Close #31138
2019-06-19 15:55:10 -07:00
c36edffe2a docs: fix bad tag (#31115)
PR Close #31115
2019-06-19 15:52:48 -07:00
13b984d72b docs: fix bad anchors (#31115)
PR Close #31115
2019-06-19 15:52:48 -07:00
f00eff5916 docs: fix code example formats (#31115)
PR Close #31115
2019-06-19 15:52:48 -07:00
31ee45efdc docs: add instructions for es5 serve and test targets (#31115)
PR Close #31115
2019-06-19 15:52:47 -07:00
b68f2d6fa5 docs: remove inappropriate link (#31091)
PR Close #31091
2019-06-19 15:31:57 -07:00
d8def6d728 refactor(docs-infra): move auto-link filters to dedicated directory (#31051)
These filters have generic names (e.g. `filterPipes`), which do not make
their purpose obvious. Moving them to a dedicated `auto-link-filters`
directory should help with that.

PR Close #31051
2019-06-19 14:59:35 -07:00
e8f464409c fix(docs-infra): do not auto-link http:// to the common/http (#31051)
Previously, our auto-linking feature would match `http` in URLs (such as
`http://...`) to the `common/http` package and automatically create a
link to that, which was undesirable. While it is possible to work around
that via `<code class="no-auto-link">http://...</code>`, most people
didn't even realize the issue.

Since in this case it is possible to reliably know it is a false match,
this commit fixes it by applying a custom auto-link filter that ignores
all docs for `http`, if it comes before `://`.

Fixes #31012

PR Close #31051
2019-06-19 14:59:35 -07:00
a73b8a62c8 release: cut the v8.0.2 release 2019-06-19 10:33:28 -07:00
2fe8f2b1e0 build: update buildifier to version that supports windows (#31129)
* Updates buildifier to a version that also comes with windows binaries.
* Fixes a few new formatting/lint warnings
* Removes the `args-order` warning because it is no longer a warning.. and is now part of the formatter.

Patch version of #31112

PR Close #31129
2019-06-19 08:50:43 -07:00
f1c08c6918 docs: add core and cli version alignment note (#30976)
docs: add core and cli version alignment note
PR Close #30976
2019-06-19 08:49:25 -07:00
bf9de8ca53 test: update side-effects test to be more descriptive (#31005)
This test will now list diffs for failed expectations and the full command to update them.

Fix #30570

PR Close #31005
2019-06-18 13:58:59 -07:00
df37c47ac5 ci: add jasonaden to forms owners (#31117)
PR Close #31117
2019-06-18 13:58:30 -07:00
788d19c036 build: enable shard_count for some jasmine tests that have many specs (#31009)
This partitions the spects across multiple processes so they run in parallel.

PR Close #31009
2019-06-18 12:11:31 -07:00
8492499fe7 docs: add missing word in build and deploy guide to clarify sentence (#31093)
PR Close #31093
2019-06-18 11:00:28 -07:00
48174010a1 docs: update group() link to point to the animations group API (#30618)
PR Close #30618
2019-06-18 10:49:46 -07:00
1460e46ba1 build: ts-api-guardian npm package contains invalid references (#31096)
Currently when building the `ts-api-guardian` npm package,
the labels are not properly replaced after recent changes to
the `entry_point` attribute. This means that the `ts-api-guardian`
package is currently not usable externally.

PR Close #31096
2019-06-18 09:50:42 -07:00
a7ff7d8d27 docs: refresh TypeScript configuration guide with updated info and files (#31097)
This removes the hard-coded tsconfig.json to use a separate file.
The tsconfig.0.json is added to the getting-started example folder
because have to check it with every major release
Also updates the text regarding defaults for TypeScript compilation targets
and typings

PR Close #31097
2019-06-18 09:47:49 -07:00
eb970b4626 docs: rewrite Observable examples with pipable operators (#31074)
PR Close #31074
2019-06-18 09:47:07 -07:00
18d301258a docs: change interceptor documentation (#30969)
PR Close #30969
2019-06-18 09:46:35 -07:00
6a01fa532c docs: add mock heroes to the code review tabs for TOH pt. 2 (#31080)
PR Close #31080
2019-06-17 16:34:39 -07:00
e190a7e9de fix(docs-infra): fix search result header color (#30924)
PR Close #30924
2019-06-17 16:33:54 -07:00
53c6425954 ci: publish snapshots job is unable to decode github token (#31099)
The publish_snapshots job is currently not able to decode the Github
token because the openssl version changed. This is because the default
digest for more recent openssl version has been updated and the github
token file has been encrypted with an old digest. We need to ensure
that the md5 digest is used for decryption as that matches the
digest used for encryption.

PR Close #31099
2019-06-17 13:56:13 -07:00
c198dc6c19 fix(bazel): builder workspace should use nodejs v10.16.0 (#31088)
The generated Bazel workspace by the `@angular/bazel` builder should
use the latest stable NodeJS version. This is necessary because some
packages like `selenium-webdriver` which are part of the default bazel
setup in order to support `ng e2e` depend on a minimum NodeJS version
of `10.15.0`.. This means that running e2e tests in a plain new bazel CLI
project (`ng new {projectName} --collection=@angular/bazel`) errors.

```
command.
 (error selenium-webdriver@4.0.0-alpha.3: The engine "node" is incompatible with
 this module. Expected version ">= 10.15.0". Got "10.13.0"
error Found incompatible module
)
```

PR Close #31088
2019-06-17 13:07:28 -07:00
d1b26dd3a1 ci: update nodejs version to v10.16.0 (#31088)
Updates the NodeJS version to the latest stable version at the time of
writing (v10.16.0). We need to update our image to use a minimum NodeJS
version of v10.15.0 because new CLI apps automatically install a non-locked
version of selenium-webdriver that now requires NodeJS >= 10.15.0 since the
latest release of 17th June 2019 (4.0.0-alpha.3).

See CI failures: https://circleci.com/gh/angular/angular/359077

PR Close #31088
2019-06-17 13:07:28 -07:00
ce7131f3fb ci(docs-infra): disable payload size tracking for test_aio_local and test_aio_local_ivy (#31064)
Payload size tracking for AIO introduced in the previous commit (c596795e64) works fine for master branch, but fails in patch branch. In order to keep CI for patch branch healthy, the size tracking is temporary disabled and will be turned on again after additional investigation.

PR Close #31064
2019-06-14 16:03:39 -07:00
934702892e ci(docs-infra): check and track payload sizes for test_aio_local and test_aio_local_ivy (#31047)
PR Close #31047
2019-06-14 14:38:11 -07:00
8a830a72e2 ci(docs-infra): run PWA score tests after unit/e2e tests (#31047)
Previously, we run the PWA score tests before unit/e2e tests, because
the latter would destroy the `dist/` directory required by the former.

Since cli@6, unit/e2e tests no longer detroy the `dist/` directory, so
it is now safe to run the unit/e2e tests first. This is preferrable,
since they are conceptually lower-level and any error messages (in case
of breakage) are more specific/actionable.

Related discussion about cli behavior:
- angular/angular-cli#4366
- angular/angular-cli#14701

PR Close #31047
2019-06-14 14:38:11 -07:00
2abb54c4a1 docs: rewrite attribute binding section and add example (#26004)
PR Close #26004
2019-06-14 12:21:28 -07:00
44632bb700 docs: edit codeowners for new Template Syntax examples (#31060)
PR Close #31060
2019-06-14 11:54:30 -07:00
e33b382ab4 docs: edit and add example for Template Expression Operators section of Template Syntax (#28087)
PR Close #28087
2019-06-14 11:53:51 -07:00
c4da400db4 docs: rewrite inputs/outputs section of Template Syntax (#27685)
PR Close #27685
2019-06-14 11:53:14 -07:00
c40e6b2edc docs: edit template ref vars copy and example (#27371)
PR Close #27371
2019-06-14 11:52:34 -07:00
978fc27314 docs: rewrite built-in directives section (#27273)
PR Close #27273
2019-06-14 11:51:47 -07:00
b9f2bbb7d1 docs: add example and edit two-way-binding section of Template Syntax (#26278)
PR Close #26278
2019-06-14 11:50:04 -07:00
9654d646ae docs: rewrite property binding section and add example (#25770)
PR Close #25770
2019-06-14 11:47:35 -07:00
7f214499e8 fix(language-service): Remove 'any' in getQuickInfoAtPosition (#31014)
PR Close #31014
2019-06-14 10:46:17 -07:00
a3d55a9d27 build(docs-infra): update browserlist configuration file (#31045)
More specifically:
- Remove Chrome 41, which was needed for googlebot support but not any
  more.
- Remove IE 9-10, because we don't expect developers to be using them.
- Expand support from _last 2 versions_ to _last 2 **major** versions_.

PR Close #31045
2019-06-14 10:43:22 -07:00
e222b8761e docs: minor fix in get-commit-range.js docs (#31049)
PR Close #31049
2019-06-14 10:41:43 -07:00
1435c0b3a9 docs(aio): add missing description to dev.to link (#30960)
PR Close #30960
2019-06-14 10:41:13 -07:00
0a7aebbcf5 fix(core): temporarily remove @deprecated jsdoc tag for a TextBedStatic.get overload (#30714)
Followup to #30514 which did the same for `TestBed`, but `TestBedStatic` was necessary too.

PR Close #30714
2019-06-14 10:40:43 -07:00
bd7f91feac docs: rewrite binding-syntax section in template-syntax.md (#25561)
PR Close #25561
2019-06-14 10:25:07 -07:00
3bbc89b958 ci: temporarily disable payload size tracking (#31057)
The `CIRCLE_COMPARE_URL` is not available in builds any more since we
enabled `Pipelines` on CircleCI. We have contected CircleCI, but until
this is solved we cannot get the commit range and thus disabling
uploading of payload size data to avoid broken builds.

PR Close #31057
2019-06-14 09:19:18 -07:00
52d98e563d docs: fix broken link in singleton services doc (#31007)
PR Close #31007
2019-06-13 17:05:21 -07:00
b279f8bd62 docs: add no-auto-link instructions to docs style guide (#30980)
PR Close #30980
2019-06-13 17:00:47 -07:00
954e34cc91 docs: add angular.tw (Traditional Chinese) site to navigation.json (#30723)
PR Close #30723
2019-06-13 16:04:41 -07:00
e1f6d15387 release: cut the v8.0.1 release 2019-06-13 15:22:16 -07:00
cbb3794931 fix(docs-infra): enable only vertical scrolling for contributors bio (#30991)
- `auto` will enable scrolling only when needed
- `overflow-y` will ensure to keep the scrolling horizontally only

PR Close #30991
2019-06-12 11:47:13 -07:00
77a5790a9d docs: add platform to glossary (#30731)
PR Close #30731
2019-06-12 11:46:25 -07:00
4ca401c394 build(docs-infra): upgrade cli command docs sources to 7da10691d (#30999)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](e567d15ae...7da10691d):

**Modified**
- help/build.json

##

PR Close #30999
2019-06-12 11:45:07 -07:00
3dcd5ebdbc fix(ivy): unable to bind to implicit receiver in embedded views (#30994)
To provide some context: The implicit receiver is part of the
parsed Angular template AST. Any property reads in bindings,
interpolations etc. read from a given object (usually the component
instance). In that case there is an _implicit_ receiver which can also
be specified explicitly by just using `this`.

e.g.

```html
<ng-template>{{this.myProperty}}</ng-template>
```

This works as expected in Ivy and View Engine, but breaks in case the
implicit receiver is not used for property reads. For example:

```html
<my-dir [myFn]="greetFn.bind(this)"></my-dir>
```

In that case the `this` will not be properly translated into the generated
template function code because the Ivy compiler currently always treats
the `ctx` variable as the implicit receiver. This is **not correct** and breaks
compatibility with View Engine. Rather we need to ensure that we retrieve
the root context for the standalone implicit receiver similar to how it works
for property reads (as seen in the example above with `this.myProperty`)

Note that this requires some small changes to the `expression_converter`
because we only want to generate the `eenextContent()` instruction if the
implicit receiver is _actually_ used/needed. View Engine determines if that is the case by recursively walking through the converted output AST and
checking for usages of the `o.variable('_co')` variable ([see here][ve_check]). This would work too for Ivy, but involves most likely more code duplication
since templates are isolated in different functions and it another pass
through the output AST for every template expression.

[ve_check]: 0d6c9d36a1/packages/compiler/src/view_compiler/view_compiler.ts (L206-L208)

Resolves FW-1366.

**NOTE**: Patch version of 58be2ff884
(#30897)

PR Close #30994
2019-06-12 11:44:11 -07:00
49307f0595 fix(bazel): do not modify tsconfig.json (#30984)
This is a patch PR for https://github.com/angular/angular/pull/30877

PR Close #30984
2019-06-11 15:40:39 -07:00
762fc28fee feat(docs-infra): layout ui polish (#30883)
PR Close #30883
2019-06-11 14:20:36 -07:00
338e58c278 docs: use const in dynamic-component-loader example (#30888)
Use const instead of let. Some of the variables are never reassigned, so it is preferred to use const over let

PR Close #30888
2019-06-11 14:20:00 -07:00
7e2ed89208 docs: fix a grammar mistake (#30949)
Grammar mistake is in the JsonPipe section
PR Close #30949
2019-06-11 14:19:17 -07:00
56a3dcf44c build(docs-infra): upgrade cli command docs sources to e567d15ae (#30971)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](d09f130ce...e567d15ae):

**Modified**
- help/build.json
- help/generate.json
- help/new.json
- help/serve.json
- help/test.json

##

PR Close #30971
2019-06-11 14:17:32 -07:00
501bacdcf6 build: update golden for //packages/core/test/bundling/injection:symbol_test (#30965)
PR Close #30965
2019-06-11 10:54:28 -07:00
c5f2979a87 build(bazel): update to nodejs rules 0.31.1 & bazel 0.26.1 (#30965)
* entry_point attribute of nodejs_binary & rollup_bundle is now a label
* nodejs rules 0.30.1 has new feature to symlink node_modules with yarn_install and bazel 0.26.0 includes new managed_directories feature which enables this
* Symlinking of node_modules for yarn_install temporarily disabled (except for integration/bazel) until the fix for https://github.com/bazelbuild/bazel/issues/8487 makes it into a future bazel release. This is needed to work-around issue: yarn_install & npm_install with managed directories can't handle deleted or manually regenerated node_modules folder [https://github.com/bazelbuild/rules_nodejs/issues/802]. Underlying issue has been fixed in Bazel https://github.com/bazelbuild/bazel/issues/8487 but hasn't landed in a release yet

PR Close #30965
2019-06-11 10:54:28 -07:00
fe02462b5f build(docs-infra): update @angular/* to v8.1.0-next.1 and @angular/material to v8.0.0 (#30935)
PR Close #30935
2019-06-11 00:11:36 +00:00
3000d19ad1 build(docs-infra): update @angular/cli to v8.0.2 (#30935)
This restores named lazy chunks, which were broken during beta/rc (i.e.
the lazy chunks were named 0/1/2/...).

PR Close #30935
2019-06-11 00:11:36 +00:00
dcf9f05c9a docs: use Node.js consistently (#30934)
PR Close #30934
2019-06-11 00:09:49 +00:00
ba56f3c15b refactor(docs-infra): avoid hard-coding URLs to redirect on archive mode (#30894)
Related discussion:
https://github.com/angular/angular/pull/30894#pullrequestreview-246731995

PR Close #30894
2019-06-11 00:07:43 +00:00
865ad56e9a fix(docs-infra): do not redirect docs URLs on archive deployments (#30894)
To avoid showing outdated info (such as events, resources, etc.) but
still allow people to see docs for older versions, we redirect
non-documentation URLs to `/docs`. Recently(-ish) we have added
documentation content under the `/cli/...` and `/start/...`
path-prefixes, but we haven't added them to the list of documentation
URLs that should not be redirected. As a result, on archive deployments
(e.g. https://v7.angular.io/cli), they are redirected to `/docs`, making
it impossible to see the documentation for these versions (unless you
know about the `?mode=stable` work-around).

This commit fixes it by adding `cli` and `start` to the list of
documentation URLs that are excluded from redirection.

PR Close #30894
2019-06-11 00:07:43 +00:00
5cda2a041b refactor(docs-infra): make archive redirection tests DRY (#30894)
PR Close #30894
2019-06-11 00:07:43 +00:00
6a484853a9 build: update rules_nodejs and clean up bazel warnings (#30370) (#30763)
Preserve compatibility with rollup_bundle rule.
Add missing npm dependencies, which are now enforced by the strict_deps plugin in tsc_wrapped

PR Close #30370

PR Close #30763
2019-06-10 23:58:54 +00:00
e6ac289518 build: update to Bazel 0.26 (#30370) (#30763)
PR Close #30370

PR Close #30763
2019-06-10 23:58:54 +00:00
4e8614bb92 fix(common): expose the HttpUploadProgressEvent interface as public API (#30852)
Fixes #30814

PR Close #30852
2019-06-07 08:47:48 -07:00
9ace748d3a docs: add dev.to link to the help section (#30873)
PR Close #30873
2019-06-07 08:47:02 -07:00
08c38a1f99 fix(service-worker): avoid uncaught rejection warning when registration fails (#30876)
Service worker API `navigator.serviceWorker.register` can fail in multiple ways.
For example, in Chrome, with an unstable network connection you can have the
following error: `An unknown error occurred when fetching the script.`

In the current state, it creates an `Uncaught (in promise) TypeError:` style of
error, which cannot be caught by the user on his own.

I think it's better to log the error over raising an error that cannot be
caught.

PR Close #30876
2019-06-07 08:46:26 -07:00
9aeef0afdb build(docs-infra): fail hard if the CLI source is not what we expect (#30901)
Previously we just logged a warning but we should fail
to prevent silently allowing the docs to look wrong if
something changes on the CLI side of things.

PR Close #30901
2019-06-07 08:45:48 -07:00
8aef446373 build(docs-infra): upgrade cli command docs sources to d09f130ce (#30909)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](e8bdfe6b9...d09f130ce):

**Modified**
- help/serve.json

##

PR Close #30909
2019-06-07 08:44:42 -07:00
f7ee91a17c build(docs-infra): remove unneeded allowEmptyCodegenFiles option in Ivy mode (#30911)
Previously, when switching to Ivy mode (e.g. to run tests on CI), we had
to add `allowEmptyCodegenFiles: true` to the `angularCompilerOptions` in
`tsconfig.app.json`.

This isn't necessary any more (potentially since we switched to dynamic
imports for loading lazy modules in #30704), so this commit removes it
from the `switch-to-ivy.js` script.

PR Close #30911
2019-06-07 08:43:50 -07:00
8ae0afd3f8 fix(ivy): ngcc - remove unused import to make linting pass (#30914)
The failure is caused by 65f20107f. The unused [`writeFile` import][1]
seems to be a result of merge conflict resolution (since it is not
present on the original PR (#30831).

[1]: 65f20107fe (diff-4840f884874632c2fbfdb64a26213396R9)

PR Close #30914
2019-06-07 08:43:19 -07:00
be82270493 feat(docs-infra): white background and corresponding figure updates (#28396)
PR Close #28396
2019-06-06 13:48:16 -07:00
4cef2c1236 build(docs-infra): fix CLI command github links (#30889)
The "view" links were broken because the version used to
compute the git tag for the GitHub URL included a build SHA.
Now we clean that off before using it in the URL.

The links are to the JSON schema that defines the documentation for
the command. This is accurate but confusing because the content for the
long description is stored in a separate markdown file referenced from this
schema file.
This commit adds a second set of links for the long description, if it exists,
which links directly to the markdown file.

Closes #30700

PR Close #30889
2019-06-06 08:49:38 -07:00
26e3615e19 fix(core): TypeScript related migrations should cater for BOM (#30719)
fix(@schematics/angular): TypeScript related migrations should cater for BOM

In the CLI `UpdateRecorder` methods such as `insertLeft`, `remove` etc.. accepts positions which are not offset by a BOM. This is because when a file has a BOM a different recorder will be used https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72 which caters for an addition offset/delta.

The main reason for this is that when a developer is writing a schematic they shouldn't need to compute the offset based if a file has a BOM or not and is handled out of the box.

Example
```ts
recorder.insertLeft(5, 'true');
```

However this is unfortunate in the case if a ts SourceFile is used and one uses `getWidth` and `getStart` method they will already be offset by 1, which at the end it results in a double offset and hence the problem.

Fixes #30713

PR Close #30719
2019-06-06 08:44:56 -07:00
65f20107fe fix(ivy): ngcc - use spaces in overwritten package.json content for readability (#30831)
When ngcc processes an entrypoint, it updates `package.json` with
metadata about the processed format. Previously, it overwrote the
`package.json` with the stringified JSON object without spaces. This
made the file difficult to read (for example when looking at the file
while debugging an ngcc failure).

This commit fixes it by using spaces in the new `package.json` content.

PR Close #30831
2019-06-05 21:24:47 -07:00
5a7bcd1862 fix(bazel): Load global stylesheet in dev and prod (#30879)
Global stylesheet should be injected as a <link> tag in index.html for
both dev and prod app.

PR Close #30879
2019-06-05 21:20:59 -07:00
152ea36c80 build: unable to run build-packages-dist script on windows (#30853)
Currently it's not possible to run the `./scripts/build-packages-dist.sh` script on Windows because
`bazel query` returns CRLF line-endings which result on array expansion in Bazel target names
that end with a carriage return (e.g. `//packages/core\r`). This then results in a build failure where
Bazel complains that target names should not end with a carriage return.

In order to fix this, we just strip off the carriage return line-endings from the bazel query stdout. Ideally
the script will be ported to a plain Node script eventually, but for now it prevents Windows users from
building the release packages and the simple workaround seems reasonable and sufficient.

PR Close #30853
2019-06-05 09:05:29 -07:00
ea2adb104b docs: correct typos and formatting in the Getting Started guide (#30758)
PR Close #30758
2019-06-04 13:37:27 -07:00
19caace2ab docs(service-worker): mention that HTTPS is required, unless on localhost (#30847)
Fixes #30823

PR Close #30847
2019-06-04 12:03:12 -07:00
ccc1c27461 refactor: Move away from index signature based "updateCache". (#30518)
We're deprecating the index signature overloads in favor of using a Map.

PR Close #30518
2019-06-04 12:02:13 -07:00
97268b95f7 docs: update example dependencies to 8.x release (#30755)
PR Close #30755
2019-06-04 11:53:56 -07:00
7c41abe64a docs: rename component for constructor example (#30845)
PR Close #30845
2019-06-04 11:52:58 -07:00
991e138650 fix(ivy): unable to project into multiple slots with default selector (#30803)
With View engine it was possible to declare multiple projection
definitions and to programmatically project nodes into the slots.

e.g.

```html
<ng-content></ng-content>
<ng-content></ng-content>
```

Using `ViewContainerRef#createComponent` allowed projecting
nodes into one of the projection defs (through index)

This no longer works with Ivy as the `projectionDef` instruction only
retrieves a list of selectors instead of also retrieving entries for
reserved projection slots which appear when using the default
selector multiple times (as seen above).

In order to fix this issue, the Ivy compiler now passes all
projection slots to the `projectionDef` instruction. Meaning that
there can be multiple projection slots with the same wildcard
selector. This allows multi-slot projection as seen in the
example above, and it also allows us to match the multi-slot node
projection order from View Engine (to avoid breaking changes).

It basically ensures that Ivy fully matches the View Engine behavior
except of a very small edge case that has already been discussed
in FW-886 (with the conclusion of working as intended).

Read more here: https://hackmd.io/s/Sy2kQlgTE

NOTE: This is the patch version of #30561

PR Close #30803
2019-06-03 11:44:44 -07:00
d00b421402 docs: fix quickstart link in readme (#30807)
PR Close #30807
2019-06-03 11:43:59 -07:00
06ffed5141 docs: document UrlTree in guard return type in cheatsheet (#30822)
Add UrlTree to the types of returned values in guard methods

PR Close #30822
2019-06-03 11:43:26 -07:00
5a15126520 docs(core): fix typo in style bindings comment (#30661)
PR Close #30661
2019-06-03 09:01:06 -07:00
9e4b2f1a4f docs: fix a small typo in injectable decorator description (#30785)
PR Close #30785
2019-06-03 08:56:22 -07:00
393529d3b5 docs: update example references from "my-app" to "app-root" (#30789)
"app" is the default prefix for CLI projects when generating components.
This updates our examples to conform that that default

Closes #19778

PR Close #30789
2019-06-03 08:55:39 -07:00
81b75590d7 docs(docs-infra): compile module first for Ivy when loading element modules (#30704)
In View Engine, NgModule factories are created for each NgModule and loaded when the module is requested. Ivy doesn't generate the
factories by design and only loads the module class, so it must be compiled after being loaded.

PR Close #30704
2019-05-31 15:24:23 -07:00
151f0f4b2c refactor(docs-infra): update loading of custom elements to use dynamic import syntax (#30704)
Removes the usage of `NgModuleFactoryLoader` and string-based imports for lazy loading.

PR Close #30704
2019-05-31 15:24:23 -07:00
f88f941008 docs: increase color contrast on elements in tutorial
This increases the color contrast of elements in the tutorial (parts 1-6)
in order to meet WCAG 2.0 AA standards.
2019-05-31 15:23:33 -07:00
0e17958640 fix(docs-infra): add v7 in versions dropdown (#30775)
Fixes #30769

PR Close #30775
2019-05-31 15:19:54 -07:00
e82b45c8a7 docs(docs-infra): remove deprecated Buffer usage from stackblitz builder (#30369)
Fixes #30364

PR Close #30369
2019-05-31 09:56:23 -07:00
8422ef2a93 fix(docs-infra): update tooltip of events link (#30643)
PR Close #30643
2019-05-31 09:50:45 -07:00
cdf586d0d2 build(docs-infra): upgrade cli command docs sources to e8bdfe6b9 (#30777)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](9a3d36c98...e8bdfe6b9):

**Modified**
- help/update.json

##

PR Close #30777
2019-05-31 09:45:09 -07:00
3828c89792 ci: add reviewer group for deprecations guide (#30722)
PR Close #30722
2019-05-30 20:45:59 -07:00
0f352b6350 docs: add final release date and update future schedule (#30712)
PR Close #30712
2019-05-30 19:39:24 -07:00
06bdecffb9 docs: remove mention of project settings from analytics (#30701)
This settings are not yet implemented and will be available in 8.1.

PR Close #30701
2019-05-30 13:42:35 -04:00
99ddec152b docs(ivy): fix symbol in example AST (#30745)
PR Close #30745
2019-05-30 13:41:52 -04:00
31aba96fcb docs: improve glossary for entry-point. (#29433)
PR Close #29433
2019-05-30 13:40:55 -04:00
facce2c9fd docs: fix typo in upgrade guide example (#30428)
An code snippet from a `package.json` file used `script`
rather than `scripts`.

Fixes #30418

PR Close #30428
2019-05-30 13:40:07 -04:00
edaf058548 docs: fix closing tags in deprecation summary (#30735)
fix closing tags in "Cannot assign to template variables" section

PR Close #30735
2019-05-30 13:38:54 -04:00
4bff2d0c8c docs: fix deprecation information (#30717)
PR Close #30717
2019-05-30 13:38:34 -04:00
cfc608aaf3 docs: merge duplicated platform-webworker content in Deprecation Guide (#30651)
fix issue of duplicate anchors/ids

PR Close #30651
2019-05-30 13:36:30 -04:00
6d9f5fcddb docs(elements): move clarification about custom elements (#30594)
Moved clarification that "custom elements" are a subtype of Web Components to the first use of the term "custom elements"

PR Close #30594
2019-05-30 13:35:15 -04:00
b19a05c25a docs(common): fix typo in ngSwitch directive description (#30483)
PR Close #30483
2019-05-30 13:34:22 -04:00
bd75b3b7b3 docs: fix the sequence of creating class in HTTP tutorial (#30566)
For more accurate procedure of creating a class in the "Tour of Heroes" app, updated the sequence of creating one class.

PR Close #30566
2019-05-30 13:32:53 -04:00
1c67b9063b docs: clarify usage of using /deep/ in component styles guide (#30452)
Updated the description regarding the (deprecated) /deep/ pseudo-selector to clarify its propensity to bleed styles across components and its solution

closes #29967

PR Close #30452
2019-05-30 13:32:32 -04:00
9a9ae60e0e docs: code sample closing in ivy.md (#30711)
PR Close #30711
2019-05-30 13:32:11 -04:00
ae6fa9260a docs: change wording for more clarity in TypeScript Configuration guide (#30748)
"You need to do nothing" indicates the presence of an action (the action of doing nothing) while the goal is to tell the user that no action is required from them. I think "You don’t need to do anything" is better suitable in this context.

PR Close #30748
2019-05-30 13:31:24 -04:00
f8fa2f2a6c docs(core): template-var-assignment schematic should link to deprecation guide (#30702)
Instead of linking to a markdown file explaining what the migration warnings
are about, we should link to the deprecation guide which now also contains
an entry for that schematic. This makes the deprecation explanations
consistent and more centralized.

PR Close #30702
2019-05-29 13:50:35 -04:00
f3ee9a6144 docs: add note to platform-webworker deprecation (#30705)
PR Close #30705
2019-05-28 16:37:58 -07:00
d076c51455 test: improve language service tests performance (#30683)
With this change we reduce the amount of IO operations. This is especially a huge factor in windows since IO ops are slower.

With this change mainly we cache `existsSync` and `readFileSync` calls

Here's the results

Before
```
//packages/language-service/test:test
INFO: Elapsed time: 258.755s, Critical Path: 253.91s
```

After
```
//packages/language-service/test:test
INFO: Elapsed time: 66.403s, Critical Path: 63.13s
```

PR Close #30683
2019-05-28 16:15:02 -07:00
38a7e2a775 release: cut the v8.0.0 release 2019-05-28 10:14:07 -07:00
c61c14a127 docs: remove core.module.ts from file tree in style guide (#30679)
PR Close #30679
2019-05-28 09:27:49 -07:00
652b0959a8 docs: add missing preposition (#30691)
You need do nothing -> You need to do nothing
PR Close #30691
2019-05-28 09:27:24 -07:00
002fbddcf1 docs: add default AOT to migrating projects to Ivy (#30697)
Followup to https://github.com/angular/angular/pull/29380, https://github.com/angular/angular/pull/30238, https://github.com/angular/angular-cli/pull/14537.

PR Close #30697
2019-05-28 09:27:02 -07:00
4761d40a41 docs: fix typo in a declaration alert (#30545)
Co-Authored-By: CaerusKaru <caerus.karu@gmail.com>
PR Close #30545
2019-05-28 09:25:10 -07:00
608e0f0d67 docs: add dynamic import allowed syntax to the deprecation guide (#30545)
PR Close #30545
2019-05-28 09:25:10 -07:00
45718b3b21 build(docs-infra): upgrade cli command docs sources to 9a3d36c98 (#30609)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](fa429865e...9a3d36c98):

**Modified**
- help/analytics.json
- help/build.json
- help/e2e.json
- help/serve.json
- help/test.json
- help/xi18n.json

##

PR Close #30609
2019-05-24 18:19:17 -04:00
b5756bcc39 docs(bazel): remove out of date known issue with Webstorm (#30650)
https://github.com/bazelbuild/intellij/issues/246 was resolved in 2018

PR Close #30650
2019-05-24 13:51:29 -04:00
60f0462049 docs: drop coding conventions from style guide (#30334)
PR Close #30334
2019-05-24 13:46:12 -04:00
9fd22959d3 docs: add Michael Hladky to GDE resources (#30596)
PR Close #30596
2019-05-24 13:40:34 -04:00
d5dd907396 docs(core): static-query migration should use permalink for migration guide (#30649)
8479cb4233 updated the static-query migration
to refer to the new guide on AIO. Unfortunately these URLs are currently not
valid as the guide is only available on `next.angular.io` right now. In order to
make the link work permanently (e.g. if we eventually remove the guide in future
major versions), we use the permalink from the `v8` subdomain.

PR Close #30649
2019-05-24 10:08:17 -05:00
5a6bf7de0e docs: update link to static queries in changelog (#30649)
PR Close #30649
2019-05-24 10:08:16 -05:00
d135bb5e6e release: cut the v8.0.0-rc.5 release 2019-05-23 22:32:48 -07:00
8b9a3e49f2 docs(core): add more info to static query guide (#30646)
PR Close #30646
2019-05-23 22:14:50 -07:00
44e55fe2e4 docs(core): update static query schematic with guide link (#30646)
PR Close #30646
2019-05-23 22:14:50 -07:00
063cc308b6 docs(core): update deprecations guide (#30644)
PR Close #30644
2019-05-23 16:25:49 -07:00
c567135dd5 docs(core): add migration guide for static queries (#30644)
PR Close #30644
2019-05-23 16:25:49 -07:00
361f181c8c feat(platform-webworker): deprecate platform-webworker (#30642)
DEPRECATION:

platform-webworker has been around since the initial release of Angular
version 2. It began as an experiment to leverage Angular's rendering
architecture and try something different: to run an entire web application
in a web worker.

We've learned a lot from this experiment, and have come to the conclusion
that pushing entire applications to run in a web worker is not a recipe for
success for most applications. This is due to a number of unresolved issues,
including:

* Poor or non-existent support for web worker APIs in web crawlers/indexers.
* Poor support in build and bundling tooling.

As a result, as of Angular version 8, we are deprecating the
`platform-webworker` APIs in Angular. This consists of both NPM packages,
`@angular/platform-webworker` and `@angular/platform-webworker-dynamic`.

Going forward, we will focus our efforts related to web workers around their
primary use case of offloading CPU-intensive but not critical work.

FW-1339 #resolve

PR Close #30642
2019-05-23 15:09:49 -07:00
b40844523b feat(core): deprecate integration with the Web Tracing Framework (WTF) (#30642)
DEPRECATION:

Angular previously has supported an integration with the Web Tracing
Framework (WTF) for performance testing of Angular applications. This
integration has not been maintained and likely does not work for the
majority of Angular applications today. As a result, we are deprecating
the integration in Angular version 8.

This deprecation covers the following public APIs:
* `WtfScopeFn`
* `wtfCreateScope`
* `wtfStartTimeRange`
* `wtfEndTimeRange`
* `wtfLeave`

FW-1338 #resolve

PR Close #30642
2019-05-23 15:09:49 -07:00
c8af830ec8 fix(core): require 'static' flag on queries in typings (#30641)
This commit makes the static flag on @ViewChild and @ContentChild required.

BREAKING CHANGE:

In Angular version 8, it's required that all @ViewChild and @ContentChild
queries have a 'static' flag specifying whether the query is 'static' or
'dynamic'. The compiler previously sorted queries automatically, but in
8.0 developers are required to explicitly specify which behavior is wanted.
This is a temporary requirement as part of a migration; see
https://angular.io/guide/static-query-migration for more details.

@ViewChildren and @ContentChildren queries are always dynamic, and so are
unaffected.

PR Close #30641
2019-05-23 15:09:20 -07:00
e2c9ddb33e test(core): update query-specific tests in core (#30626) (#30641)
PR Close #30626

PR Close #30641
2019-05-23 15:09:20 -07:00
04196ec2d0 test(compiler): update examples and compiler tests (#30626) (#30641)
PR Close #30626

PR Close #30641
2019-05-23 15:09:20 -07:00
7323072c5c test(common): update common tests to use static flag (#30626) (#30641)
PR Close #30626

PR Close #30641
2019-05-23 15:09:20 -07:00
f0c5400cab test(core): update core tests (unrelated to queries) to use static flag (#30626) (#30641)
PR Close #30626

PR Close #30641
2019-05-23 15:09:19 -07:00
3f2f937c9f docs: add v8 deprecations (#30598)
PR Close #30598
2019-05-23 13:31:14 -07:00
256fe2421a refactor(core): static-query migration should warn about syntax failures (#30628)
Currently if a project has source-files with syntax failures and the migration
has been started on a broken project, we silently migrate *as much as possible*,
but never notify the developer that the project was in a broken state and that
he can re-run the migration after the failures are fixed.

Additionally the template strategy does not need to exit gracefully if it detects
Angular semantic diagnostics on generated files (template type checking). These
diagnostics are not relevant for the query timing analysis.

PR Close #30628
2019-05-23 10:31:49 -07:00
e6f27bcb0c refactor(core): static-query migration should always use template strategy (#30628)
We are removing the prompt for the `static-query` migration and make the
template strategy the migration strategy for the migration. The usage
strategy is good for best-practices, but for now we want to ensure that
the migration is a seamless as possible and that is only achievable my
re-using the same logic that View Engine uses for determining the
timing of a query.

PR Close #30628
2019-05-23 10:31:48 -07:00
8abcf04a5e docs: update simple stackblitz deployment instructions (#30465)
PR Close #30465
2019-05-22 16:29:45 -07:00
bf38df4eb9 fix(bazel): allow ts_library interop with list-typed inputs (#30600)
_compile_action should take a list since we compute it within one node in the build graph
This needs to be cleaned up since Bazel is getting stricter with
disallowing iteration over depsets

PR Close #30600
2019-05-22 16:22:11 -07:00
79a025306a docs: add new cli builder api guide (#29964)
PR Close #29964
2019-05-22 16:19:54 -07:00
62c936aa49 docs: update node and typescript versions mentioned in docs (#30601)
PR Close #30601
2019-05-22 16:17:42 -07:00
77e1b34d91 docs: update file structure and workspace config for v8 (#30595)
PR Close #30595
2019-05-22 11:20:18 -07:00
26cb128b3c build: remove concurrency from e2e tests (#30547)
There appears to be a race condition with the package.json files during test runs

PR Close #30547
2019-05-22 10:41:19 -07:00
fdbe07982a refactor: Move from Δ back to ɵɵ (#30547)
PR Close #30547
2019-05-22 10:41:19 -07:00
c0e3209915 build: update base SHA for rebase on merge-pr script 2019-05-22 10:40:34 -07:00
70880f0cea refactor(core): migrations should parse cli workspace config as json5 (#30582)
Currently we try to parse CLI workspace configurations gracefully by
using the native `JSON.parse()` method. This means that the CLI workspace
configuration needs to follow the strict JSON specification because otherwise
the migrations would not be able to find TypeScript configurations in the CLI
project where JSON5 workspace configurations are supported.

In order to handle such workspace configurations, we leverage the JSON
parsing logicfrom the `@angular-devkit/core` which is also used by the CLI.

PR Close #30582
2019-05-21 17:26:23 -07:00
221a5ba634 build(docs-infra): upgrade cli command docs sources to fa429865e (#30531)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](d46eb367f...fa429865e):

**Modified**
- help/update.json

##

PR Close #30531
2019-05-21 17:09:18 -07:00
68b08cf782 docs: deprecations summary fix api heading level, remove inject, add index by version (#30400)
PR Close #30400
2019-05-21 13:52:46 -07:00
10560a0872 docs: delete double dashes on ng command in testing guide (#30551)
Closes #30550

PR Close #30551
2019-05-21 13:12:48 -07:00
561e01ddfd fix(core): temporarily remove @deprecated jsdoc tag for a TextBed.get overload (#30514)
PR #29290 introduced a new `TestBed.get` signature and deprecated the existing one.
This raises a lot of TSLint deprecation warnings in projects using a strict TS config (see #29905 for context), so we are temporarily removing the `@deprecated` annotation in favor of a plain text warning until we properly fix it.

Refs #29905
Fixes FW-1336

PR Close #30514
2019-05-21 13:11:22 -07:00
d1345c78f0 docs(docs-infra): add common/upgrade to authors package for API docs (#30567)
This fixes an issue where the common/upgrade packge isn't included
on page reload when changes are made to the common/upgrade package

PR Close #30567
2019-05-21 13:09:10 -07:00
276f9067c8 docs(common): update API docs for unified location service for upgrading (#30567)
PR Close #30567
2019-05-21 13:09:09 -07:00
0e90a4263b docs: document the PR action: rerun CI at HEAD label in TRIAGE_AND_LABELS.md (#30171)
Related to #29098.

PR Close #30171
2019-05-21 13:07:38 -07:00
e4cc1398aa docs: document the PR action: review label in TRIAGE_AND_LABELS.md (#30171)
PR Close #30171
2019-05-21 13:07:38 -07:00
8d1f993ceb docs: add info about who adds/removes labels in TRIAGE_AND_LABELS.md (#30171)
PR Close #30171
2019-05-21 13:07:38 -07:00
df1ab49893 docs: fix spelling of 'its' (#30455)
PR Close #30455
2019-05-21 13:07:13 -07:00
df03fec8a6 refactor(ivy): rewrite flatten function to be more memory efficient (#30468)
The `flatten` function used `concat` and `slice` which created a lot of intermediary
object allocations. Because `flatten` is used from query any benchmark which
used query would exhibit high minor GC counts.

PR Close #30468
2019-05-21 13:06:24 -07:00
c01cae22e1 docs: add section to upgrade guide on lazy loading AngularJS (#30541)
PR Close #30541
2019-05-21 13:06:02 -07:00
5a46f94987 fix(core): remove deprecated TestBed.deprecatedOverrideProvider API (#30576)
BREAKING CHANGE

In PR #19558, we fixed a bug in `TestBed.overrideProvider` where
eager providers were not being instantiated correctly. However,
it turned out that since this bug had been around for quite a bit,
many apps were relying on the broken behavior where the providers
would not be instantiated. To assist in the transition, the
`TestBed.deprecatedOverrideProvider` method was temporarily
introduced to mimic the old behavior so that apps would have a
longer time period to migrate their code.

2 years and 3 versions later, it is time to remove the temporary
method. This commit removes `TestBed.deprecatedOverrideProvider`
altogether. Any usages of `TestBed.deprecatedOverrideProvider`
should be replaced with `TestBed.overrideProvider`. This may mean
that providers that were not created before will now be instantiated,
which could mean that your tests need to provide more mocks or stubs
for the dependencies of the newly instantiated providers.

PR Close #30576
2019-05-21 12:37:18 -07:00
5716605d52 ci(docs-infra): fix test_docs_examples_ivy job (#30593)
Context:
As part of the `test_docs_examples_ivy` job, we run 5 concurrent builds
on each VM (each for a different example/project). Additionally, all
example projects share the same `node_modules/` (via a symlink to
`aio/tools/examples/shared/node_modules/`), so all concurrent builds
operate on the same files.

Previously, we pre-ran ngcc with `--properties module` to process the
fesm5 bundles. Since we have switched to es2015 in 661a57d9e, we now
need the esm2015 bundles. As a result, the initial ngcc run is
redundant and ngcc runs again during each build (to process the fesm2015
bundles). Since there are 5 concurrent builds, we often end up with
multiple ngcc instances processing the same package and trying to write
to the same directories at the same time, causing a
`file already exists` error

This commit fixes it by pre-processing the esm2015 bundles, so there is
no need to re-run ngcc during each concurrent build.

Fixes #30577

PR Close #30593
2019-05-21 12:32:58 -07:00
8043e3131c docs: use dynamic import syntax in examples using lazy loading (#30563)
PR Close #30563
2019-05-21 09:09:35 -07:00
54f7245081 docs(changelog): remove docs-infra changes (#25833)
PR Close #25833
2019-05-21 09:06:46 -07:00
5de24b6dfe docs: move instructions to see changes after the error is fixed in the tutorial (#30529)
docs: List only appears after the error is fixed

When the error happens, the list is not displayed too. Once the error is removed, the heroes list appears, so we can click and see the details.

PR Close #30529
2019-05-21 09:03:49 -07:00
4dc4d7f30a docs: remove gender prefixes from examples (#29972)
PR Close #29972
2019-05-20 16:43:00 -07:00
fcea1a3c22 docs: improve consistency of style guide example (#30504)
The text for entry Style 04-10 of the style guide talks about
FilterTextService however, the example folder structure has the inversed
filename.

PR Close #30504
2019-05-20 16:42:16 -07:00
8bc4da8665 fix(bazel): ng test should run specific ts_web_test_suite (#30526)
PR closes https://github.com/angular/angular/issues/30191

PR Close #30526
2019-05-20 16:40:11 -07:00
a5a2d525ae docs: move old quick start content into new local setup guide (#29651)
PR Close #29651
2019-05-20 10:16:24 -07:00
4690dcecac build: add recommended config files for VSCode remote development (#30450)
Add some recommended config files to use (as is or as basis) for setting
up [remote development using docker containers][1] with VSCode. This is
an opt-in feature. See `.devcontainer/README.md` for more info.

The configuration can be further tweaked/improved, but is a good
starting point.

[1]: https://code.visualstudio.com/docs/remote/containers

PR Close #30450
2019-05-20 10:13:53 -07:00
722b2fa6ed feat(common): stricter types for SlicePipe (#30156)
Adds overloads to the `transform` methods of `SlicePipe`,
to have better types than `any` for `value` and `any` as a return.
With this commit, using `slice` in an `ngFor` still allow to type-check the content of the `ngFor`
with `fullTemplateTypeCheck` enabled in Ivy:

    <div *ngFor="let user of users | slice:0:2">{{ user.typo }}</div>
                                                        |
                                                        `typo` does not exist on type `UserModel`

whereas it is currently not catched (as the return of `slice` is `any`) neither in VE nor in Ivy.

BREAKING CHANGE
`SlicePipe` now only accepts an array of values, a string, null or undefined.
This was already the case in practice, and it still throws at runtime if another type is given.
But it is now a compilation error to try to call it with an unsupported type.

PR Close #30156
2019-05-17 14:21:37 -07:00
124d1abf19 docs: update docs example dependencies to version 8 (#30385)
PR Close #30385
2019-05-17 14:16:56 -07:00
736d3ef820 docs: add kamil mysliwiec to GDE resources (#30508)
PR Close #30508
2019-05-17 13:32:44 -07:00
9b0ad347e1 test(platform-browser-dynamic): avoid swallowing error in CachedResourceLoader test (#30515)
Previously, in order to assert that the promise was not resolved, an
error was thrown when the promise was resolved successfully. At the
same, `.catch()` was used to silence the (expected) promise rejection.
However, the chained `.catch()` handler would also catch (and swallow)
the error thrown on resolving the promise, making the test pass, even if
the promise was not rejected.

This commit fixes it by ensuring that the error thrown on resolving the
promise is not caught by the rejection handler.

PR Close #30515
2019-05-16 20:14:05 -07:00
d2598ace0a test(platform-browser-dynamic): make CachedResourceLoader tests more reliable (#30515)
Previously, [this test][1] would occasionally fail (e.g. on CI) with
"Template cache was not found in $templateCache". This was due to a
combination of:
1. [That test][2] (which removes the cache) being run right before the
   failing test.
2. The async `TestBed.compileComponents()` operation run in the
   `beforeEach()` block (which sets the cache) not having completed
   before the `it()` block.

This commit fixes the issue by ensuring the cache is always set, before
instantiating `CachedResourceLoader`.

This commit also moves some operations that are only needed in one test
from the `beforeEach()` block to that test's `it()` block.

[1]: 79903b1842/packages/platform-browser-dynamic/test/resource_loader/resource_loader_cache_spec.ts (L50)
[2]: 79903b1842/packages/platform-browser-dynamic/test/resource_loader/resource_loader_cache_spec.ts (L37)

Fixes #30499

PR Close #30515
2019-05-16 20:14:04 -07:00
4a25e4cf95 build(bazel): update to latest stable chromium 74 on osx and linux for karma under bazel (#30502)
We were on 69 for both of these platforms which is fairly old. This update also requires a temporary patch to the @bazel/karma npm package to disable chrome sandboxing on OSX as it is broken under Bazel as of chromium 73. Windows is still on Chromium 66 but updating this will require upstream changes to rules_webtesting as the archive name & executable name has changed as of 72 for Windows and hard-coded paths in rules_webtesting break things.

PR Close #30502
2019-05-16 14:38:15 -07:00
3f67bf208d docs: add link to location upgrade config (#30331)
PR Close #30331
2019-05-16 11:53:48 -07:00
d85476fd8c docs(docs-infra): add common/upgrade to API package sources (#30331)
Closes #30332

PR Close #30331
2019-05-16 11:53:43 -07:00
9763edf829 refactor(common): update argument length in UrlCodec.areEqual method and AngularJSUrlCodec.areEqual methods (#30331)
dgeni requires that method arguments be at least 2 characters long

PR Close #30331
2019-05-16 11:47:17 -07:00
b6ae54c547 docs: add section to upgrade guide on using the unified location service (#30331)
The LocationUpgradeModule provides a unified way of handling URL updates
across AngularJS and Angular.

PR Close #30331
2019-05-16 11:47:17 -07:00
3de26a84ff fix(bazel): Disable sandbox on Mac OS (#30460)
Removing the sandbox improves build time by almost 40%.

For a hello world (ng new) application:
ng build with sandbox: 22.0 seconds
ng build without sandbox: 13.3 seconds

PR Close #30460
2019-05-16 09:43:54 -07:00
8022d3691b feat(common): add ability to watch for AngularJS URL updates through onUrlChange hook (#30466)
The LocationShim (replacement for `$location`) was added to centralize dealing with the browser URL. Additionally, an `onUrlChange` method was added to Angular's Location service. This PR adds a corresponding method to the LocationShim so updates from AngularJS can be tracked in Angular.

PR Close #30466
2019-05-16 09:43:33 -07:00
581336a918 docs: fix typo in animations doc (#30457)
PR Close #30457
2019-05-15 14:26:12 -07:00
effc58086c docs: correct types in transform method to match specification. (#29812)
PR Close #29812
2019-05-15 14:24:20 -07:00
766615c8a1 docs: fix example "testing" app compilation (#30427)
PR Close #30427
2019-05-15 14:12:23 -07:00
ede4246663 docs: fix the payload in event-binding sample code (#30429)
after reading the context. there are  some clues to infer the payload should be the `item`, not `item.name`.
1.  EventEmitter<Item>.
2.  the desc say that:
The component defines a deleteRequest property that returns an EventEmitter. When the user clicks delete, the component invokes the delete() method, telling the EventEmitter to emit an **Item** object.

PR Close #30429
2019-05-15 14:12:02 -07:00
bb8a6abbf2 test(ivy): move render3 query tests to acceptance (#30382)
Moves all manual render3 query tests that use the `elementProperty`
instructions to TestBed acceptance tests.

PR Close #30382
2019-05-15 14:11:38 -07:00
32daa930d0 fix(router): type cast correctly for IE 11 bug breaking URL Unification when comparing objects (#30464)
PR #30393 corrected behavior where Object.keys sometimes returns an `undefined` value. However, the types didn't reflect this in the code. That fix actually missed one value that could return `undefined`. This PR corrects this by casting the types to what they can be in IE 11. This ensures the code behaves as it should when this edge case comes up.

PR Close #30464
2019-05-15 14:09:54 -07:00
b6aa99d3a7 release: cut the v8.0.0-rc.4 release 2019-05-15 12:19:51 -07:00
e10b213784 refactor(ivy): deprecate ɵɵinject and ɵɵdefineInjectable (#30467)
- They are to be removed before the end of RC

PR Close #30467
2019-05-15 11:40:33 -07:00
a67cf99b0c refactor(ivy): mark ΔdefineInjectable as codeGenApi. (#30467)
PR Close #30467
2019-05-15 11:40:33 -07:00
04d04fd147 refactor(ivy): replace ɵɵ with Δ (#30467)
PR Close #30467
2019-05-15 11:40:33 -07:00
17361d2b2c Revert "Revert "fix(router): fix a problem with router not responding to back button (#30160)" (#30320)" (#30344)
This reverts commit 8ced321bb6.

PR Close #30344
2019-05-15 10:14:48 -07:00
9b88920aa9 fix(router): ensure navigations start with the current URL value incase redirect is skipped (#30344)
In some cases where multiple navigations happen to the same URL, the router will not process a given URL. In those cases, we fall into logic that resets state for the next navigation. One piece of this resetting is to set the `browserUrlTree` to the most recent `urlAfterRedirects`i.

However, there was bug in this logic because in some cases the `urlAfterRedirects` is a stale value. This happens any time a URL won't be processed, and the previous URL will also not be processed. This creates unpredictable behavior, not the least of which ends up being a broken `back` button.

This PR kicks off new navigations with the current value the router assumes is in the browser. All the logic around how to handle future navigations is based on this value compared to the current transition, so it's important to kick off all new navigations with the current value so in the edge case described above we don't end up with an old value being set into `browserUrlTree`.

Fixes #30340
Related to #30160

PR Close #30344
2019-05-15 10:14:47 -07:00
b12e76d1d3 refactor: remove toplevel property accesses (#30470)
PR Close #30470
2019-05-15 10:00:12 -07:00
af001a8cbd test: add integration test for side effects (#30470)
This new tests keeps track of the known side effects for Angular ES modules.

PR Close #30470
2019-05-15 10:00:12 -07:00
db64b014f8 Revert "fix(core): CSS sanitizer now allows parens in file names (#30322)" (#30463)
This reverts commit 728db88280.

We're reverting this commit for now, until it can be subjected to a more
thorough security review.

PR Close #30463
2019-05-14 14:49:40 -07:00
7e34975bb0 refactor(core): improve messages for static-query migrations (#30458)
Slightly improves the messages for the static-query migration in order
to make the terminal output less verbose but more helpful. Unfortunately
we are limited in what we can print due to the devkit not providing much
utilities for printing good messages from a migration schematic.

PR Close #30458
2019-05-14 14:04:44 -07:00
0fa48e8c00 fix(core): static-query migration should not fallback to test strategy (#30458)
Currently if something fails in the selected strategy (e.g. AOT failures),
the migration currently accidentally falls back to the test strategy. This
is not helpful as we want to give developers the possibility to re-run
the migration after fixing potential AOT failures.

PR Close #30458
2019-05-14 14:04:44 -07:00
fde3f467e2 fix(core): static-query migration errors not printed properly (#30458)
Apparently the devkit logger is not able to properly print
out error objects, so we need to convert them to a string
before in order to make the error visible to the user.

This is not testable without an e2e test that validates the CLI
terminal output.

PR Close #30458
2019-05-14 14:04:44 -07:00
7b378a6920 docs: update ivy preview page (#30355)
PR Close #30355
2019-05-14 12:17:26 -07:00
3136d9ff2e fix(bazel): Use existing npm/yarn lock files (#30438)
This PR fixes Bazel builder to create yarn_install rule in WORKSPACE if
yarn.lock is present, otherwise npm_install rule if package-lock.json is
present. If none is present, default to yarn_install and create an empty
yarn.lock file.

PR closes https://github.com/angular/angular/issues/30164
PR closes https://github.com/angular/angular/pull/30359

PR Close #30438
2019-05-14 11:37:33 -07:00
325e6cf557 build(docs-infra): update http-server to 0.11.1 (#30401)
Fixes #30363

PR Close #30401
2019-05-14 09:55:47 -07:00
381d7c4e44 test(ivy): move render3 directive tests to acceptance (#30432)
Moves all manual render3 directive tests to TestBed acceptance
tests.

PR Close #30432
2019-05-14 09:37:01 -07:00
1b6f3c1ead test(ivy): move render3 renderer_factory tests to acceptance (#30435)
Moves all manual render3 tests which are located within the
`renderer_factory_spec.ts` file to acceptance tests. A few tests
that use Ivy-specific logic which is not replicable with `TestBed`
remain in the render3 folder (e.g. using `renderTemplate`)

Additionally migrated tests that assert the lifecycles of the
renderer_factory are set to *ivy only* as the lifecycle seems
to be different in Ivy. Tracked with: FW-1320

PR Close #30435
2019-05-14 09:36:24 -07:00
c38349127c fix(router): IE 11 bug can break URL unification when comparing objects (#30393)
This PR fixes an issue where IE 11 can return `undefined` in with an `Object.keys` call. Solution is to add a runtime check on the value. Based on the types being passed, this shouldn't be necessary, but is needed only for IE 11. Unit test doesn't work for this PR because it can't be replicated easily.

PR Close #30393
2019-05-13 11:40:43 -07:00
a4817729a2 test: fix ngtsc tests in windows (#30146)
This commit fixes the following test target in windows

```
//packages/compiler-cli/test/ngtsc:ngtsc
```

PR Close #30146
2019-05-13 11:06:13 -07:00
61c343e3eb test: fix several Bazel compiler tests in windows (#30146)
```
//packages/compiler-cli/test:ngc
//packages/compiler/test:test
```

This also address `node_modules` to the ignored paths for ngc compiler as otherwise the `ready` is never fired

Partially addresses #29785

PR Close #30146
2019-05-13 11:06:13 -07:00
24e6c1e80d release: ts_api_guardian (#30120)
PR Close #30120
2019-05-13 10:53:35 -07:00
42fc5c9b33 docs: change reference to jQuery programmers (#30386)
The section on Data Binding makes a reference to "any experienced jQuery programmer" which is a bit too narrow since there are also  programmers that write their front end in pure JavaScript.
PR Close #30386
2019-05-13 10:49:27 -07:00
33e7b285ca build(docs-infra): upgrade cli command docs sources to d46eb367f (#30415)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](cd7920355...d46eb367f):

**Modified**
- help/build.json
- help/e2e.json
- help/serve.json
- help/test.json
- help/xi18n.json

##

PR Close #30415
2019-05-13 10:28:18 -07:00
74afdc37da build: ignore .devcontainer/ directory (#30417)
This makes it easier to experiment with VSCode's
[remote development using docker containers][1] feature.

In the future, we may check in the necessary files for users to use this
feature, but for now ignoring the directory makes it easier play around
and evaluate the feature.

[1]: https://code.visualstudio.com/docs/remote/containers

PR Close #30417
2019-05-13 10:17:16 -07:00
3c1ffba0ad test(ivy): move pipe tests into acceptance (#30389)
Moves over the tests from `pipe_spec` into `acceptance`. Note that the two `WrappedValue` tests haven't been moved over, because impure pipes always throw "changed after checked" errors in `TestBed`. This seems to be consistent with ViewEngine.

PR Close #30389
2019-05-10 14:35:57 -07:00
14c0017db8 build: upgrade zone.js to 0.9.1 (#30260)
Close 30203

resolves the issue that zone-legacy XHR issue

PR Close #30260
2019-05-10 14:25:56 -07:00
4878f4890b build(docs-infra): ensure hidden cli commands are excluded from sitemap.xml (#30395)
Previously, the processor that excludes certain cli commands
(`filterHiddenCommand`) was being run after the `createSitemap`
processor, resulting in those commands to be present in `sitemap.xml`,
while the actual pages where missing. This also resulted in 404s, when
search engine crawlers tried to index the missing URLs.

This commit fixes it by ensuring that the `filterHiddenCommand`
processor is run before the `createSitemap` processor.

PR Close #30395
2019-05-10 11:56:39 -07:00
b7edef0cd3 docs: remove mention of chrome 41 from differential loading (#30390)
PR Close #30390
2019-05-10 11:55:12 -07:00
39fa937ab9 test(ivy): move output tests to acceptance (#30372)
Moves most of the tests in `output_spec` into `acceptance`. Note that one test is left in `render3`, because it's testing mixing in custom logic with instructions which we can't replicate using `TestBed`.

PR Close #30372
2019-05-10 09:27:57 -07:00
2977829c67 test(ivy): move content projection tests to acceptance (#30357)
Moves all manual `render3` content projection tests that use
the `ɵɵelementProperty` to acceptance tests. Additionally a
few other content projection tests were moved over to
acceptance. Eventually we'll be able to move all remaining
content projection tests to acceptance.

PR Close #30357
2019-05-10 09:18:37 -07:00
dbe845e048 test(ivy): use TestBed for render3 component tests (#30282)
PR Close #30282
2019-05-10 09:18:19 -07:00
e562acc884 feat(bazel): use rbe_autoconfig() and new container. (#29336)
After this PR is merged, maintainers no longer need to update .bazelrc
file, toolchain and platform related flags for RBE builds and tests
(unless there is a breaking change in Bazel related to those flags).

Maintainers just need to update the pin of @bazel-toolchains repo
regularly in the packages/bazel/package.bzl file according to
https://releases.bazel.build/bazel-toolchains.html to include the
latest checked-in toolchain configs. If rbe_autoconfig() cannot find
appropriate toolchain configs for the version of Bazel in the version of
@bazel_toolchains repo that is currently used by this project, it will pull
down the container and generate the configs on the fly as the beginning
of the build/test.

PR Close #29336
2019-05-09 14:58:34 -07:00
e295c6a0ae fix(core): static-query usage migration strategy should detect ambiguous query usage (#30215)
Currently we always just set the timing to `false` if we aren't
able to analyze a given call expression or new expression. e.g.

```ts
ngOnInit() {
  thirdPartyCallSync(() => this.query.doSomething())
}
```

In that case the `thirdPartyCallSync` function comes from the `node_modules`
and is only defined through types while there is no code for the
actual function logic that can be analyzed. This makes it impossible
to tell whether the given call expression actually causes the specified
arrow function to be executed synchronously or not. In order to be able
to make this better, we now peek into the passed arrow function and
check for a synchronous query usage. If so, we set the query timing to
static and mark it as ambiguous. This ensures that the usage strategy is
less "magical" and more correct with third-party code.

Additionally since functions like `setTimeout` are not analyzable but known
to be asynchronous, there is a hard-coded list of known functions which
shouldn't be marked as ambiguous.

Resolves FW-1214. As planned within https://hackmd.io/hPiLWpPlQ4uynC1luIBdfQ

PR Close #30215
2019-05-09 14:39:06 -07:00
10b43355f8 test(core): update core_all size-tracking golden file (#30257)
Even though we don't run the size-tracking test on CI
right now, we update the golden size map as part of
the size-tracking tool update. The size-map difference
should generally be kept up-to-date to be able to
determine which PRs contribute size to a given file.

PR Close #30257
2019-05-09 12:55:17 -07:00
d4e7587bd8 build: size-tracking test should support max-byte threshold (#30257)
Based on discussion that happened on the PR that introduced
the size-tracking tool, we want to have another threshold for
the raw byte difference. This allows us to better control for
which changes the size-tracking tool should report a difference.

See: https://github.com/angular/angular/pull/30070#discussion_r278332315

PR Close #30257
2019-05-09 12:55:17 -07:00
cabe03cf6d docs(forms): properly convert number to string for formControlName input (#29473)
PR Close #29473
2019-05-09 11:27:49 -07:00
0cefa9e342 docs: fix filename in example headers for provider guides (#29889)
PR Close #29889
2019-05-09 11:27:01 -07:00
e073daa48e docs(forms): add comment of the value (#29898)
PR Close #29898
2019-05-09 11:25:58 -07:00
994d48a96e test(ivy): update devkit in hello world tests to rc.2 (#30162)
PR Close #30162
2019-05-09 11:24:52 -07:00
806f8118c8 docs: remove reference to e2e applications (#30324)
This is no longer applicable in angular version 8.

PR Close #30324
2019-05-09 11:23:06 -07:00
dd299f9eb2 fix(core): static-query migration should handle queries on accessors (#30327)
Currently the static-query migration ignores queries declared on getters
or setters as these are not part of a `PropertyDeclaration`. We need to
handle these queries in order to cover all queries within a given project.

The usage strategy is not able to detect timing for queries on accessors,
so we add a TODO and print a message. The template strategy is able
to detect the proper timing for such queries because it's not dependent
on detecting the usage of the query.

Resolves FW-1215

PR Close #30327
2019-05-09 11:22:37 -07:00
49ec3f312c fix(docs-infra): Handle search criteria from Chrome search providers (#30345)
fixes #30242

PR Close #30345
2019-05-09 11:21:12 -07:00
71eba450e6 fix(bazel): pass correct arguments to http_server in Windows (#30346)
Under Windows, the server binary has an extension of  `.exe` and the current logic is not handling that.

Partially addresses: #29785

PR Close #30346
2019-05-09 11:20:52 -07:00
192f108b0f fix: ensure strict mode when evaluating in JIT (#30122)
PR Close #30122
2019-05-08 14:34:10 -07:00
dd8651db73 fix(core): CSS sanitizer now allows parens in file names (#30322)
Resolves an issue where images that were created with a name like `'foo (1).png'` would not pass CSS url sanitization.

PR Close #30322
2019-05-08 14:22:44 -07:00
5bbbe3f684 docs(router): Move ActivatedRoute example to mini-app (#29755)
PR Close #29755
2019-05-08 13:52:23 -07:00
a71d8a837b fix(core): static-query migration should gracefully exit if AOT compiler throws (#30269)
The static-query template strategy leverages the AOT compiler
in order to determine the query timing. Unfortunately the AOT
compiler has open bugs that can cause unexpected failures which
make the template strategy unusable in rare cases. These rare
exceptions need to be handled gracefully in order to avoid confusion
and to provide a more smooth migration.

Additionally migration strategy setup failures are now reported with
stack traces as the `ng update` command does not print stack traces.
This makes it easier to reproduce and report migration issues.

PR Close #30269
2019-05-08 11:54:34 -07:00
e8ceae14e1 fix(core): migrations not always migrating all files (#30269)
In an Angular CLI project scenario where projects only reference
top-level source-files through the `tsconfig` `files` option, we currently
do not migrate referenced source-files. This can be fixed checking all
referenced source-files which aren't coming from an external library.

This is similar to how `tslint` determines project source-files.

PR Close #30269
2019-05-08 11:54:34 -07:00
c3246e6f16 fix(core): static-query migration fails with default parameter values (#30269)
Currently when someone has a call expression within the `ngOnInit` call
and we try to peek into that function with respect to the current function
context, the schematic errors because a call expression argument is
undefined. This is valid because the target function declaration defines
that parameter with a default value. In order to fix this, we need to
respect parameter default values.

PR Close #30269
2019-05-08 11:54:34 -07:00
685753361e fix(docs-infra): remove scroll position from sessionStorage when a ServiceWorker update has been activated (#29958)
closes #29893

PR Close #29958
2019-05-08 09:23:43 -07:00
6b07711f96 test(core): run schematic tests with public migration collection (#30198)
572b54967c changed how the schematic
tests are executed. Tests no longer use the schematic collection
that is also used by the CLI `ng update` command and therefore
the migration collection could  technically be invalid.

In order to ensure that the public migration collection is guaranteed
to work and to avoid duplication within two schematic collections, the
changes are partially reverted and only the disabled `injectable-pipe`
schematic has its own collection.

PR Close #30198
2019-05-08 09:23:29 -07:00
12fb639b7d fix(core): static-query migration should not prompt if no queries are used (#30254)
Currently we always prompt when the static-query migration runs. This is not
always needed because some applications do not even use `ViewChild` or
`ContentChild` queries and it just causes confusion if developers need to
decide on a migration strategy while there is nothing to migrate.

In order to avoid this confusion, we no longer prompt for a strategy
if there are no queries declared within the project.

PR Close #30254
2019-05-08 09:22:49 -07:00
644925fd0c build: add jasonaden to angular/upgrade in CODEOWNERS (#30307)
PR Close #30307
2019-05-08 09:20:25 -07:00
bcc72b0924 test(ivy): move host binding tests to acceptance (#30308)
Switches over all host binding tests to use `TestBed` and to be under `acceptance`.

PR Close #30308
2019-05-08 09:19:44 -07:00
e1091b2ba8 build(docs-infra): upgrade cli command docs sources to cd7920355 (#30326)
Updating [angular#8.0.x](https://github.com/angular/angular/tree/8.0.x) from [cli-builds#8.0.x](https://github.com/angular/cli-builds/tree/8.0.x).

##
Relevant changes in [commit range](73c53266f...cd7920355):

**Modified**
- help/e2e.json
- help/generate.json
- help/update.json

##

PR Close #30326
2019-05-08 09:15:22 -07:00
08841e31d9 Revert "fix(router): fix a problem with router not responding to back button (#30160)" (#30320)
This reverts commit 3327bd8eab.

PR Close #30320
2019-05-07 17:22:25 -07:00
d1fcc2bc13 fix(bazel): Directly spawn native Bazel binary (#30306)
Instead of launching a Node.js process that in turn spawns Bazel binary,
the Builder could now directly spawn the native binary. This makes the
bootup process slightly more efficient, and allows the Builder to
control spawn options. This works with both Bazel and iBazel.

PR Close #30306
2019-05-07 16:51:42 -07:00
fac00442d2 fix(core): consistently use ng:/// for sourcemap URLs (#29826)
Currently, in jit mode, `ngInjectableDef`, `ngDirectiveDef`, `ngPipeDef` and `ngModuleDef` use `ng://`,
which display them in the top domain in Chrome Dev Tools, whereas `ngComponentDef` uses `ng:///` which display components in a separate domain.

You can currently see:

```
AppModule
UserService
ng://
|_ AppComponent
   |_ template.html
|_ AppComponent.js
...
```

This commits replaces all `ng://` with `ng:///` to display every Angular entity in the `ng://` domain.

```
ng://
|_ AppModule
|_ UserService
|_ AppComponent
...
```

PR Close #29826
2019-05-07 15:37:21 -07:00
b8cbcbcf49 release: cut the v8.0.0-rc.3 release 2019-05-07 14:30:37 -07:00
1ed45bd783 docs(aio): add awade jigsaw into resources (#30204)
PR Close #30204
2019-05-07 13:13:22 -07:00
82fd1920b1 docs: update date pipe example for minutes and seconds (#30281) (#30295)
PR Close #30295
2019-05-07 10:29:31 -07:00
f6d7271ec7 refactor: remove tslint no-use-before-declare rule (#30288)
PR Close #30288
2019-05-07 10:25:36 -07:00
c1f3faf1df test: fix several bazel compiler-cli tests in windows (#30189)
```
//packages/compiler-cli/integrationtest:integrationtest
//packages/compiler-cli/test/compliance:compliance
```

Partially addresses #29785

PR Close #30189
2019-05-07 10:21:37 -07:00
97202278f9 fix(router): ensure history.state is set in eager update mode (#30154)
Without this change, `history.state` isn't being set when updating the browser URL in `eager` update mode.

PR Close #30154
2019-05-06 16:09:59 -07:00
132f01c5ca fix(router): fix a problem with router not responding to back button (#30160)
There was a problem with a combination of the `eager` URL update, browser `back` button, and hybrid applications. Details provided in internal ticket http://b/123667227.

This fix handles the problem by setting `router.browserUrlTree` when all conditions have failed, meaning the browser doesn't do anything with the navigation other than update internal data structures. Without this change, the problem was an old value was stored in `router.broserUrlTree` causing some new navigations to be compared to an old value and breaking future navigations.

PR Close #30160
2019-05-06 16:06:59 -07:00
6a987f1b9c docs(forms): fix import line ending (#30290)
PR Close #30290
2019-05-06 16:05:23 -07:00
548b003ed3 fix(compiler-cli): log ngcc skipping messages as debug instead of info (#30232)
Related to https://github.com/angular/angular-cli/issues/14194, https://github.com/angular/angular-cli/pull/14320

PR Close #30232
2019-05-06 14:11:28 -07:00
48dc41de01 docs: fix naming miss and improve anchor reference in router guide (#30225)
Signed-off-by: Richard Lea <chigix@zoho.com>

PR Close #30225
2019-05-06 11:48:05 -07:00
817c2b49bc docs: add explanation on what lazy loading is (#29667)
PR Close #29667
2019-05-06 10:16:58 -07:00
fed07c735c docs(forms): fix ControlValueAccessor registerOnChange code example (#30276)
PR Close #30276
2019-05-06 09:27:12 -07:00
390cac6874 docs: fix targetEntryPointPath description (#30237)
PR Close #30237
2019-05-06 09:21:23 -07:00
8eb0b8bd40 docs: update Wikipedia link to Polyfill description (#30214)
PR Close #30214
2019-05-06 09:20:14 -07:00
d7283c6085 docs: fix example header in singleton services guide to match styleguide (#30097)
Removes the ".0" from code header, as that doesn't match the
recommended code style for service files names.

fixes #29862

PR Close #30097
2019-05-06 09:19:36 -07:00
3fe3a84a4b fix(core): fix interpolate identifier in AOT (#30243)
This commit fixes a regression introduced in PR 29692 where
the interpolate symbol in View Engine was improperly prefixed
with the ɵɵ that signifies private instructions for Ivy. It
resulted in interpolations of 10+ values not working correctly
in AOT mode. This commit removes the prefix.

PR Close #30243
2019-05-02 10:33:34 -07:00
28e4187bd6 fix(docs-infra): update app code to work with Ivy (#28530)
This commit also enables more tests to be run on CI with Ivy.

PR Close #28530
2019-05-01 16:38:33 -07:00
7cbc69c890 fix(ivy): allow R3TestBedCompiler to work in ngcc-processed apps (#28530)
Previously, `R3TestBedCompiler` was dynamically defining an
`@NgModule`-decorated `CompilerModule` class inside a method call.
Since ngcc only processes top-level classes, this class was not
transformed causing failures in unit tests (see #30121 for details).

This commit fixes it by using `compileNgModuleDefs()` directly (similar
to the fix in #30037).

Fixes #30121

PR Close #28530
2019-05-01 16:38:33 -07:00
1dc134bc6b docs: explicitly state purpose of components (#29879)
Current description is vague. I'd love to see this doc explicitly state that components are for reusable sets of UI features instead.

PR Close #29879
2019-05-01 13:38:13 -07:00
6a61d37f95 ci(docs-infra): re-enable aio_monitoring CircleCI jobs and change time (#30168)
The `aio_monitoring_next` CircleCI job was disabled due to a failure in
[302254](https://circleci.com/gh/angular/angular/302254). It turned out
the failure was caused because the job happened to run after a change
had been merged into master and right before it was deployed to
https://next.angular.io/ causing the tests not to match the deployed
version.

This commit re-enables the job and moves it to a different time, when it
is less likely that PRs will be being merged (and thus reducing the risk
of a similar timming issue).

Fixes #30101

PR Close #30168
2019-04-30 16:17:53 -07:00
8d2e92bcfe build(docs-infra): upgrade material and cdk to 8.0.0-rc.0 (#30202)
I bumped the payload size limits to reflect the current values - the changes have been insignificant.

PR Close #30202
2019-04-29 18:46:54 -07:00
5038f5c909 build(docs-infra): upgrade framework and cli to 8.0.0-rc.2 (#30202)
Brings in small payload size fixes.

PR Close #30202
2019-04-29 18:46:54 -07:00
6eeca70043 refactor(core): static-query migrations fails if options cannot be transformed (#30178)
Currently the `static-query` migrations fails at the final step of
updating a query when the query already specifies options which
cannot be transformed easily. e.g. the options are computed through
a function call: `@ViewChild(..., getQueryOpts());` or `@ViewChild(..., myOptionsVar)`.

In these cases we technically could add additionally logic to update
the query options, but given that this is an edge-case and it's
potentially over-engineering the migration schematic, we just
always add a TODO for the timing and print out the determined
query timing in the console. The developer in that case just needs
to manually update the logic for the query options to contain the
printed query timing.

Potentially related to: https://github.com/angular/angular-cli/issues/14298

PR Close #30178
2019-04-29 13:30:37 -07:00
9f68c35fa9 fix(bazel): Bump ibazel to 0.10.1 for windows fixes (#30196)
PR Close #30196
2019-04-29 13:29:12 -07:00
21418ea109 test: fix ngc-wrapped bazel tests in windows (#30111)
Partially addresses #29785

PR Close #30111
2019-04-29 13:23:45 -07:00
02d8b4ed3c docs: add in-page nav, change title to match left nav better (#30093)
PR Close #30093
2019-04-29 13:23:15 -07:00
6748392edc docs: add architect terms (#26963)
PR Close #26963
2019-04-29 13:22:20 -07:00
d9fd301157 build(docs-infra): update the aio app to framework and cli 8.0.0-rc.1 (#30183)
I updated the payload size limits as well. There still seem to be size regressions in the framework,
but at least the polyfills now uses the evergreen build of zones so we shaved off a few KB there.

PR Close #30183
2019-04-29 12:30:26 -07:00
71c5d80ce7 build: add size-tracking bazel test (#30070)
Introduces a new Bazel test that allows us to inspect
what source-files contribute to a given bundled file
and how much bytes they contribute to the bundle size.

Additionally the size-tracking rule groups the size
data by directories. This allows us to compare size
changes in the scope of directories. e.g. a lot of
files in a directory could increase slightly in size, but
in the directory scope the size change could be significant
and needs to be reported by the test target.

Resolves FW-1278

PR Close #30070
2019-04-29 12:29:25 -07:00
9798229fde release: cut the v8.0.0-rc.2 release 2019-04-29 12:03:39 -07:00
4b2fcfd5dc fix: disable injectable-pipe migration (#30180)
Disables the injectable pipe migration until we can decide whether this is the right solution for Ivy. Rolling it out properly will involve a more detailed plan and more changes like updating the styleguide, scaffolding schematics etc.

Context for the new `test-migrations.json`: since we use the `migrations.json` both for the real migrations and for tests, it doesn't allow us to disable a schematic, but continue running its tests. This change adds the test-specific file so that we can continue running the `injectable-pipe` tests, even though the schematic itself is disabled.

PR Close #30180
2019-04-29 09:40:00 -07:00
b4d291aa7a fix(ivy): injectable pipe schematic generating incorrect import statements (#30170)
Currently the injectable pipe schematic generates invalid imports like `import import { Pipe, PipeTransform, Injectable } from '@angular/core'; from '@angular/core';`. The issue wasn't caught by the unit tests, because the invalid import still contains the valid one.

Fixes #30159.

PR Close #30170
2019-04-29 09:39:11 -07:00
b0ecafdc2f docs: temporary disable aio_monitoring job due to a version skew (#30161)
It looks like `aio_monitoring` CircleCI job is still failing. Disabling it for now to keep master green.

PR Close #30161
2019-04-26 17:38:59 -07:00
6816bb62d7 Revert "refactor: use new Http library in playground (#29355)"
This reverts commit 908d43a5bb.
2019-04-26 16:51:38 -07:00
4b05b8cea0 refactor(ivy): move exports tests to acceptance (#30157)
PR Close #30157
2019-04-26 16:37:34 -07:00
a0728aedf7 docs: update readme. sentence correction. (#30136)
PR Close #30136
2019-04-26 16:36:53 -07:00
ea96f6112a build: unable to accept new symbol-extractor golden on windows (#30127)
Currently when working on Windows, it's not possible to accept a new
golden for a `symbol-extractor` Bazel test. This is because the generated
executable output from the `nodejs_binary` rule (without a macro) misses
a Windows executable wrapper that sets up the proper environment
variables for the runfiles. Causing the following failure on Windows:

```
 >>>> FAIL: RUNFILES environment variable is not set. <<<<
```

PR Close #30127
2019-04-26 16:35:51 -07:00
b706800ea8 fix(language-service): Remove tsserverlibrary from rollup globals (#30123)
This PR removes `tsserverlibrary` from rollup globals since the symbol
should not appear by the time rollup is invoked. `tsserverlibrary` is
used for types only, so the import statement should not be emitted by
tsc.

PR Close #30123
2019-04-26 16:35:05 -07:00
c6f95b1d70 ci: enable language service tests in codefresh (#30113)
PR Close #30113
2019-04-26 16:34:23 -07:00
d896126604 test: fix language service tests in windows (#30113)
This PR parially addresses #29785 and fixes ` //packages/language-service/test:test`

PR Close #30113
2019-04-26 16:34:23 -07:00
a20da5ddcc ci(docs-infra): use the tests from the stable branch in aio_monitoring_stable CircleCI job (#30110)
Previously, the `aio_monitoring_stable` job (which runs tests against
https://angular.io/) was using the tests from the master branch. As a
result, if the master branch included changes in those tests that were
not yet backported to the stable branch (and thus deployed to
https://angular.io/), the tests would fail.

This commit fixes this by using the tests from the stable branch to test
against https://angular.io/.

Fixes #30101

PR Close #30110
2019-04-26 16:33:46 -07:00
18878600ba ci(docs-infra): split the aio_monitoring CircleCI job into two jobs (#30110)
Previously, the `aio_monitoring` job was testing both the stable
(https://angular.io/) and the @next (https://next.angular.io/) versions.

This commit splits the tests into two separate jobs (still run as part
of the same workflow). This speeds up the tests (since the two jobs can
now run in parallel) and makes it easier to isolate failures (e.g.
identify which branch is failing, disable one of the two, etc.).
(Credits to @petebacondarwin 😉)

PR Close #30110
2019-04-26 16:33:46 -07:00
d7e10f3f7e ci(docs-infra): re-use setup CircleCI job in aio_monitoring (#30110)
PR Close #30110
2019-04-26 16:33:46 -07:00
4d044ea5b2 ci(docs-infra): re-enable aio_monitoring CircleCI job (#30110)
The job started failing for https://angular.io/, due to changes in tests
that only affected https://next.angular.io/, and was disabled in #30102.

This commit re-enables the job (since it does not block anything and it
will be fixed in a subsequent commit).

PR Close #30110
2019-04-26 16:33:46 -07:00
e2d1e0cd98 docs(docs-infra): fix typo in workspace-config.md file (#30108)
Fixed typo in 'Project asset configuration' section inside workdspace-config.md

PR Close #30108
2019-04-26 16:33:03 -07:00
4e056580bb test: fix api guardian tests on windows when node_modules are not installed (#30105)
When the workspace node_modules are not installed outside of bazel context the api guardian tests fails because the tree artifacts files are not symlinked in windows.

We need to pass the node module location in the node_path

PR Close #30105
2019-04-26 16:32:23 -07:00
e4c2e6a904 ci: add public_api_guard tests to codefresh config (#30105)
PR Close #30105
2019-04-26 16:32:23 -07:00
a50989832d test: fix ts api guardian and public guard tests on windows (#30105)
This change addresses several issues with ts-api-guardian and public api guards related tests in Windows

The fixes contain 3 main changes:
1) In `stripExportPattern` - replace `^` with `^^^^`  in RegExp due to a double escaping requirment under Windows. Note that under Linux this the extra character has no effect because it's still a valid RegExp in Js.

2. Force `*.patch` files to always be with a LF line sequence instead of CRLF in windows

3. When adding JSDoc comments consider the presence of a carriage return in a line new feed

Partially addresses #29785

PR Close #30105
2019-04-26 16:32:23 -07:00
525307b6a3 fix(ivy): correctly reflect undefined values (#30103)
Fixes Ivy reflecting properties with `undefined` values, rather than omitting them. Also fixes that Ivy doesn't clear the reflected values when property value changes from something that is defined to undefined.

This PR resolves FW-1277.

PR Close #30103
2019-04-26 16:31:50 -07:00
a3ab76b216 docs: update redirect links and fix typo (#30092)
PR Close #30092
2019-04-26 16:31:04 -07:00
f2265d4b46 build: upgrade yargs package to 13.1.0 (#29722)
Update yargs, because the old version was transitively (via os-local) depending on a vulnerable version of the mem package: https://app.snyk.io/vuln/npm:mem:20180117

PR Close #29722
2019-04-26 16:29:29 -07:00
d3ac709b99 fix(ivy): @Component should support entry components from another module (#29566)
PR Close #29566
2019-04-26 16:27:19 -07:00
908d43a5bb refactor: use new Http library in playground (#29355)
PR Close #29355
2019-04-26 16:26:31 -07:00
71cdb0a08e refactor(ivy): move di tests for inject to acceptance (#29299)
PR Close #29299
2019-04-26 16:23:44 -07:00
c7fbbdfa99 refactor(ivy): move di tests for flags to acceptance (#29299)
Including tests for `@Optional`, `@Self`, `@SkipSelf` and `@Host`.

PR Close #29299
2019-04-26 16:23:44 -07:00
10e4ab7712 refactor(ivy): move di tests for directive injection to acceptance (#29299)
PR Close #29299
2019-04-26 16:23:44 -07:00
5114c23c21 refactor(ivy): move di tests for DI tokens to acceptance (#29299)
Move tests for special tokens like `Injector`, `ElementRef`, `TemplateRef`, `ViewContainerRef`, `ChangeDectetorRef` and custom string tokens.

PR Close #29299
2019-04-26 16:23:43 -07:00
c3e585d7eb refactor(ivy): move di tests for Attribute to acceptance (#29299)
PR Close #29299
2019-04-26 16:23:43 -07:00
0776daec88 release: cut the v8.0.0-rc.1 release 2019-04-26 13:28:49 -07:00
615e1a58b2 test(ivy): pin deps on hello world size tests (#30152)
We recently had an unexpected size regression in the hello world
tests because the CLI devkit released an RC that regressed us and
the dependencies were not pinned. This change ensures that we only
update dependencies like devkit deliberately, so we do not have
mysterious breakages caused by other packages.

PR Close #30152
2019-04-26 12:34:10 -07:00
606758357e fix(bazel): update peerDep ranges (#30155)
PR Close #30155
2019-04-26 12:32:35 -07:00
ba2a3595c6 fix(ivy): output should not be subscribe twice when 2 listeners (#30144)
PR Close #30144
2019-04-26 11:11:09 -07:00
a50bfe5054 fix(ivy): property bindings use correct indices (#30129)
- Extracts and documents code that will be common to interpolation instructions
- Ensures that binding indices are updated at the proper time during compilation
- Adds additional tests

Related #30011

PR Close #30129
2019-04-26 11:09:51 -07:00
c8983bc367 docs: remove note about ivy being coupled to dynamic import (#30151)
PR Close #30151
2019-04-26 11:08:51 -07:00
8d6d2c6704 build: bazel ts-api-guardian usage fails on workspaces which don't depend on chalk (#30138)
When using the npm package in a workspace which doesn't depend on chalk, ts-api-guardian fails with an error `Error: Cannot find module 'chalk'`

PR Close #30138
2019-04-26 11:08:05 -07:00
6711f22e62 fix(bazel): Exclude common/upgrade* in metadata.tsconfig.json (#30133)
It has a dependency on @angular/upgrade which is not part of the
dependencies in package.json, so postinstall would fail.

PR Close #30133
2019-04-26 11:07:34 -07:00
8dd9192fe3 refactor(ivy): undeprecate inject (#30132)
PR Close #30132
2019-04-26 11:06:42 -07:00
870e0dab48 fix(ivy): remove debug utilities from ivy production builds (#30130)
Prior to this commit, we were pulling DebugNode and DebugElement
into production builds because BrowserModule automatically pulled
in NgProbe and thus getDebugNode. In Ivy, this is not necessary
because Ivy has its own set of debug utilities. We should use these
existing tools instead of NgProbe.

This commit adds an Ivy switch so we do not pull in NgProbe utilities
when running with Ivy. This saves us ~8KB in prod builds.

PR Close #30130
2019-04-26 11:04:48 -07:00
7502 changed files with 350342 additions and 662421 deletions

View File

@ -1,97 +1,8 @@
# Bazel does not yet support wildcards or other .gitignore semantics for
# .bazelignore. Two issues for this feature request are outstanding:
# https://github.com/bazelbuild/bazel/issues/7093
# https://github.com/bazelbuild/bazel/issues/8106
.git
node_modules
dist
aio/content
aio/node_modules
aio/tools/examples/shared/node_modules
packages/bazel/node_modules
integration/bazel/bazel-bazel
integration/bazel/bazel-bin
integration/bazel/bazel-out
integration/bazel/bazel-testlogs
integration/bazel
integration/bazel-schematics/demo
# All integration test node_modules folders
integration/bazel/node_modules
integration/bazel-schematics/node_modules
integration/cli-hello-world/node_modules
integration/cli-hello-world-ivy-compat/node_modules
integration/cli-hello-world-ivy-i18n/node_modules
integration/cli-hello-world-ivy-minimal/node_modules
integration/cli-hello-world-lazy/node_modules
integration/cli-hello-world-lazy-rollup/node_modules
integration/dynamic-compiler/node_modules
integration/hello_world__closure/node_modules
integration/hello_world__systemjs_umd/node_modules
integration/i18n/node_modules
integration/injectable-def/node_modules
integration/ivy-i18n/node_modules
integration/language_service_plugin/node_modules
integration/ng_elements/node_modules
integration/ng_elements_schematics/node_modules
integration/ng_update/node_modules
integration/ng_update_migrations/node_modules
integration/ngcc/node_modules
integration/platform-server/node_modules
integration/service-worker-schema/node_modules
integration/side-effects/node_modules
integration/terser/node_modules
integration/typings_test_ts36/node_modules
integration/typings_test_ts37/node_modules
# All integration test .yarn_local_cache folders
integration/bazel/.yarn_local_cache
integration/bazel-schematics/.yarn_local_cache
integration/cli-hello-world/.yarn_local_cache
integration/cli-hello-world-ivy-compat/.yarn_local_cache
integration/cli-hello-world-ivy-i18n/.yarn_local_cache
integration/cli-hello-world-ivy-minimal/.yarn_local_cache
integration/cli-hello-world-lazy/.yarn_local_cache
integration/cli-hello-world-lazy-rollup/.yarn_local_cache
integration/dynamic-compiler/.yarn_local_cache
integration/hello_world__closure/.yarn_local_cache
integration/hello_world__systemjs_umd/.yarn_local_cache
integration/i18n/.yarn_local_cache
integration/injectable-def/.yarn_local_cache
integration/ivy-i18n/.yarn_local_cache
integration/language_service_plugin/.yarn_local_cache
integration/ng_elements/.yarn_local_cache
integration/ng_elements_schematics/.yarn_local_cache
integration/ng_update/.yarn_local_cache
integration/ng_update_migrations/.yarn_local_cache
integration/ngcc/.yarn_local_cache
integration/platform-server/.yarn_local_cache
integration/service-worker-schema/.yarn_local_cache
integration/side-effects/.yarn_local_cache
integration/terser/.yarn_local_cache
integration/typings_test_ts36/.yarn_local_cache
integration/typings_test_ts37/.yarn_local_cache
# All integration test NPM_PACKAGE_MANIFEST.json folders
integration/bazel/NPM_PACKAGE_MANIFEST.json
integration/bazel-schematics/NPM_PACKAGE_MANIFEST.json
integration/cli-hello-world/NPM_PACKAGE_MANIFEST.json
integration/cli-hello-world-ivy-compat/NPM_PACKAGE_MANIFEST.json
integration/cli-hello-world-ivy-i18n/NPM_PACKAGE_MANIFEST.json
integration/cli-hello-world-ivy-minimal/NPM_PACKAGE_MANIFEST.json
integration/cli-hello-world-lazy/NPM_PACKAGE_MANIFEST.json
integration/cli-hello-world-lazy-rollup/NPM_PACKAGE_MANIFEST.json
integration/dynamic-compiler/NPM_PACKAGE_MANIFEST.json
integration/hello_world__closure/NPM_PACKAGE_MANIFEST.json
integration/hello_world__systemjs_umd/NPM_PACKAGE_MANIFEST.json
integration/i18n/NPM_PACKAGE_MANIFEST.json
integration/injectable-def/NPM_PACKAGE_MANIFEST.json
integration/ivy-i18n/NPM_PACKAGE_MANIFEST.json
integration/language_service_plugin/NPM_PACKAGE_MANIFEST.json
integration/ng_elements/NPM_PACKAGE_MANIFEST.json
integration/ng_elements_schematics/NPM_PACKAGE_MANIFEST.json
integration/ng_update/NPM_PACKAGE_MANIFEST.json
integration/ng_update_migrations/NPM_PACKAGE_MANIFEST.json
integration/ngcc/NPM_PACKAGE_MANIFEST.json
integration/platform-server/NPM_PACKAGE_MANIFEST.json
integration/service-worker-schema/NPM_PACKAGE_MANIFEST.json
integration/side-effects/NPM_PACKAGE_MANIFEST.json
integration/terser/NPM_PACKAGE_MANIFEST.json
integration/typings_test_ts36/NPM_PACKAGE_MANIFEST.json
integration/typings_test_ts37/NPM_PACKAGE_MANIFEST.json
packages/bazel/node_modules

118
.bazelrc
View File

@ -1,3 +1,14 @@
###############################
# Typescript / Angular / Sass #
###############################
# Make compilation fast, by keeping a few copies of the compilers
# running as daemons, and cache SourceFile AST's to reduce parse time.
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
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
@ -18,8 +29,11 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
# See https://github.com/bazelbuild/bazel/issues/4603
build --symlink_prefix=dist/
# Disable watchfs as it causes tests to be flaky on Windows
# https://github.com/angular/angular/issues/29541
build --nowatchfs
# Turn off legacy external runfiles
build --nolegacy_external_runfiles
run --nolegacy_external_runfiles
test --nolegacy_external_runfiles
@ -33,10 +47,21 @@ build --incompatible_strict_action_env
run --incompatible_strict_action_env
test --incompatible_strict_action_env
# Do not build runfile trees by default. If an execution strategy relies on runfile
# symlink teee, the tree is created on-demand. See: https://github.com/bazelbuild/bazel/issues/6627
# and https://github.com/bazelbuild/bazel/commit/03246077f948f2790a83520e7dccc2625650e6df
build --nobuild_runfile_links
###############################
# 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 #
@ -47,8 +72,7 @@ build --nobuild_runfile_links
# Releases should always be stamped with version control info
# This command assumes node on the path and is a workaround for
# https://github.com/bazelbuild/bazel/issues/4802
build:release --workspace_status_command="yarn -s ng-dev release build-env-stamp"
build:release --stamp
build:release --workspace_status_command="node ./tools/bazel_stamp_vars.js"
###############################
# Output #
@ -61,53 +85,37 @@ query --output=label_kind
# By default, failing tests don't print any output, it goes to the log file
test --test_output=errors
# Show which actions are run under workers,
# and print all the actions running in parallel.
# Helps to demonstrate that bazel uses all the cores on the machine.
build --experimental_ui
test --experimental_ui
################################
# Settings for CircleCI #
################################
# Bazel flags for CircleCI are in /.circleci/bazel.linux.rc and /.circleci/bazel.windows.rc
##################################
# Settings for integration tests #
##################################
# Trick bazel into treating BUILD files under integration/bazel as being regular files
# This lets us glob() up all the files inside this integration test to make them inputs to tests
# (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it)
build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
# Bazel flags for CircleCI are in /.circleci/bazel.rc
################################
# Temporary Settings for Ivy #
################################
# To determine if the compiler used should be Ivy instead of ViewEngine, one can use `--config=ivy`
# on any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
build --define=angular_ivy_enabled=False
# to determine if the compiler used should be Ivy or ViewEngine one can use `--define=compile=aot` on
# any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
build --define=compile=legacy
build:view-engine --define=angular_ivy_enabled=False
build:ivy --define=angular_ivy_enabled=True
###############################
# Remote Build Execution support
# Turn on these settings with
# --config=remote
###############################
##################################
# Remote Build Execution support #
# Turn on these settings with #
# --config=remote #
##################################
# The following --define=EXECUTOR=remote will be able to be removed
# once https://github.com/bazelbuild/bazel/issues/7254 is fixed
build:remote --define=EXECUTOR=remote
# Set a higher timeout value, just in case.
build:remote --remote_timeout=600
# Load default settings for Remote Build Execution.
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/.bazelrc.notoolchain
# Increase the default number of jobs by 50% because our build has lots of
# parallelism
build:remote --jobs=150
build:remote --google_default_credentials
# Force remote exeuctions to consider the entire run as linux
build:remote --cpu=k8
build:remote --host_cpu=k8
# Toolchain and platform related flags
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
@ -115,26 +123,36 @@ 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 --host_platform=//tools:rbe_ubuntu1604-angular
build:remote --platforms=//tools:rbe_ubuntu1604-angular
# Remote instance and caching
# Remote instance.
build:remote --remote_instance_name=projects/internal-200822/instances/default_instance
build:remote --project_id=internal-200822
# Remote caching
build:remote --remote_cache=remotebuildexecution.googleapis.com
build:remote --remote_executor=remotebuildexecution.googleapis.com
# By default, do not accept remote cache, to be set to true for CI based on environment
build:remote --remote_accept_cached=false
# By default, do not upload local results to cache, to be set to true for CI based on environment
build:remote --remote_upload_local_results=false
##################################
# Saucelabs tests settings #
# Turn on these settings with #
# --config=saucelabs #
##################################
# Build Event Service Configuration
build:remote --bes_backend=buildeventservice.googleapis.com
build:remote --bes_timeout=30s
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
# For saucelabs tests we don't want to enable flaky test attempts. Karma has its own integrated
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
test:saucelabs --flaky_test_attempts=1
###############################
# 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

View File

@ -1,3 +0,0 @@
3.2.0
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl

42
.buildkite/Dockerfile Normal file
View 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
View 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.

View 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
View 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

View File

@ -0,0 +1,94 @@
# 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-standard-16 (16 vCPUs, 60 GB memory).
# Use a recent windows boot disk with container support such as
# "Windows Server version 1803 Datacenter Core for Containers", and add a 128GB SSD disk.
# 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"
# Sleep for 15s while git is installed. Trying to remove the git.exe before it finishes install causes an error.
Start-Sleep -s 15
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

View File

@ -12,8 +12,8 @@ We use this as a symmetric AES encryption key to encrypt tokens like
a GitHub token that enables publishing snapshots.
To create the github_token file, we take this approach:
- Find the angular-builds:token in the internal pw database
- Find the angular-builds:token in http://valentine
- Go inside the CircleCI default docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it circleci/node:10.12`
- echo "https://[token]:@github.com" > credentials
- openssl aes-256-cbc -e -in credentials -out .circleci/github_token -k $KEY
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`

View File

@ -1,15 +0,0 @@
# Settings in this file should be OS agnostic. Use the bazel.<OS>.rc files for OS specific settings.
# Don't be spammy in the logs
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
# 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

View File

@ -1,30 +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
# Import config items common to both Linux and Windows setups.
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
try-import %workspace%/.circleci/bazel.common.rc
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
build --repository_cache=/home/circleci/bazel_repository_cache
# Workaround https://github.com/bazelbuild/bazel/issues/3645
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
build --local_cpu_resources=8
build --local_ram_resources=14336
# All build executed remotely should be done using our RBE configuration.
build:remote --google_default_credentials
# Upload to GCP's Build Status viewer to allow for us to have better viewing of execution/build
# logs. This is only done on CI as the BES (GCP's Build Status viewer) API requires credentials
# from service accounts, rather than end user accounts.
build:remote --bes_backend=buildeventservice.googleapis.com
build:remote --bes_timeout=30s
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
build --config=remote

30
.circleci/bazel.rc Normal file
View File

@ -0,0 +1,30 @@
# 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 downloaded repositories in a location that can be cached by CircleCI. This helps us
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
build --repository_cache=/home/circleci/bazel_repository_cache
# 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 CircleCI "xlarge" class
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
build --local_resources=14336,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

View File

@ -1,21 +0,0 @@
# These options are enabled when running on CI
# We do this by copying this file to $env:ProgramData\bazel.bazelrc at the start of the build.
# See documentation in /docs/BAZEL.md
# Import config items common to both Linux and Windows setups.
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
try-import %workspace%/.circleci/bazel.common.rc
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
build --repository_cache=C:/Users/circleci/bazel_repository_cache
# Manually set the local resources used in windows CI runs
build --local_ram_resources=13500
build --local_cpu_resources=4
# All windows jobs run on master and should use http caching
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
build --remote_accept_cached=true
build --remote_upload_local_results=true
build --google_default_credentials

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
# Variables
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
readonly bashEnvCachePath="$projectDir/.circleci/bash_env_cache";
readonly getCommitRangePath="$projectDir/.circleci/get-commit-range.js";
# Load helpers and make them available everywhere (through `$BASH_ENV`).
source $envHelpersPath;
@ -15,23 +15,23 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
####################################################################################################
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
####################################################################################################
setPublicVar CI "$CI"
setPublicVar PROJECT_ROOT "$projectDir";
setPublicVar CI_AIO_MIN_PWA_SCORE "62";
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
# This is the branch being built; e.g. `pull/12345` for PR builds.
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
# ChromeDriver version compatible with the Chrome version included in the docker image used in
# `.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.
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 75.0.3770.90";
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
# workflows of such builds).
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
# `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
# rerun workflows of such builds). That is fine, since we only need it in push builds.
setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || node $getCommitRangePath "$CIRCLE_BUILD_NUM" "$CIRCLE_COMPARE_URL"`";
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
####################################################################################################
@ -51,63 +51,33 @@ setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
####################################################################################################
# Define SauceLabs environment variables for CircleCI.
####################################################################################################
setPublicVar SAUCE_USERNAME "angular-framework";
setSecretVar SAUCE_ACCESS_KEY "0c731274ed5f-cbc9-16f4-021a-9835e39f";
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
# In order to have a meaningful SauceLabs badge on the repo page,
# the angular2-ci account is used only when pushing commits to master;
# in all other cases, the regular angular-ci account is used.
if [ "${CI_PULL_REQUEST}" = "false" ] && [ "${CI_REPO_OWNER}" = "angular" ] && [ "${CI_BRANCH}" = "master" ]; then
setPublicVar SAUCE_USERNAME "angular2-ci";
setSecretVar SAUCE_ACCESS_KEY "693ebc16208a-0b5b-1614-8d66-a2662f4e";
else
setPublicVar SAUCE_USERNAME "angular-ci";
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
fi
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-framework-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
####################################################################################################
# Define environment variables for the `angular/components` repo unit tests job.
# 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. **NOTE**: When updating the temporary directory, also update
# the `save_cache` path configuration in `config.yml`
setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
setPublicVar COMPONENTS_REPO_BRANCH "master"
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
setPublicVar COMPONENTS_REPO_COMMIT "09e68db8ed5b1253f2fe38ff954ef0df019fc25a"
# 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"
####################################################################################################
# Decrypt GCP Credentials and store them as the Google default credentials.
####################################################################################################
mkdir -p "$HOME/.config/gcloud";
openssl aes-256-cbc -d -in "${projectDir}/.circleci/gcp_token" \
-md md5 -k "$CIRCLE_PROJECT_REPONAME" -out "$HOME/.config/gcloud/application_default_credentials.json"
####################################################################################################
# Set bazel configuration for CircleCI runs.
####################################################################################################
cp "${projectDir}/.circleci/bazel.linux.rc" "$HOME/.bazelrc";
####################################################################################################
# Create shell script in /tmp for Bazel actions to access CI envs without
# busting the cache. Used by payload-size.sh script in integration tests.
####################################################################################################
readonly bazelVarEnv="/tmp/bazel-ci-env.sh"
echo "# Setup by /.circle/env.sh" > $bazelVarEnv
echo "export PROJECT_ROOT=\"${PROJECT_ROOT}\";" >> $bazelVarEnv
echo "export CI_BRANCH=\"${CI_BRANCH}\";" >> $bazelVarEnv
echo "export CI_BUILD_URL=\"${CI_BUILD_URL}\";" >> $bazelVarEnv
echo "export CI_COMMIT=\"${CI_COMMIT}\";" >> $bazelVarEnv
echo "export CI_COMMIT_RANGE=\"${CI_COMMIT_RANGE}\";" >> $bazelVarEnv
echo "export CI_PULL_REQUEST=\"${CI_PULL_REQUEST}\";" >> $bazelVarEnv
echo "export CI_REPO_NAME=\"${CI_REPO_NAME}\";" >> $bazelVarEnv
echo "export CI_REPO_OWNER=\"${CI_REPO_OWNER}\";" >> $bazelVarEnv
echo "export CI_SECRET_PAYLOAD_FIREBASE_TOKEN=\"${CI_SECRET_PAYLOAD_FIREBASE_TOKEN}\";" >> $bazelVarEnv
####################################################################################################
####################################################################################################
## Source `$BASH_ENV` to make the variables available immediately. ##
## ***NOTE: This must remain the the last action in this script*** ##
####################################################################################################
####################################################################################################
# Source `$BASH_ENV` to make the variables available immediately.
source $BASH_ENV;

Binary file not shown.

View File

@ -0,0 +1,159 @@
#!/usr/bin/env node
/**
* **Usage:**
* ```
* 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
* format of the `CIRCLE_COMPARE_URL` environment variable, or by retrieving the equivalent of
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow and extracting it from there.
*
* **Context:**
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
* range) on push builds (a.k.a. non-PR, non-scheduled builds). Yet, when a workflow is rerun
* (either from the beginning or from failed jobs) - e.g. when a job flakes - CircleCI does not set
* the `CIRCLE_COMPARE_URL`.
*
* **Implementation details:**
* This script relies on the fact that all rerun workflows share the same CircleCI workspace and the
* (undocumented) fact that the workspace ID happens to be the same as the workflow ID that first
* created it.
*
* For example, for a job on push build workflow, the CircleCI API will return data that look like:
* ```js
* {
* compare: 'THE_COMPARE_URL_WE_ARE_LOOKING_FOR',
* //...
* previous: {
* // ...
* build_num: 12345,
* },
* //...
* workflows: {
* //...
* workflow_id: 'SOME_ID_A',
* workspace_id: 'SOME_ID_A', // Same as `workflow_id`.
* }
* }
* ```
*
* If the workflow is rerun, the data for jobs on the new workflow will look like:
* ```js
* {
* compare: null, // ¯\_(ツ)_/¯
* //...
* previous: {
* // ...
* build_num: 23456,
* },
* //...
* workflows: {
* //...
* workflow_id: 'SOME_ID_B',
* workspace_id: 'SOME_ID_A', // Different from current `workflow_id`.
* // Same as original `workflow_id`. \o/
* }
* }
* ```
*
* This script uses the `previous.build_num` (which points to the previous build number on the same
* branch) to traverse the jobs backwards, until it finds a job from the original workflow. Such a
* job (if found) should also contain the compare URL.
*
* **NOTE 1:**
* This is only useful on workflows which are created by rerunning a workflow for which
* `CIRCLE_COMPARE_URL` was defined.
*
* **NOTE 2:**
* The `circleToken` will be used for CircleCI API requests if provided, but it is not needed for
* accessing the read-only endpoints that we need (as long as the current project is FOSS and the
* corresponding setting is turned on in "Advanced Settings" in the project dashboard).
*
* ---
* Inspired by https://circleci.com/orbs/registry/orb/iynere/compare-url
* (source code: https://github.com/iynere/compare-url-orb).
*
* We are not using the `compare-url` orb for the following reasons:
* 1. (By looking at the code) it would only work if the rerun workflow is the latest workflow on
* the branch (which is not guaranteed to be true).
* 2. It is less efficient (e.g. makes unnecessary CircleCI API requests for builds on different
* branches, installs extra dependencies, persists files to the workspace (as a means of passing
* the result to the calling job), etc.).
* 3. It is slightly more complicated to setup and consume than our own script.
* 4. Its implementation is more complicated than needed for our usecase (e.g. handles different git
* providers, handles newly created branches, etc.).
*/
// Imports
const {get: httpsGet} = require('https');
// Constants
const API_URL_BASE = 'https://circleci.com/api/v1.1/project/github/angular/angular';
const COMPARE_URL_RE = /^.*\/([0-9a-f]+\.\.\.[0-9a-f]+)$/i;
// Run
_main(process.argv.slice(2));
// Helpers
async function _main([buildNumber, compareUrl = '', circleToken = '']) {
try {
if (!buildNumber || isNaN(buildNumber)) {
throw new Error(
'Missing or invalid arguments.\n' +
'Expected: buildNumber (number), compareUrl? (string), circleToken? (string)');
}
if (!compareUrl) {
compareUrl = await getCompareUrl(buildNumber, circleToken);
}
const commitRangeMatch = COMPARE_URL_RE.exec(compareUrl)
const commitRange = commitRangeMatch ? commitRangeMatch[1] : '';
console.log(commitRange);
} catch (err) {
console.error(err);
process.exit(1);
}
}
function getBuildInfo(buildNumber, circleToken) {
console.error(`BUILD ${buildNumber}`);
const url = `${API_URL_BASE}/${buildNumber}?circle-token=${circleToken}`;
return getJson(url);
}
async function getCompareUrl(buildNumber, circleToken) {
let info = await getBuildInfo(buildNumber, circleToken);
const targetWorkflowId = info.workflows.workspace_id;
while (info.workflows.workflow_id !== targetWorkflowId) {
info = await getBuildInfo(info.previous.build_num, circleToken);
}
return info.compare || '';
}
function getJson(url) {
return new Promise((resolve, reject) => {
const opts = {headers: {Accept: 'application/json'}};
const onResponse = res => {
const statusCode = res.statusCode || -1;
const isSuccess = (200 <= statusCode) && (statusCode < 400);
let responseText = '';
res.
on('error', reject).
on('data', d => responseText += d).
on('end', () => isSuccess ?
resolve(JSON.parse(responseText)) :
reject(`Error getting '${url}' (status ${statusCode}):\n${responseText}`));
};
httpsGet(url, opts, onResponse).
on('error', reject).
end();
});
}

View File

@ -60,15 +60,14 @@ if (require.resolve === module) {
// Helpers
function _main(args) {
triggerWebhook(...args)
.then(
({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
console.log(`Status: ${statusCode}\n${responseText}`) :
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`)))
.catch(err => {
console.error(err);
process.exit(1);
});
triggerWebhook(...args).
then(({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
console.log(`Status: ${statusCode}\n${responseText}`) :
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`))).
catch(err => {
console.error(err);
process.exit(1);
});
}
function postJson(url, data) {
@ -78,12 +77,15 @@ function postJson(url, data) {
const statusCode = res.statusCode || -1;
let responseText = '';
res.on('error', reject)
.on('data', d => responseText += d)
.on('end', () => resolve({statusCode, responseText}));
res.
on('error', reject).
on('data', d => responseText += d).
on('end', () => resolve({statusCode, responseText}));
};
request(url, opts, onResponse).on('error', reject).end(JSON.stringify(data));
request(url, opts, onResponse).
on('error', reject).
end(JSON.stringify(data));
});
}

View File

@ -1,56 +0,0 @@
# Install Bazel pre-reqs on Windows
# https://docs.bazel.build/versions/master/install-windows.html
# https://docs.bazel.build/versions/master/windows.html
# Install MSYS2 and packages
choco install msys2 --version 20180531.0.0 --no-progress --package-parameters "/NoUpdate"
C:\tools\msys64\usr\bin\bash.exe -l -c "pacman --needed --noconfirm -S zip unzip patch diffutils git"
# Add PATH modifications to the Powershell profile. This is the win equivalent of .bash_profile.
# https://docs.microsoft.com/en-us/previous-versions//bb613488(v=vs.85)
new-item -path $profile -itemtype file -force
# Paths for nodejs, npm, yarn, and msys2. Use single quotes to prevent interpolation.
# Add before the original path to use msys2 instead of the installed gitbash.
Add-Content $profile '$Env:path = "${Env:ProgramFiles}\nodejs\;C:\Users\circleci\AppData\Roaming\npm\;${Env:ProgramFiles(x86)}\Yarn\bin\;C:\Users\circleci\AppData\Local\Yarn\bin\;C:\tools\msys64\usr\bin\;" + $Env:path'
# Environment variables for Bazel
Add-Content $profile '$Env:BAZEL_SH = "C:\tools\msys64\usr\bin\bash.exe"'
# Get the bazelisk version devdep and store it in a global var for use in the circleci job.
$bazeliskVersion = & ${Env:ProgramFiles}\nodejs\node.exe -e "console.log(require('./package.json').devDependencies['@bazel/bazelisk'])"
# This is a tricky situation: we want $bazeliskVersion to be evaluated but not $Env:BAZELISK_VERSION.
# Formatting works https://stackoverflow.com/questions/32127583/expand-variable-inside-single-quotes
$bazeliskVersionGlobalVar = '$Env:BAZELISK_VERSION = "{0}"' -f $bazeliskVersion
Add-Content $profile $bazeliskVersionGlobalVar
# Remove the CircleCI checkout SSH override, because it breaks cloning repositories through Bazel.
# See https://circleci.com/gh/angular/angular/401454 for an example.
# TODO: is this really needed? Maybe there's a better way. It doesn't happen on Linux or on Codefresh.
git config --global --unset url.ssh://git@github.com.insteadOf
####################################################################################################
# Decrypt GCP Credentials and store them as the Google default credentials.
####################################################################################################
mkdir ${env:APPDATA}\gcloud
openssl aes-256-cbc -d -in .circleci\gcp_token -md md5 -out "$env:APPDATA\gcloud\application_default_credentials.json" -k "$env:CIRCLE_PROJECT_REPONAME"
####################################################################################################
# Set bazel configuration for CircleCI runs.
####################################################################################################
copy .circleci\bazel.windows.rc ${Env:USERPROFILE}\.bazelrc
####################################################################################################
# Install specific version of node.
####################################################################################################
choco install nodejs --version 12.14.1 --no-progress
# These Bazel prereqs aren't needed because the CircleCI image already includes them.
# choco install yarn --version 1.16.0 --no-progress
# choco install vcredist2015 --version 14.0.24215.20170201
# We don't need VS Build Tools for the tested bazel targets.
# If it's needed again, uncomment these lines.
# VS Build Tools are needed for Bazel C++ targets (like com_google_protobuf)
# choco install visualstudio2019buildtools --version 16.1.2.0 --no-progress --package-parameters "--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"
# Add-Content $profile '$Env:BAZEL_VC = "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\"'
# Python is needed for Bazel Python targets
# choco install python --version 3.5.1 --no-progress

View File

@ -0,0 +1,103 @@
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); \
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; \
Start-Process 'c:\\vc_redist.x64.exe' -ArgumentList '/Install', '/Passive', '/NoRestart' -NoNewWindow -Wait; \
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"]

33
.codefresh/README.md Normal file
View File

@ -0,0 +1,33 @@
# CodeFresh configuration
[![Codefresh build status](https://g.codefresh.io/api/badges/pipeline/angular/angular%2Fangular%2Fangular?type=cf-1)](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

42
.codefresh/bazel.rc Normal file
View File

@ -0,0 +1,42 @@
# 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 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
# 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=8000,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
# Include PATH in Windows build/tests
# https://github.com/bazelbuild/rules_typescript/pull/356
build --action_env=PATH
test --action_env=PATH --test_env=PATH
# Exclude tests known to not work on Windows.
# Chrome web tests are currently broken.
test --test_tag_filters=-browser:chromium-local

26
.codefresh/codefresh.yml Normal file
View File

@ -0,0 +1,26 @@
version: '1.0'
steps:
BuildImage:
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 Example
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
- yarn bazel test //tools/ts-api-guardian:all //packages/language-service/test //packages/compiler/test //packages/compiler-cli/test:ngc //packages/compiler-cli/test/ngtsc:ngtsc
- yarn test-ivy-aot //packages/animations/test //packages/common/test //packages/forms/test //packages/http/test //packages/platform-browser/test //packages/platform-browser-dynamic/test //packages/router/test
- yarn bazel test //tools/public_api_guard/...
- yarn bazel test //packages/compiler-cli/integrationtest:integrationtest //packages/compiler-cli/test/compliance:compliance

View 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."

View File

@ -1,31 +0,0 @@
# VSCode Remote Development - Developing inside a Containers
This folder contains configuration files that can be used to opt into working on this repository in a [Docker container](https://www.docker.com/resources/what-container) via [VSCode](https://code.visualstudio.com/)'s Remote Development feature (see below).
Info on remote development and developing inside a container with VSCode:
- [VSCode: Remote Development](https://code.visualstudio.com/docs/remote/remote-overview)
- [VSCode: Developing inside a Container](https://code.visualstudio.com/docs/remote/containers)
- [VSCode: Remote Development FAQ](https://code.visualstudio.com/docs/remote/faq)
## Usage
_Prerequisite: [Install Docker](https://docs.docker.com/install) on your local environment._
To get started, read and follow the instuctions in [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). The [.devcontainer/](.) directory contains pre-configured `devcontainer.json` and `Dockerfile` files, which you can use to set up remote development with a docker container.
In a nutshell, you need to:
- Install the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
- Copy [recommended-Dockerfile](./recommended-Dockerfile) to `Dockerfile` (and optionally tweak to suit your needs).
- Copy [recommended-devcontainer.json](./recommended-devcontainer.json) to `devcontainer.json` (and optionally tweak to suit your needs).
- Open VSCode and bring up the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
- Type `Remote-Containers: Open Folder in Container` and choose your local clone of [angular/angular](https://github.com/angular/angular).
The `.devcontainer/devcontainer.json` and `.devcontainer/Dockerfile` files are ignored by git, so you can have your own local versions. We may occasionally update the template files ([recommended-devcontainer.json](./recommended-devcontainer.json), [recommended-Dockerfile](./recommended-Dockerfile)), in which case you will need to manually update your local copies (if desired).
## Updating `recommended-devcontainer.json` and `recommended-Dockerfile`
You can update and commit the recommended config files (which people use as basis for their local configs), if you find that something is broken, out-of-date or can be improved.
Please, keep in mind that any changes you make will potentially be used by many people on different environments. Try to keep these config files cross-platform compatible and free of personal preferences.

View File

@ -1,6 +1,5 @@
# Image metadata and config.
FROM circleci/node:10-browsers # Ideally, the image version should be what we use on CI.
# See `executors > browsers-executor` in `.circleci/config.yml`.
FROM circleci/node:10-browsers
LABEL name="Angular dev environment" \
description="This image can be used to create a dev environment for building Angular." \
@ -16,8 +15,7 @@ USER root
# Configure `Node.js`/`npm` and install utilities.
RUN npm config --global set user root
RUN npm install --global yarn@latest # Ideally, the version should be what we use on CI.
# See `commands > overwrite_yarn` in `.circleci/config.yml`.
RUN npm install --global yarn@1.13.0 # This needs to be in sync with what we use on CI.
# Go! (And keep going.)

939
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,939 @@
# ==================================================================================
# ==================================================================================
# Angular CODEOWNERS
# ==================================================================================
# ==================================================================================
#
# Configuration of code ownership and review approvals for the angular/angular repo.
#
# More info: https://help.github.com/articles/about-codeowners/
#
# ================================================
# General rules / philosophy
# ================================================
#
# - we trust that people do the right thing and not approve changes they don't feel confident reviewing
# - we use github teams so that we funnel code reviews to the most appropriate reviewer, this is why the team structure is fine-grained
# - we enforce that only approved PRs get merged to ensure that unreviewed code doesn't get accidentally merged
# - we delegate approval rights as much as possible so that we can scale better
# - each group must have at least one person, but several people are preferable to avoid a single point of failure issues
# - most file groups have one or two global approvers groups as fallbacks:
# - @angular/fw-global-approvers: for approving minor changes, large-scale refactorings, and emergency situations.
# - @angular/fw-global-approvers-for-docs-only-changes: for approving minor documentation-only changes that don't require engineering review
# - a small number of file groups have very limited number of reviewers because incorrect changes to the files they guard would have serious consequences (e.g. security, public api)
#
# Configuration nuances:
#
# - This configuration works in conjunction with the protected branch settings that require all changes to be made via pull requests with at least one approval.
# - This approval can come from an appropriate codeowner, or any repo collaborator (person with write access) if the PR is authored by a codeowner.
# - Each codeowners team must have write access to the repo, otherwise their reviews won't count.
#
# In the case of emergency, the repo administrators which include angular-caretaker can bypass this requirement.
# ================================================
# GitHub username registry
# (just to make this file easier to understand)
# ================================================
# alan-agius4 - Alan Agius
# alexeagle - Alex Eagle
# alxhub - Alex Rickabaugh
# AndrewKushnir - Andrew Kushnir
# andrewseguin - Andrew Seguin
# benlesh - Ben Lesh
# brandonroberts - Brandon Roberts
# devversion - Paul Gschwendtner
# filipesilva - Filipe Silva
# gkalpak - George Kalpakas
# hansl - Hans Larsen
# IgorMinar - Igor Minar
# jasonaden - Jason Aden
# jenniferfell - Jennifer Fell
# JiaLiPassion - Jia Li
# josephperrott - Joey Perrott
# kara - Kara Erickson
# kyliau - Keen Yee Liau
# matsko - Matias Niemelä
# mgechev - Minko Gechev
# mhevery - Misko Hevery
# ocombe - Olivier Combe
# petebacondarwin - Pete Bacon Darwin
# pkozlowski-opensource - Pawel Kozlowski
# robwormald - Rob Wormald
# stephenfluin - Stephen Fluin
# vikerman - Vikram Subramanian
######################################################################################################
#
# Team structure and memberships
# ------------------------------
#
# This section is here just because the GitHub UI is too hard to navigate and audit.
#
# Any changes to team structure or memberships must first be made in this file and only then
# implemented in the GitHub UI.
#######################################################################################################
# ===========================================================
# @angular/framework-global-approvers
# ===========================================================
# Used for approving minor changes, large-scale refactorings, and emergency situations.
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
#
# - IgorMinar
# - kara
# - mhevery
# - alexeagle
# ===========================================================
# @angular/framework-global-approvers-for-docs-only-changes
# ===========================================================
# Used for approving minor documentation-only changes that don't require engineering review.
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
#
# - brandonroberts
# - gkalpak
# - jenniferfell
# - petebacondarwin
# ===========================================================
# @angular/fw-animations
# ===========================================================
#
# - matsko
# ===========================================================
# @angular/tools-bazel
# ===========================================================
#
# - alexeagle
# - kyliau
# - IgorMinar
# - mgechev
# ===========================================================
# @angular/tools-cli
# ===========================================================
#
# - alexeagle
# - filipesilva
# - hansl
# - mgechev
# ===========================================================
# @angular/fw-compiler
# ===========================================================
#
# - alxhub
# ===========================================================
# @angular/fw-ngcc
# ===========================================================
#
# - alxhub
# - gkalpak
# - petebacondarwin
# ===========================================================
# @angular/fw-core
# ===========================================================
#
# - alxhub
# - AndrewKushnir
# - kara
# - mhevery
# - pkozlowski-opensource
# ===========================================================
# @angular/fw-http
# ===========================================================
#
# - alxhub
# - IgorMinar
# ===========================================================
# @angular/fw-elements
# ===========================================================
#
# - andrewseguin
# - gkalpak
# - robwormald
# ===========================================================
# @angular/fw-forms
# ===========================================================
#
# - kara
# - jasonaden
# ===========================================================
# @angular/tools-language-service
# ===========================================================
#
# - kyliau
# ===========================================================
# @angular/fw-server
# ===========================================================
#
# - alxhub
# - vikerman
# ===========================================================
# @angular/fw-router
# ===========================================================
#
# - jasonaden
# ===========================================================
# @angular/fw-service-worker
# ===========================================================
#
# - alxhub
# - gkalpak
# - IgorMinar
# ===========================================================
# @angular/fw-upgrade
# ===========================================================
#
# - gkalpak
# - petebacondarwin
# - jasonaden
# ===========================================================
# @angular/fw-testing
# ===========================================================
#
# - vikerman
# ===========================================================
# @angular/fw-i18n
# ===========================================================
#
# - AndrewKushnir
# - mhevery
# - ocombe
# - vikerman
# ===========================================================
# @angular/fw-security
# ===========================================================
#
# - IgorMinar
# - mhevery
# ===========================================================
# @angular/fw-zones
# ===========================================================
#
# - JiaLiPassion
# - mhevery
# - vikerman
# ===========================================================
# @angular/tools-benchpress
# ===========================================================
#
# - alxhub
# ===========================================================
# @angular/fw-integration
# ===========================================================
#
# - alexeagle
# - IgorMinar
# - mhevery
# ===========================================================
# @angular/docs-infra
# ===========================================================
#
# - brandonroberts
# - gkalpak
# - IgorMinar
# - petebacondarwin
# ===========================================================
# @angular/fw-docs-intro
# ===========================================================
#
# - jenniferfell
# - brandonroberts
# - IgorMinar
# - stephenfluin
# ===========================================================
# @angular/fw-docs-observables
# ===========================================================
#
# - benlesh
# - jasonaden
# ===========================================================
# @angular/fw-docs-packaging
# ===========================================================
#
# - alexeagle
# - 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
# ===========================================================
#
# - IgorMinar
# - stephenfluin
# ===========================================================
# @angular/fw-public-api
# ===========================================================
#
# - IgorMinar
# ===========================================================
# @angular/fw-dev-infra
# ===========================================================
#
# - alexeagle
# - devversion
# - filipesilva
# - gkalpak
# - IgorMinar
# - josephperrott
######################################################################################################
#
# CODEOWNERS rules
# -----------------
#
# All the following rules are applied in the order specified in this file.
# The last rule that matches wins!
#
# See https://git-scm.com/docs/gitignore#_pattern_format for pattern syntax docs.
#
######################################################################################################
# ================================================
# Default Owners
# (in case no pattern matches a path in a PR - this should be treated as a bug and result in adding the path to CODEOWNERS)
# ================================================
* @IgorMinar @angular/framework-global-approvers
# ================================================
# @angular/animations
# ================================================
/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
/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/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
# ================================================
# @angular/bazel
# ================================================
/packages/bazel/** @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/compiler
# @angular/compiler-cli
# ================================================
/packages/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/compiler-cli/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/aot-compiler.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# packages/compiler-cli/ngcc/
# ================================================
/packages/compiler-cli/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers
# ================================================
# Framework/cli integration
#
# 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
/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
# ================================================
# @angular/core
# @angular/common (except @angular/common/http)
# @angular/platform-browser
# @angular/platform-browser-dynamic
# @angular/platform-webworker
# @angular/platform-webworker-dynamic
# ================================================
/packages/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/platform-browser/** @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-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/examples/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/attribute-directives/** @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/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/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/guide/component-styles.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/component-styles/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/dependency-injection-in-action.md @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/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-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/examples/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/entry-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/feature-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/feature-modules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/feature-modules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/frequent-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/frequent-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/hierarchical-dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/hierarchical-dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/lazy-loading-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/lifecycle-hooks.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/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/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/guide/ngmodule-api.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/ngmodule-faq.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/ngmodule-faq/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/ngmodule-vs-jsmodule.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/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/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/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/providers.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/providers/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/singleton-services.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/set-document-title.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/set-document-title/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/set-document-title/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/sharing-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/structural-directives.md @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/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
# ================================================
# @angular/common/http
# @angular/http
# ================================================
/packages/common/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/http.md @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/elements
# ================================================
/packages/elements/** @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/elements/** @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/elements/** @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
# ================================================
/packages/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/forms-overview.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/forms-overview/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/forms-overview/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/form-validation.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/form-validation/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/form-validation/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/dynamic-form.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/dynamic-form/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/dynamic-form/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/reactive-forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/reactive-forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/reactive-forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/language-service
# ================================================
/packages/language-service/** @angular/tools-language-service @angular/framework-global-approvers
/aio/content/guide/language-service.md @angular/tools-language-service @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/language-service/** @angular/tools-language-service @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/platform-server
# ================================================
/packages/platform-server/** @angular/fw-server @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/universal.md @angular/fw-server @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/universal/** @angular/fw-server @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/router
# ================================================
/packages/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/router.md @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/service-worker
# ================================================
/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/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-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-intro.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/upgrade
# ================================================
/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
/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/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-2-hybrid/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/upgrade-phonecat-3-final/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/upgrade-performance.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/ajs-quick-reference.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/ajs-quick-reference/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular/**/testing
# ================================================
testing/** @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/testing.md @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/testing/** @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/images/guide/testing/** @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular i18n
# ================================================
/packages/core/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/core/src/render3/i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/core/src/render3/i18n.md @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/core/src/render3/interfaces/i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/locales/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/src/pipes/date_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/src/pipes/i18n_plural_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/src/pipes/i18n_select_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/common/src/pipes/number_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/compiler/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/compiler/src/render3/view/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/packages/compiler-cli/src/extract_i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/i18n.md @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# @angular security
# ================================================
/packages/core/src/sanitization/** @angular/fw-security
/packages/core/test/linker/security_integration_spec.ts @angular/fw-security
/packages/compiler/src/schema/** @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/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
# ================================================
# zone.js
# ================================================
/packages/zone.js/** @angular/fw-zones @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# benchpress
# ================================================
/packages/benchpress/** @angular/tools-benchpress @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
# ================================================
# /integration/*
# ================================================
/integration/** @angular/fw-integration @angular/framework-global-approvers
# ================================================
# docs-infra
# ================================================
/aio/* @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/src/** @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
# 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
# ================================================
# Docs: getting started & tutorial
# ================================================
/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/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
# ================================================
/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/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/guide/practical-observable-usage.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/guide/rx-library.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
# ================================================
# Docs: packaging, tooling, releasing
# ================================================
/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/typescript-configuration.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/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/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/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
# ================================================
# Docs: marketing
# ================================================
/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/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
# ================================================
# Build & CI Owners
# ================================================
/* @angular/fw-dev-infra
/.buildkite/** @angular/fw-dev-infra
/.circleci/** @angular/fw-dev-infra
/.codefresh/** @angular/fw-dev-infra
/.devcontainer/** @angular/fw-dev-infra
/.github/** @angular/fw-dev-infra
/.vscode/** @angular/fw-dev-infra
/docs/BAZEL.md @angular/fw-dev-infra
/packages/* @angular/fw-dev-infra
/scripts/** @angular/fw-dev-infra
/third_party/** @angular/fw-dev-infra
/tools/build/** @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
# ================================================
# Material CI
# ================================================
/tools/material-ci/** @angular/fw-core @angular/framework-global-approvers
# ================================================
# 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
# ================================================
# CODEOWNERS Owners owners ...
# ================================================
/.github/CODEOWNERS @IgorMinar @angular/framework-global-approvers

69
.github/ISSUE_TEMPLATE/1-bug-report.md vendored Normal file
View File

@ -0,0 +1,69 @@
---
name: "\U0001F41EBug report"
about: Report a bug in the Angular Framework
---
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
Oh hi there! 😄
To expedite issue processing please search open and closed issues before submitting a new one.
Existing issues often contain information about workarounds, resolution, or progress updates.
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
# 🐞 bug report
### Affected Package
<!-- Can you pin-point one or more @angular/* packages as the source of the bug? -->
<!-- ✍edit: --> The issue is caused by package @angular/....
### Is this a regression?
<!-- Did this behavior use to work in the previous version? -->
<!-- ✍️--> Yes, the previous version in which this bug was not present was: ....
### Description
<!-- ✍️--> A clear and concise description of the problem...
## 🔬 Minimal Reproduction
<!--
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-issue-repro2
-->
<!-- ✍️--> 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.
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.
You can read more about issue submission guidelines here: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue
-->
## 🔥 Exception or Error
<pre><code>
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
<!-- ✍️-->
</code></pre>
## 🌍 Your Environment
**Angular Version:**
<pre><code>
<!-- run `ng version` and paste output below -->
<!-- ✍️-->
</code></pre>
**Anything else relevant?**
<!-- ✍Is this a browser specific issue? If so, please specify the browser and version. -->
<!-- ✍Do any of these matter: operating system, IDE, package manager, HTTP server, ...? If so, please mention it below. -->

View File

@ -0,0 +1,32 @@
---
name: "\U0001F680Feature request"
about: Suggest a feature for Angular Framework
---
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
Oh hi there! 😄
To expedite issue processing please search open and closed issues before submitting a new one.
Existing issues often contain information about workarounds, resolution, or progress updates.
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
# 🚀 feature request
### Relevant Package
<!-- Can you pin-point one or more @angular/* packages the are relevant for this feature request? -->
<!-- ✍edit: --> This feature request is for @angular/....
### Description
<!-- ✍️--> A clear and concise description of the problem or missing capability...
### Describe the solution you'd like
<!-- ✍️--> If you have a solution in mind, please describe it.
### Describe alternatives you've considered
<!-- ✍️--> Have you considered any alternative solutions or workarounds?

55
.github/ISSUE_TEMPLATE/3-docs-bug.md vendored Normal file
View File

@ -0,0 +1,55 @@
---
name: "📚 Docs or angular.io issue report"
about: Report an issue in Angular's documentation or angular.io application
---
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
Oh hi there! 😄
To expedite issue processing please search open and closed issues before submitting a new one.
Existing issues often contain information about workarounds, resolution, or progress updates.
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
# 📚 Docs or angular.io bug report
### Description
<!-- ✍edit:--> A clear and concise description of the problem...
## 🔬 Minimal Reproduction
### What's the affected URL?**
<!-- ✍edit:--> https://angular.io/...
### Reproduction Steps**
<!-- If applicable please list the steps to take to reproduce the issue -->
<!-- ✍edit:-->
### Expected vs Actual Behavior**
<!-- If applicable please describe the difference between the expected and actual behavior after following the repro steps. -->
<!-- ✍edit:-->
## 📷Screenshot
<!-- Often a screenshot can help to capture the issue better than a long description. -->
<!-- ✍upload a screenshot:-->
## 🔥 Exception or Error
<pre><code>
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
<!-- ✍️-->
</code></pre>
## 🌍 Your Environment
### Browser info
<!-- ✍Is this a browser specific issue? If so, please specify the device, browser, and version. -->
### Anything else relevant?
<!-- ✍Please provide additional info if necessary. -->

View File

@ -0,0 +1,11 @@
---
name: ⚠️ Security issue disclosure
about: Report a security issue in Angular Framework, Material, or CLI
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
Please read https://angular.io/guide/security#report-issues on how to disclose security related issues.
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -0,0 +1,16 @@
---
name: "❓Support request"
about: Questions and requests for support
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
Please do not file questions or support requests on the GitHub issues tracker.
You can get your questions answered using other communication channels. Please see:
https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Thank you!
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

13
.github/ISSUE_TEMPLATE/6-angular-cli.md vendored Normal file
View File

@ -0,0 +1,13 @@
---
name: "\U0001F6E0Angular CLI"
about: Issues and feature requests for Angular CLI
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
Please file any Angular CLI issues at: https://github.com/angular/angular-cli/issues/new
For the time being, we keep Angular CLI issues in a separate repository.
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -0,0 +1,13 @@
---
name: "\U0001F48EAngular Material"
about: Issues and feature requests for Angular Material
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
Please file any Angular Material issues at: https://github.com/angular/material2/issues/new
For the time being, we keep Angular Material issues in a separate repository.
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -1,22 +0,0 @@
---
name: "📚Traducir doc al español"
about: Solicitud para traducir ciertos docs al español
---
📚Traducir: <!-- ✍️ editar: --> creating-libraries.md
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
Traducción de la documentación oficial de Angular a español
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
## Nombre del archivo:
<!-- ✍️ editar: --> creating-libraries.md
## Ruta donde se encuentra el archivo dentro del proyecto de Angular
<!-- ✍️ editar: --> https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md

View File

@ -1,35 +1,43 @@
## Lista de Verificación del PR
Comprueba si tu PR cumple los siguientes requisitos:
## PR Checklist
Please check if your PR fulfills the following requirements:
- [ ] El mensaje de commit esta conforme con [nuestras reglas](https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md#-formato-para-el-mensaje-de-los-commits)
- [ ] Probe los cambios que agregué (arreglo de bugs / funcionalidades)
- [ ] Revisé previamente las traducciones o cambios de contenido
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/blob/master/aio/diccionario-de-términos.md) en español
- [ ] He creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
- [ ] He enlazado el commit con el issue correspondiente <!-- ejemplo Fixes #X -->
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
## Tipo de PR
¿Qué tipo de cambio introduce este PR?
## PR Type
What kind of change does this PR introduce?
<!-- Marca con una "x" las opciones que aplican. -->
<!-- Please check the one that applies to this PR using "x". -->
- [ ] Bugfix
- [ ] Funcionalidad
- [ ] Actualización de el estilo del código (formato, variables locales)
- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api)
- [ ] Cambios relacionados al build
- [ ] Cambios relacionados al CI (Integración continua)
- [ ] Cambios en el contenido de la documentación
- [ ] Cambios en la aplicación / infraestructura de angular.io
- [ ] Otro... Por favor describe la:
## ¿Cuál es el comportamiento actual?
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
-->
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] angular.io application / infrastructure changes
- [ ] Other... Please describe:
## ¿Cuál es el nuevo comportamiento?
<!--
Ejemplo: Archivo en inglés traducido al español
-->
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
Issue Number: N/A
## What is the new behavior?
## Does this PR introduce a breaking change?
- [ ] Yes
- [ ] No
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
## Other information

View File

@ -30,7 +30,7 @@ merge:
# text to show when the status is success
successDesc: "Does not affect google3"
# link to use for the details
url: "http://go/angular/g3sync"
url: "http://go/angular-g3sync"
# list of patterns to check for the files changed by the PR
# this list must be manually kept in sync with google3/third_party/javascript/angular2/copy.bara.sky
include:
@ -52,7 +52,6 @@ merge:
- "packages/elements/schematics/**"
- "packages/examples/**"
- "packages/language-service/**"
- "packages/localize/**"
- "packages/private/**"
- "packages/service-worker/**"
- "**/.gitignore"
@ -62,15 +61,10 @@ merge:
- "**/third_party/**"
- "**/tsconfig-build.json"
- "**/tsconfig.json"
- "**/rollup.config.js"
- "**/BUILD.bazel"
- "**/*.md"
- "packages/**/integrationtest/**"
- "packages/**/test/**"
- "packages/zone.js/*"
- "packages/zone.js/doc/**"
- "packages/zone.js/example/**"
- "packages/zone.js/scripts/**"
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
@ -115,7 +109,6 @@ merge:
- "ci/angular: size"
- "cla/google"
- "google3"
- "pullapprove"
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
@ -154,12 +147,6 @@ triage:
-
- "type: RFC / Discussion / question"
- "comp: *"
-
- "type: confusing"
- "comp: *"
-
- "type: use-case"
- "comp: *"
# options for the triage PR plugin
triagePR:

View File

@ -1,15 +0,0 @@
name: Lock closed inactive issues
on:
schedule:
# Run at 16:00 every day
- cron: '0 16 * * *'
jobs:
lock_closed:
if: github.repository == 'angular/angular'
runs-on: ubuntu-latest
steps:
- uses: angular/dev-infra/github-actions/lock-closed@66462f6
with:
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}

12
.gitignore vendored
View File

@ -3,26 +3,23 @@
/dist/
/bazel-out
/integration/bazel/bazel-*
*.log
e2e_test.*
node_modules
tools/gulp-tasks/cldr/cldr-data/
# Include when developing application packages.
pubspec.lock
.c9
.idea/
.devcontainer/*
!.devcontainer/README.md
!.devcontainer/recommended-devcontainer.json
!.devcontainer/recommended-Dockerfile
.settings/
.vscode/launch.json
.vscode/settings.json
.vscode/tasks.json
*.swo
modules/.settings
modules/.vscode
.vimrc
.nvimrc
# Don't check in secret files
*secret.js
@ -40,8 +37,3 @@ yarn-error.log
# User specific bazel settings
.bazelrc.user
.notes.md
baseline.json
# Ignore .history for the xyz.local-history VSCode extension
.history

View File

@ -1,145 +0,0 @@
<type>(<scope>): <summary>
<Describe the motivation behind this change - explain WHY you are making this change. Wrap all lines
at 100 characters.>
Fixes #<issue number>
# ────────────────────────────────────────── 100 chars ────────────────────────────────────────────┤
# Example Commit Messages
# =======================
# ─── Example: Simple refactor ────────────────────────────────────────────────────────────────────┤
# refactor(core): rename refreshDynamicEmbeddedViews to refreshEmbeddedViews
#
# Improve code readability. The original name no longer matches how the function is used.
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# ─── Example: Simple docs change ─────────────────────────────────────────────────────────────────┤
# docs: clarify the service limitation in providers.md guide
#
# Fixes #36332
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# ─── Example: A bug fix ──────────────────────────────────────────────────────────────────────────┤
# fix(ngcc): ensure lockfile is removed when `analyzeFn` fails
#
# Previously an error thrown in the `analyzeFn` would cause the ngcc process to exit immediately
# without removing the lockfile, and potentially before the unlocker process had been successfully
# spawned resulting in the lockfile being orphaned and left behind.
#
# Now we catch these errors and remove the lockfile as needed.
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# ─── Example: Breaking change ────────────────────────────────────────────────────────────────────┤
# feat(bazel): simplify ng_package by dropping esm5 and fesm5
#
# esm5 and fesm5 distributions are no longer needed and have been deprecated in the past.
#
# https://v9.angular.io/guide/deprecations#esm5-and-fesm5-code-formats-in-angular-npm-packages
#
# This commit modifies ng_package to no longer distribute these two formats in npm packages built by
# ng_package (e.g. @angular/core).
#
# This commit intentionally doesn't fully clean up the ng_package rule to remove all traces of esm5
# and fems5 build artifacts as that is a bigger cleanup and currently we are narrowing down the
# scope of this change to the MVP needed for v10, which in this case is 'do not put esm5 and fesm5'
# into the npm packages.
#
# More cleanup to follow: https://angular-team.atlassian.net/browse/FW-2143
#
# BREAKING CHANGE: esm5 and fesm5 format is no longer distributed in Angular's npm packages e.g.
# @angular/core
#
# Angular CLI will automatically downlevel the code to es5 if differential loading is enabled in the
# Angular project, so no action is required from Angular CLI users.
#
# If you are not using Angular CLI to build your application or library, and you need to be able to
# build es5 artifacts, then you will need to downlevel the distributed Angular code to es5 on your
# own.
#
#
# Fixes #1234
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
# Angular Commit Message Format
# =============================
#
# The full specification of the Angular Commit Message Format can be found at
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
#
# The following is an excerpt of the specification with the most commonly needed info.
#
# Each commit message consists of a *header*, a *body*, and a *footer*.
#
# <header>
# <BLANK LINE>
# <body>
# <BLANK LINE>
# <footer>
#
# The header is mandatory.
#
# The body is mandatory for all commits except for those of scope "docs". When the body is required
# it must be at least 20 characters long.
#
# The footer is optional.
#
# Any line of the commit message cannot be longer than 100 characters.
#
#
# Commit Message Header
# ---------------------
#
# <type>(<scope>): <short summary>
# │ │ │
# │ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
# │ │
# │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
# │ elements|forms|http|language-service|localize|platform-browser|
# │ platform-browser-dynamic|platform-server|platform-webworker|
# │ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
# │ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
# │
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
#
#
# Commit Message Body
# ---------------------
#
# Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
#
# Explain the motivation for the change in the commit message body. This commit message should
# explain WHY you are making the change. You can include a comparison of the previous behavior with
# the new behavior in order to illustrate the impact of the change.
#
#
# Commit Message Footer
# ---------------------
#
# The footer can contain information about breaking changes and is also the place to reference
# GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
#
# ```
# BREAKING CHANGE: <breaking change summary>
# <BLANK LINE>
# <breaking change description + migration instructions>
# <BLANK LINE>
# <BLANK LINE>
# Fixes #<issue number>
# ```
#
# Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of
# the breaking change, a blank line, and a detailed description of the breaking change that also
# includes migration instructions.
#

View File

@ -1,53 +0,0 @@
import {CommitMessageConfig} from '../dev-infra/commit-message/config';
/**
* The configuration for `ng-dev commit-message` commands.
*/
export const commitMessage: CommitMessageConfig = {
maxLineLength: 120,
minBodyLength: 20,
minBodyLengthTypeExcludes: ['docs', 'upstream'],
types: [
'build',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'release',
'style',
'test',
'upstream',
],
scopes: [
'animations',
'bazel',
'benchpress',
'changelog',
'common',
'compiler',
'compiler-cli',
'core',
'dev-infra',
'docs-infra',
'elements',
'forms',
'http',
'language-service',
'localize',
'migrations',
'ngcc',
'packaging',
'platform-browser',
'platform-browser-dynamic',
'platform-server',
'platform-webworker',
'platform-webworker-dynamic',
'router',
'service-worker',
'upgrade',
've',
'zone.js',
]
};

View File

@ -1,11 +0,0 @@
import {commitMessage} from './commit-message';
import {format} from './format';
import {github} from './github';
import {merge} from './merge';
module.exports = {
commitMessage,
format,
github,
merge,
};

View File

@ -1,22 +0,0 @@
import {FormatConfig} from '../dev-infra/format/config';
/**
* Configuration for the `ng-dev format` command.
*/
export const format: FormatConfig = {
'clang-format': {
'matchers': [
'**/*.{js,ts}',
// TODO: burn down format failures and remove aio and integration exceptions.
'!aio/**',
'!integration/**',
// Both third_party and .yarn are directories containing copied code which should
// not be modified.
'!third_party/**',
'!.yarn/**',
// Do not format d.ts files as they are generated
'!**/*.d.ts',
]
},
'buildifier': true
};

View File

@ -1,15 +0,0 @@
# The file is inert unless it's explicitly included into the local git config via:
#
# ```
# git config --add include.path '../.ng-dev/gitconfig'
# ```
#
# Calling that command will append the following into `.git/config` of the current git workspace
# (i.e. $GIT_DIR, typically `angular/.git/config`):
#
# ```
# [include]
# path = ../.ng-dev/gitconfig
# ```
[commit]
template = .gitmessage

View File

@ -1,11 +0,0 @@
import {GithubConfig} from '../dev-infra/utils/config';
/**
* Github configuration for the `ng-dev` command. This repository is used as
* remote for the merge script and other utilities like `ng-dev pr rebase`.
*/
export const github: GithubConfig = {
owner: 'angular',
name: 'angular'
};

View File

@ -1,38 +0,0 @@
import {MergeConfig} from '../dev-infra/pr/merge/config';
/**
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
* are respected by the merge script (e.g. the target labels).
*/
export const merge = (): MergeConfig => {
// TODO: resume dynamically determining patch branch
const patch = '10.0.x';
return {
githubApiMerge: false,
claSignedLabel: 'cla: yes',
mergeReadyLabel: /^PR action: merge(-assistance)?/,
caretakerNoteLabel: 'PR action: merge-assistance',
commitMessageFixupLabel: 'commit message fixup',
labels: [
{
pattern: 'PR target: master-only',
branches: ['master'],
},
{
pattern: 'PR target: patch-only',
branches: [patch],
},
{
pattern: 'PR target: master & patch',
branches: ['master', patch],
},
],
requiredBaseCommits: {
// PRs that target either `master` or the patch branch, need to be rebased
// on top of the latest commit message validation fix.
// These SHAs are the commits that update the required license text in the header.
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
},
};
};

2
.nvmrc
View File

@ -1 +1 @@
12.14.1
10.9.0

File diff suppressed because it is too large Load Diff

18
.vscode/README.md vendored
View File

@ -1,25 +1,23 @@
# VSCode Configuration
This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings), [Tasks](https://code.visualstudio.com/docs/editor/tasks), [Launch Configurations](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations) 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.
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 configurations follow the steps below:
To use the recommended settings follow the steps below:
- install the recommneded extensions in `.vscode/extensions.json`
- copy (or link) `.vscode/recommended-settings.json` to `.vscode/settings.json`
- copy (or link) `.vscode/recommended-launch.json` to `.vscode/launch.json`
- copy (or link) `.vscode/recommended-tasks.json` to `.vscode/tasks.json`
- 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 contents.
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-*.json` files
## Editing `.vscode/recommended-settings.json`
If you wish to add extra configuration items please keep in mind any modifications you make here will be used by many users.
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/configuations to things that help facilitate the development process and avoid altering the user workflow whenever possible.
Try to keep these settings to things that help facilitate the development process and avoid altering the user workflow whenever possible.

View File

@ -1,85 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach to bazel test ... --config=debug",
"type": "node",
"request": "attach",
"port": 9229,
"address": "localhost",
"restart": false,
"sourceMaps": true,
"localRoot": "${workspaceRoot}",
"remoteRoot": "${workspaceRoot}",
"stopOnEntry": false,
"timeout": 600000,
},
{
"name": "Attach to bazel test ... --config=debug (no source maps)",
"type": "node",
"request": "attach",
"port": 9229,
"address": "localhost",
"restart": false,
"sourceMaps": false,
"localRoot": "${workspaceRoot}",
"remoteRoot": "${workspaceRoot}",
"stopOnEntry": false,
"timeout": 600000,
},
{
"name": "IVY:packages/core/test/acceptance",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test/acceptance",
"--config=debug"
],
"port": 9229,
"address": "localhost",
"restart": true,
"sourceMaps": true,
"timeout": 600000,
},
{
"name": "IVY:packages/core/test/render3",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test/render3",
"--config=debug"
],
"port": 9229,
"address": "localhost",
"restart": true,
"sourceMaps": true,
"timeout": 600000,
},
{
"name": "IVY:packages/core/test",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test",
"--config=debug"
],
"port": 9229,
"address": "localhost",
"restart": true,
"sourceMaps": true,
"timeout": 600000,
},
]
}

View File

@ -26,7 +26,6 @@
"**/bazel-out": true,
"**/dist": true,
"**/aio/src/generated": true,
".history": true,
},
"git.ignoreLimitWarning": true,
}
}

View File

@ -1,113 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "IVY:packages/core/test/...",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test",
"packages/core/test/acceptance",
"packages/core/test/render3",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
{
"label": "VE:packages/core/test/...",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"packages/core/test",
"packages/core/test/acceptance",
"packages/core/test/render3",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
{
"label": "IVY:packages/core/test/acceptance",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test/acceptance",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
{
"label": "VE:packages/core/test/acceptance",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"packages/core/test/acceptance",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
{
"label": "IVY:packages/core/test",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
{
"label": "VE:packages/core/test",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"packages/core/test",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
{
"label": "IVY:packages/core/test/render3",
"type": "shell",
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
"args": [
"test",
"--config=ivy",
"packages/core/test/render3",
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
},
},
],
}

View File

@ -1,13 +0,0 @@
# Yarn Vendoring
We utilize Yarn's `yarn-path` configuration in a shared `.yarnrc` file to enforce
everyone using the same version of Yarn. Yarn checks the `.yarnrc` file to
determine if yarn should delegate the command to a vendored version at the
provided path.
## How to update
To update to the latest version of Yarn as our vendored version:
- Run this command
```sh
yarn policies set-version latest
```
- Remove the previous version

File diff suppressed because one or more lines are too long

View File

@ -1,5 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
yarn-path ".yarn/releases/yarn-1.22.4.js"

View File

@ -1,13 +1,12 @@
package(default_visibility = ["//visibility:public"])
load("//tools:defaults.bzl", "karma_web_test")
exports_files([
"LICENSE",
"protractor-perf.conf.js",
"karma-js.conf.js",
"browser-providers.conf.js",
"scripts/ci/track-payload-size.sh",
"scripts/ci/payload-size.sh",
"scripts/ci/payload-size.js",
"package.json",
])
alias(
@ -19,15 +18,15 @@ filegroup(
name = "web_test_bootstrap_scripts",
# do not sort
srcs = [
"@npm//:node_modules/core-js/client/core.js",
"//packages/zone.js/bundles:zone.umd.js",
"//packages/zone.js/bundles:zone-testing.umd.js",
"//packages/zone.js/bundles:task-tracking.umd.js",
"@npm//node_modules/core-js:client/core.js",
"@npm//node_modules/zone.js:dist/zone.js",
"@npm//node_modules/zone.js:dist/zone-testing.js",
"@npm//node_modules/zone.js:dist/task-tracking.js",
"//:test-events.js",
"//:third_party/shims_for_IE.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",
"@npm//node_modules/systemjs:dist/system.src.js",
"@npm//node_modules/reflect-metadata:Reflect.js",
],
)
@ -36,14 +35,58 @@ filegroup(
srcs = [
# 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)
"@npm//:node_modules/angular/angular.js",
"@npm//:node_modules/angular/angular.min.js",
"@npm//:node_modules/angular-1.5/angular.js",
"@npm//:node_modules/angular-1.5/angular.min.js",
"@npm//:node_modules/angular-1.6/angular.js",
"@npm//:node_modules/angular-1.6/angular.min.js",
"@npm//:node_modules/angular-mocks/angular-mocks.js",
"@npm//:node_modules/angular-mocks-1.5/angular-mocks.js",
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
"@npm//node_modules/angular:angular.js",
"@npm//node_modules/angular:angular.min.js",
"@npm//node_modules/angular-1.5:angular.js",
"@npm//node_modules/angular-1.5:angular.min.js",
"@npm//node_modules/angular-1.6:angular.js",
"@npm//node_modules/angular-1.6:angular.min.js",
"@npm//node_modules/angular-mocks:angular-mocks.js",
"@npm//node_modules/angular-mocks-1.5:angular-mocks.js",
"@npm//node_modules/angular-mocks-1.6:angular-mocks.js",
],
)
# To run a karma_web_test target locally on SauceLabs:
# 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`
# NOTE: start-tunnel.sh uses `node_modules/sauce-connect` which is current linux specific:
# "sauce-connect": "https://saucelabs.com/downloads/sc-4.5.3-linux.tar.gz".
# On OSX or Windows you'll need to use the appropriate sauce-connect binary.
# 3) run target with `yarn bazel test --config=saucelabs <target>`
# NOTE: --config=saucelabs is required as it makes the SAUCE_XXX environment variables available to
# the action. See /.bazelrc.
karma_web_test(
name = "test_web_all",
tags = [
"local",
"manual",
"saucelabs",
],
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/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)
],
)

File diff suppressed because it is too large Load Diff

View File

@ -1,72 +1,12 @@
# Código de Conducta
# Contributor Code of Conduct
## Version 0.3b-angular
## 1. Propósito
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
“Prometemos brindar cortesía y respeto a cualquier persona involucrada en esta comunidad, sin importar el género con el que se identifique, su orientación sexual, limitación física, edad, raza, etnia, religión o nivel de conocimiento. Esperamos que cualquiera que desee contribuir en este proyecto brinde el mismo comportamiento”
Communication through any of Angular's channels (GitHub, Gitter, IRC, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
Bajo ese principio queremos enfocar esta comunidad, una comunidad de respeto por el otro, donde cualquiera que sienta pasión por Angular y desee involucrarse con cualquier tipo de actividad deberá ayudar a mantener una atmósfera de cortesía por el otro, respetando los pensamientos, acciones, ideales y propuestas del otro.
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
## 2. Comportamiento esperado
If any member of the community violates this code of conduct, the maintainers of the Angular project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
- Evitar usar expresiones o gestos insultantes, humillantes o intimidatorios para referirnos a otros.
- Ejercita la consideración y el respeto en tus comunicaciones y acciones.
- Absténte de adoptar una conducta y un lenguaje degradantes, discriminatorios, abusivos o acosadores.
- Evitar comportamientos que agredan las expresiones de identidad, género, creencias religiosas, acciones que lastimen o los aíslen a otros.
- Evitar comentarios sobre ideas políticas.
- No se toleran conductas físicas y actitudes dirigidas al descrédito personal, físico o emocional de cualquier persona.
- No se toleran chistes y comentarios excluyentes, sexistas y racistas.
- Se rechaza actitudes de hostigamiento.
- Se rechaza el acoso: este se entiende como cualquier tipo de comentario verbal que refuerce discriminación por género, identidad y expresión de género, orientación sexual, discapacidad, apariencia física, tamaño corporal, raza, edad o religión en contextos laborales o sociales.
- No se tolera el contacto físico y/o la atención sexual no deseada.
- Promover la igualdad de oportunidades de formación, educación, intercambio y retroalimentación antes, durante y después de los eventos.
- Intenta colaborar en lugar de generar conflicto.
- Sé consciente de tu entorno y de tus compañeros participantes. Alerta a líderes de la comunidad si notas una situación peligrosa, alguien en apuros, o violaciones de este Código de Conducta, incluso si parecen intrascendentes.
## 3. Comportamiento inaceptable
Comportamientos inaceptables incluyen: intimidación, acoso, abuso, discriminación, comunicación despectiva o degradante o acciones por cualquier participante en nuestra comunidad ya sea virtual, o en las comunicaciones uno-a-uno que se realizan en el contexto de la comunidad. Por favor ser respetuoso con todos.
El acoso incluye: comentarios nocivos o perjudiciales, verbales o escritos relacionados con el género, la orientación sexual, raza, religión, discapacidad; uso inadecuado de desnudos y / o imágenes sexuales en espacios públicos (incluyendo la presentación diapositivas); intimidación deliberada, acecho o seguimiento; fotografías o grabaciones acosadoras; interrupción sostenida de charlas y otros eventos; contacto físico inapropiado, y atención sexual no deseada.
## 4. Consecuencias de comportamiento inaceptable
Se espera que personas a quienes se les solicite que detengan su comportamiento inaceptable lo hagan de manera inmediata esto será válido para cualquier miembro de la comunidad.
En caso de presentarse una violación al código de conducta de manera repetida se tendrá cero tolerancia a este comportamiento por parte de los organizadores.
Si un miembro de la comunidad participa en una conducta inaceptable, los organizadores pueden tomar cualquier acción que consideren apropiada, hasta e incluyendo una prohibición temporal o expulsión permanente de la comunidad, sin previo aviso.
Priorizamos la seguridad de las personas marginadas sobre la comodidad de las personas privilegiadas. Nos reservamos el derecho de no actuar sobre las quejas relacionadas con:
- El "racismo inverso", "sexismo inverso" y "cisfobia".
- Comunicación razonable de límites, como "déjame en paz", "vete" o "no estoy discutiendo esto contigo".
- Al comunicarse en un "tono", no se encuentra agradable.
- Identificando comportamientos o suposiciones racistas, sexistas, cissexistas u opresivas.
## 5. ¿Qué hacer si se incumple el código de conducta?
Si eres víctima o testigo de una conducta inaceptable, o tienes cualquier inquietud, por favor comunícate con el equipo organizador lo antes posible:
- Mensaje directo: Michael Prentice (@splaktar)
- Mensaje directo: Jorge Cano (@jorgeucano)
- Mensaje directo: Andrés Villanueva (@villanuevand)
- Email: [soporte@angular.lat](mailto:soporte@angular.lat)
### ¿Qué pasa después?
- Una vez haya sido notificada el no cumplimiento de la norma, el equipo de liderazgo se reunirán y analizarán el caso.
- Los incidentes presentados se manejarán con discreción.
- Los organizadores se comunicarán con la persona que incumplió la norma y tomarán las medidas respectivas.
- Se realizará un acompañamiento a la persona agredida y se apoyará.
- Si el incidente se hace público, Angular Hispano no se hace responsable de los perjuicios que esto pueda ocasionar en el agresor o el agredido.
## 6. Alcance
Esperamos que todos los participantes de la comunidad (organizadores, voluntarios, contribuyentes pagados o de otro modo; patrocinadores; y otros invitados) se atengan a este Código de Conducta en todos los espacios virtuales y presenciales, así como en todas las comunicaciones de uno-a-uno pertinentes la comunidad.
### Colaboradores
- Alejandra Giraldo
- Vanessa Marely
- Mariano Alvarez
- Andrés Villanueva
- Michael Prentice
- javascript&friends
- Angular
- She Codes Angular
- Colombia dev
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [conduct@angular.io](mailto:conduct@angular.io).

View File

@ -1,359 +0,0 @@
# Contributing to Angular
We would love for you to contribute to Angular and help make it even better than it is today!
As a contributor, here are the guidelines we would like you to follow:
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
- [Coding Rules](#rules)
- [Commit Message Guidelines](#commit)
- [Signing the CLA](#cla)
## <a name="coc"></a> Code of Conduct
Help us keep Angular open and inclusive.
Please read and follow our [Code of Conduct][coc].
## <a name="question"></a> Got a Question or Problem?
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
Stack Overflow is a much better place to ask questions since:
- there are thousands of people willing to help on Stack Overflow
- questions and answers stay available for public viewing so your question/answer might help someone else
- Stack Overflow's voting system assures that the best answers are prominently visible.
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
## <a name="issue"></a> Found a Bug?
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Missing a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
In order to reproduce bugs, we require that you provide a minimal reproduction.
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
Often, developers find coding problems themselves while preparing a minimal reproduction.
We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
You don't want to duplicate existing efforts.
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
Discussing the design upfront helps to ensure that we're ready to accept your work.
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
We cannot accept code without a signed CLA.
Make sure you author all contributed Git commits with email address associated with your CLA signature.
4. Fork the angular/angular repo.
5. Make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
```
6. Create your patch, **including appropriate test cases**.
7. Follow our [Coding Rules](#rules).
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
```shell
git commit -a
```
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
10. Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
11. In GitHub, send a pull request to `angular:master`.
If we ask for changes via code reviews then:
* Make the required updates.
* Re-run the Angular test suites to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
```shell
git rebase master -i
git push -f
```
That's it! Thank you for your contribution!
#### After your pull request is merged
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
```shell
git push origin --delete my-fix-branch
```
* Check out the master branch:
```shell
git checkout master -f
```
* Delete the local branch:
```shell
git branch -D my-fix-branch
```
* Update your master with the latest upstream version:
```shell
git pull --ff upstream master
```
## <a name="rules"></a> Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
* All public API methods **must be documented**.
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
## <a name="commit"></a> Commit Message Format
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
We have very precise rules over how our Git commit messages must be formatted.
This format leads to **easier to read commit history**.
Each commit message consists of a **header**, a **body**, and a **footer**.
```
<header>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
The `body` is mandatory for all commits except for those of scope "docs".
When the body is required it must be at least 20 characters long.
The `footer` is optional.
Any line of the commit message cannot be longer than 100 characters.
#### <a href="commit-header"></a>Commit Message Header
```
<type>(<scope>): <short summary>
│ │ │
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
│ │
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
│ elements|forms|http|language-service|localize|platform-browser|
│ platform-browser-dynamic|platform-server|platform-webworker|
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
```
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
##### Type
Must be one of the following:
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
* **docs**: Documentation only changes
* **feat**: A new feature
* **fix**: A bug fix
* **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
* **test**: Adding missing tests or correcting existing tests
##### Scope
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
The following is the list of supported scopes:
* `animations`
* `bazel`
* `benchpress`
* `common`
* `compiler`
* `compiler-cli`
* `core`
* `elements`
* `forms`
* `http`
* `language-service`
* `localize`
* `platform-browser`
* `platform-browser-dynamic`
* `platform-server`
* `platform-webworker`
* `platform-webworker-dynamic`
* `router`
* `service-worker`
* `upgrade`
* `zone.js`
There are currently a few exceptions to the "use package name" rule:
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
* `changelog`: used for updating the release notes in CHANGELOG.md
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
* `migrations`: used for changes to the `ng update` migrations.
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
##### Summary
Use the summary field to provide a succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize the first letter
* no dot (.) at the end
#### Commit Message Body
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
#### Commit Message Footer
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
```
BREAKING CHANGE: <breaking change summary>
<BLANK LINE>
<breaking change description + migration instructions>
<BLANK LINE>
<BLANK LINE>
Fixes #<issue number>
```
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
### Revert commits
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
The content of the commit message body should contain:
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
- a clear description of the reason for reverting the commit message.
## <a name="cla"></a> Signing the CLA
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
* For individuals, we have a [simple click-through form][individual-cla].
* For corporations, we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
* https://help.github.com/articles/about-commit-email-addresses/
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
[angular-group]: https://groups.google.com/forum/#!forum/angular
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
[github]: https://github.com/angular/angular
[gitter]: https://gitter.im/angular/angular
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
[jsfiddle]: http://jsfiddle.net
[plunker]: http://plnkr.co/edit
[runnable]: http://runnable.com
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular

View File

@ -1,340 +1,281 @@
# Contribuye a Angular
# Contributing to Angular
¡Nos encantaría que contribuyeras a Angular y que ayudaras a hacerlo aún mejor de lo que es hoy!
Como colaborador, estos son los lineamientos que nos gustaría que siguieras:
We would love for you to contribute to Angular and help make it even better than it is
today! As a contributor, here are the guidelines we would like you to follow:
- [Código de conducta](#coc)
- [¿Preguntas o problemas?](#question)
- [_Issues_ y _bugs_](#issue)
- [Solicitud de funcionalidades](#feature)
- [Guía para la creación de issues y PRs](#submit)
- [Reglas del código](#rules)
- [Convención para el mensaje de los _commits_](#commit)
- [Firma del Acuerdo de Licencia de Colaborador (CLA)](#cla)
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
- [Coding Rules](#rules)
- [Commit Message Guidelines](#commit)
- [Signing the CLA](#cla)
## <a name="coc"></a> Code of Conduct
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
## <a name="question"></a> Got a Question or Problem?
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
Stack Overflow is a much better place to ask questions since:
- there are thousands of people willing to help on Stack Overflow
- questions and answers stay available for public viewing so your question / answer might help someone else
- Stack Overflow's voting system assures that the best answers are prominently visible.
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
## <a name="issue"></a> Found a Bug?
If you find a bug in the source code, you can help us by
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
[submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Missing a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
Repository. If you would like to *implement* a new feature, please submit an issue with
a proposal for your work first, to be sure that we can use it.
Please consider what kind of change it is:
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
and help you to craft the change so that it is successfully accepted into the project.
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction. Having a minimal reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions.
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
We will be insisting on a minimal reproduction scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
## <a name="coc"></a> Código de conducta
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:
Ayúdanos a mantener Angular abierto e inclusivo.
Por favor lee y sigue nuestro [Código de conducta][coc].
## <a name="question"></a> ¿Tienes alguna pregunta o problema?
No abras *issues* para preguntas de soporte general ya que queremos mantener los *issues* de GitHub para reporte de *bugs* y solicitud de funcionalidades.
En su lugar, recomendamos utilizar [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) para hacer preguntas relacionadas con soporte. Al crear una nueva pregunta en Stack Overflow, asegúrate de agregar el etiqueta (tag) de `angular`.
Stack Overflow es mucho mejor para hacer preguntas ya que:
- Hay miles de personas dispuestas a ayudar en preguntas y respuestas de Stack Overflow
que permanecen disponibles para el público, por lo que tu pregunta o respuesta podría ayudar a otra persona.
- El sistema de votación de Stack Overflow asegura que las mejores respuestas sobresalgan y sean visibles.
Para ahorrar tu tiempo y el nuestro, cerraremos sistemáticamente todos los *issues* que sean solicitudes de soporte general y redirigiremos a las personas a Stack Overflow.
Si deseas chatear sobre alguna pregunta en tiempo real, puedes hacerlo a través de nuestro [canal de Gitter][gitter].
## <a name="issue"></a> ¿Encontraste un Bug?
Si encontraste un error en el código fuente, puedes ayudarnos [creando un *issue*](#submit-issue) en nuestro [repositorio de GitHub][github].
O incluso mejor, puedes [crear un *Pull Request*](#submit-pr) con la solución.
## <a name="feature"></a> ¿Falta alguna funcionalidad?
Puedes solicitar una nueva funcionalidad [creando un *issue*](#submit-issue) en nuestro repositorio de GitHub.
Si deseas implementar una nueva funcionalidad, por favor considera el tamaño del cambio para determinar los pasos correctos para continuar:
* Para un **cambio significativo**, primero abre un *issue* y describe tu propuesta para que pueda ser discutida.
Este proceso nos permite coordinar mejor nuestros esfuerzos, evitar trabajo duplicado y ayudarte a diseñar el cambio para que sea aceptado con éxito en el proyecto.
**Nota**: Agregar un nuevo tema a la documentación o reescribir significativamente un tema, también cuenta como *cambio significativo*.
* **Cambios pequeños** pueden ser elaborados y directamente [creados como un _pull request_](#submit-pr).
## <a name="submit"></a> Guía para la creación de issues y PRs
### <a name="submit-issue"></a> Creación de _issues_
Antes de crear un *issue*, por favor busca en el el *issue tracker*, quizá un *issue* para tu problema ya existe y la discusión puede informarte sobre soluciones alternativas disponibles.
Queremos solucionar todos los problemas lo antes posible, pero antes de corregir un bug necesitamos reproducirlo y confirmarlo.
Para reproducir errores, requerimos que proporciones una reproducción mínima.
Tener un escenario reproducible mínimo nos brinda una gran cantidad de información importante sin tener que ir y venir con preguntas adicionales.
Una reproducción mínima nos permite confirmar rápidamente un bug (o señalar un problema de código), así también confirmar que estamos solucionando el problema correcto.
Requerimos una reproducción mínima para ahorrar tiempo a los encargados del mantenimiento y en última instancia, poder corregir más bugs.
A menudo los desarrolladores encuentran problemas de código mientras preparan una reproducción mínima.
Entendemos que a veces puede ser difícil extraer porciones esenciales de código de un código más grande, pero realmente necesitamos aislar el problema antes de poder solucionarlo.
Desafortunadamente no podemos investigar/corregir errores sin una reproducción mínima, por lo que si no tenemos tu retroalimentación del bug, vamos a cerrar el *issue* ya que no tiene suficiente información para reproducirse.
Puedes presentar nuevos *issues* seleccionando nuestra [plantilla de _issues_](https://github.com/angular/angular/issues/new/choose) y complentando la plantilla.
### <a name="submit-pr"></a> Creación de un Pull Requests (PR)
Antes de crear tu Pull Request (PR) considera los siguientes lineamientos:
1. Busca en [GitHub](https://github.com/angular/angular/pulls) PRs que estén abiertos o cerrados y que estén relacionados con el que vas a crear.
No deseas duplicar los esfuerzos existentes.
2. Asegúrate de que el PR describa el problema que estás solucionando o que documente el diseño de la funcionalidad que deseas agregar.
Discutir el diseño por adelantado ayuda a garantizar que estemos listos para aceptar tu trabajo.
3. Por favor firma nuestro [Acuerdo de Licencia de Colaborador (CLA)](#cla) antes de crear PRs.
No podemos aceptar el código sin el Acuerdo de Licencia de Colaborador (CLA) firmado.
Asegúrate de crear todas las contribuciones de Git con la dirección de correo electrónico asociada con tu firma del Acuerdo de Licencia de Colaborador (CLA).
4. Haz *fork* del repositorio angular/angular.
5. Haz tus cambios en una nueva rama de Git:
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
that relates to your submission. You don't want to duplicate effort.
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
Discussing the design up front helps to ensure that we're ready to accept your work.
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
1. Fork the angular/angular repo.
1. Make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
```
6. Crea tu correción, **incluyendo casos de prueba apropiados**.
7. Sigue nuestras [Reglas de código](#rules).
8. Ejecuta todo el conjunto de pruebas de Angular, tal como está descrito en la [documentación del desarrollador][dev-doc], y asegúrate de que todas las pruebas pasen.
9. Crea un commit de tus cambios utilizando un mensaje de commit descriptivo que siga nuestra [convención para el mensaje de los commits](#commit).
Es necesario cumplir con estas convenciones porque las notas de las versiones se generan automáticamente a partir de estos mensajes.
1. Create your patch, **including appropriate test cases**.
1. Follow our [Coding Rules](#rules).
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
and ensure that all tests pass.
1. Commit your changes using a descriptive commit message that follows our
[commit message conventions](#commit). Adherence to these conventions
is necessary because release notes are automatically generated from these messages.
```shell
git commit -a
```
Nota: la opción de la línea de comandos de Git `-a` automaticamente hará "add" y "rm" a los archivos editados.
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
10. Haz push de tu rama a GitHub:
1. Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
11. En GitHub, crea un pull request a `angular:master`.
1. In GitHub, send a pull request to `angular:master`.
* If we suggest changes then:
* Make the required updates.
* Re-run the Angular test suites to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
Si solicitamos cambios a través de revisiones de código, sigue las siguientes indicaciones:
```shell
git rebase master -i
git push -f
```
* Haz los cambios requeridos.
* Ejecuta nuevamente el conjunto de pruebas de Angular para asegurar que todas las pruebas aún están pasando.
* Haz rebase de tu rama a la rama master y haz push con la opción `-f` a tu repositorio de Github (esto actualizará tu Pull Request):
That's it! Thank you for your contribution!
```shell
git rebase master -i
git push -f
```
#### After your pull request is merged
¡Es todo! ¡Muchas gracias por tu contribución!
After your pull request is merged, you can safely delete your branch and pull the changes
from the main (upstream) repository:
#### Después del merge de tu pull request
Después de que se hizo merge de tu pull request, puedes eliminar de forma segura tu rama y hacer pull de los cambios del repositorio principal (upstream):
* Elimina la rama remota en GitHub a través de la interfaz de usuario web de GitHub o en tu línea de comandos de la siguiente manera:
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
```shell
git push origin --delete my-fix-branch
```
* Muévete a la rama master:
* Check out the master branch:
```shell
git checkout master -f
```
* Elimina tu rama local:
* Delete the local branch:
```shell
git branch -D my-fix-branch
```
* Actualiza tu rama master con la última versión del fork (upstream):
* Update your master with the latest upstream version:
```shell
git pull --ff upstream master
```
## <a name="rules"></a> Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
## <a name="rules"></a> Reglas del código
Para garantizar la coherencia en todo el código fuente, ten en cuenta estas reglas mientras trabajas:
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
* All public API methods **must be documented**. (Details TBC).
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
**100 characters**. An automated formatter is available, see
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
* Todas las funcionalidades o solución de bugs **deben ser probadas** por una o más pruebas (pruebas unitarias).
* Todos los métodos públicos del API **deben ser documentados**.
* Seguimos la [guía de estilo JavaScript de Google][js-style-guide], pero cada línea no debe exceder **100 caracteres**.
## <a name="commit"></a> Commit Message Guidelines
Un formateador automatizado está disponible, revisar [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
## <a name="commit"></a> Formato para el mensaje de los commits
*Esta especificación está inspirada y reemplaza el [Formato de mensaje de commits de AngularJS][commit-message-format].*
Tenemos reglas muy precisas sobre cómo deben formatearse nuestros mensajes de los commits de Git.
Este formato permite tener **un historial de commits más facil de leer**.
Cada mensaje de un commit consta del **header**, el **body**, y el **footer**.
We have very precise rules over how our git commit messages can be formatted. This leads to **more
readable messages** that are easy to follow when looking through the **project history**. But also,
we use the git commit messages to **generate the Angular change log**.
### Commit Message Format
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
```
<header>
<LINEA VACIA>
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<LINEA VACIA>
<BLANK LINE>
<footer>
```
El `header` es obligatorio y debe ajustarse al formato del [mensaje del header del commit](#commit-header).
The **header** is mandatory and the **scope** of the header is optional.
El `body` es obligatorio para todos los commits excepto los que tenga scope "docs".
Cuando el body es requerido debe tener al menos 20 caracteres.
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.
El `footer` es opcional.
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
Cualquier línea del mensaje del commit no puede tener más de 100 caracteres.
#### <a href="commit-header"></a>Mensaje del header del commit
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
```
<tipo>(<alcance>): <resumen>
│ │ │
│ │ └─⫸ Resumen corto escrito en modo imperativo, tiempo presente. Sin mayúsculas. Sin punto final.
│ │
│ └─⫸ Alcance del commit: animations|bazel|benchpress|common|compiler|compiler-cli|core|
│ elements|forms|http|language-service|localize|platform-browser|
│ platform-browser-dynamic|platform-server|platform-webworker|
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
└─⫸ Tipo de commit: build|ci|docs|feat|fix|perf|refactor|style|test
docs(changelog): update changelog to beta.5
```
```
fix(release): need to depend on latest rxjs and zone.js
The version in our package.json gets copied to the one we publish, and users need the latest of these.
```
El `<tipo>` y `<resumen>` son obligatorios, el `(<alcance>)` es opcional.
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
### Type
Must be one of the following:
##### Tipo
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
* **docs**: Documentation only changes
* **feat**: A new feature
* **fix**: A bug fix
* **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
* **test**: Adding missing tests or correcting existing tests
El tipo debe ser uno de los siguientes:
### Scope
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages.
* **build**: cambios que afectan el sistema de compilación o dependencias externas (ejemplos de scopes: gulp, broccoli, npm)
* **ci**: cambios en nuestros archivos y scripts de configuración de CI (ejemplos de scopes: Circle, BrowserStack, SauceLabs)
* **docs**: cambios en la documentación
* **feat**: una nueva funcionalidad
* **fix**: una solución de un bug
* **perf**: un cambio de código que mejora el rendimiento.
* **refactor**: un cambio de código que no corrige ningún error ni agrega ninguna funcionalidad
* **style**: cambios que no afectan el significado del código (espacios en blanco, formato, falta de punto y coma, etc.)
* **test**: se agregan pruebas faltantes o se corrigen pruebas existentes
The following is the list of supported scopes:
* **animations**
* **common**
* **compiler**
* **compiler-cli**
* **core**
* **elements**
* **forms**
* **http**
* **language-service**
* **platform-browser**
* **platform-browser-dynamic**
* **platform-server**
* **platform-webworker**
* **platform-webworker-dynamic**
* **router**
* **service-worker**
* **upgrade**
##### Alcance
El alcance debe ser el nombre del paquete npm afectado (tal como lo percibe la persona que lee el registro de cambios generado a partir de los mensajes de commit).
There are currently a few exceptions to the "use package name" rule:
La siguiente es la lista de alcances permitidos:
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g.
public path changes, package.json changes done to all packages, d.ts file/format changes, changes
to bundles, etc.
* **changelog**: used for updating the release notes in CHANGELOG.md
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
repo
* **ivy**: used for changes to the [Ivy renderer](https://github.com/angular/angular/issues/21706).
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
specific package (e.g. `docs: fix typo in tutorial`).
* `animations`
* `bazel`
* `benchpress`
* `common`
* `compiler`
* `compiler-cli`
* `core`
* `elements`
* `forms`
* `http`
* `language-service`
* `localize`
* `platform-browser`
* `platform-browser-dynamic`
* `platform-server`
* `platform-webworker`
* `platform-webworker-dynamic`
* `router`
* `service-worker`
* `upgrade`
* `zone.js`
### Subject
The subject contains a succinct description of the change:
Actualmente hay algunas excepciones a la regla "usar el nombre de paquete":
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize the first letter
* no dot (.) at the end
* `packaging`: usado para cambios que cambian el diseño de los paquetes de npm en todos nuestros paquetes. Ejemplos: cambios de la ruta públic, package.json cambios hechos a todos los paquetes, cambios a archivos o formatos d.ts, cambios a bundles, etc.
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
* `changelog`: utilizado para actualizar las notas de la versión en CHANGELOG.md
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.
* `dev-infra`: utilizado para cambios relacionados con dev-infra dentro de los directorios /scripts, /tools y /dev-infra
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
* `docs-infra`: utilizado para cambios relacionados con la documentación (angular.io) dentro del directorio /aio del repositorio
A detailed explanation can be found in this [document][commit-message-format].
* `migrations`: utilizado para los cambios en las migraciones `ng update`.
## <a name="cla"></a> Signing the CLA
* `ngcc`: usado para los cambios del [Compilador de compatibilidad de Angular](./packages/compiler-cli/ngcc/README.md)
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
* `ve`: utilizado para cambios específicos de ViewEngine (legacy compiler/renderer).
* For individuals we have a [simple click-through form][individual-cla].
* For corporations we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
* alcance vacío: útil para cambios de `style`, `test` y `refactor` que se realizan en todos los paquetes (ejemplo: `style: add missing semicolons`) y para cambios de la documentación que no están relacionados a un paquete en específico(ejemplo: `docs: corrige error gramatical en el tutorial`).
<hr>
##### Resumen
Usa el campo resumen para proporcionar una descripción breve del cambio:
* usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios"
* no debe de contener ninguna letra mayúscula
* no debe de conter punto (.) al final
#### Mensaje del cuerpo del commit
Tal como en el resumen, usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios".
Explica la razón del cambio en el el mensaje del cuerpo del commit. Este mensaje de confirmación debe explicar _por qué_ está realizando el cambio.
Puedes incluir una comparación del comportamiento anterior con el nuevo comportamiento para ilustrar el impacto del cambio.
#### Mensaje del footer del commit
El footer puede contener información sobre cambios significativos y también es el lugar para hacer referencia a issues de GitHub, tickets de Jira y otros PRs que están relacionados con el commit.
```
CAMBIO SIGNIFICATIVO: <resumen del cambio significativo>
<LINEA VACIA>
<descripción del cambio significativo + instrucciones para la migración>
<LINEA VACIA>
<LINEA VACIA>
Fix #<issue número>
```
La sección de cambios significativos debería comenzar con la frase "CAMBIO SIGNIFICATIVO: " seguido de un resumen del cambio significativo, una línea en blanco y una descripción detallada del cambio significativo que también incluya instrucciones de migración.
### Revirtiendo commits
Si el commit revierte un commit previo, el commit debería comenzar con `revert: `, seguido por el header del commit revertido.
El contenido del mensaje del commit debería contener:
- Información sobre el SHA del commit que se revierte en el siguiente formato: `Esto revierte el commit <SHA>`,
- Una descripción clara de la razón para revertir el mensaje del _commit_.
## <a name="cla"></a> Firma del Acuerdo de Licencia de Colaborador (CLA)
Por favor firma nuestro Acuerdo de Licencia de Colaborador (CLA) cuando creas tu primer pull request. Para que cualquier cambio de código sea aceptado, el Acuerdo de Licencia de Colaborador (CLA) debe ser firmado. Es un proceso rápido con nuestro CLA assistant que está integrado con nuestro CI.
Los siguientes documentos pueden ayudarte a resolver problemas con cuentas de GitHub y múltiples direcciones de correo electrónico:
If you have more than one Git identity, you must make sure that you sign the CLA using the primary email address associated with the ID that has been granted access to the Angular repository. Git identities can be associated with more than one email address, and only one is primary. Here are some links to help you sort out multiple Git identities and email addresses:
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
* https://help.github.com/articles/about-commit-email-addresses/
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA, before you commit changes. If not, your PR will fail the CLA check.
<hr>
[angular-group]: https://groups.google.com/forum/#!forum/angular

View File

@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2010-2020 Google LLC. http://angular.io/license
Copyright (c) 2010-2019 Google LLC. http://angular.io/license
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,26 +0,0 @@
[![CircleCI](https://circleci.com/gh/angular/angular/tree/master.svg?style=shield)](https://circleci.com/gh/angular/workflows/angular/tree/master)
[![Join the chat at https://gitter.im/angular/angular](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![npm version](https://badge.fury.io/js/%40angular%2Fcore.svg)](https://www.npmjs.com/@angular/core)
# Angular
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
## Quickstart
[Get started in 5 minutes][quickstart].
## Changelog
[Learn about the latest improvements][changelog].
## Want to help?
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
[quickstart]: https://angular.io/start
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
[ng]: https://angular.io

View File

@ -1,25 +1,28 @@
# Angular en español
[![CircleCI](https://circleci.com/gh/angular/angular/tree/master.svg?style=shield)](https://circleci.com/gh/angular/workflows/angular/tree/master)
[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
[![Join the chat at https://gitter.im/angular/angular](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![npm version](https://badge.fury.io/js/%40angular%2Fcore.svg)](https://www.npmjs.com/@angular/core)
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa
TypeScript/JavaScript y otros lenguajes de programación.
## ¿Quieres ayudar?
# Angular
### Documentación en español
Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
¿Quieres mejorar la documentación? ¡Excelente! Lee nuestras pautas para
[colaborar](CONTRIBUTING.md) y luego revisa algunos de nuestras
[issues](https://github.com/angular-hispano/angular/issues).
## Quickstart
### El framework
[Get started in 5 minutes][quickstart].
La colaboración para corregir errores y agregar funciones en el framework debe realizarse en inglés a través
del repositorio [angular/angular](https://github.com/angular/angular) upstream.
## Changelog
## Guía rápida
[Learn about the latest improvements][changelog].
[Comienza a usarlo en 5 minutos](https://docs.angular.lat/start).
## Want to help?
## Registro de cambios (Changelog)
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
[Últimas mejoras realizadas](CHANGELOG.md).
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
[quickstart]: https://angular.io/start
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
[ng]: https://angular.io

View File

@ -5,37 +5,84 @@ workspace(
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Uncomment for local bazel rules development
#local_repository(
# name = "build_bazel_rules_nodejs",
# path = "../rules_nodejs",
#)
#local_repository(
# name = "npm_bazel_typescript",
# path = "../rules_typescript",
#)
# Fetch rules_nodejs so we can install our npm dependencies
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
sha256 = "e04a82a72146bfbca2d0575947daa60fda1878c8d3a3afe868a8ec39a6b968bb",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.31.1/rules_nodejs-0.31.1.tar.gz"],
)
# Check the rules_nodejs version and download npm dependencies
# Note: bazel (version 2 and after) will check the .bazelversion file so we don't need to
# assert on that.
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
# Check the bazel version and download npm dependencies
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "check_rules_nodejs_version", "node_repositories", "yarn_install")
check_rules_nodejs_version(minimum_version_string = "1.7.0")
# 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
check_bazel_version(
message = """
You no longer need to install Bazel on your machine.
Angular has a dependency on the @bazel/bazel package which supplies it.
Try running `yarn bazel` instead.
(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 = {
"12.14.1-darwin_amd64": ("node-v12.14.1-darwin-x64.tar.gz", "node-v12.14.1-darwin-x64", "0be10a28737527a1e5e3784d3ad844d742fe8b0718acd701fd48f718fd3af78f"),
"12.14.1-linux_amd64": ("node-v12.14.1-linux-x64.tar.xz", "node-v12.14.1-linux-x64", "07cfcaa0aa9d0fcb6e99725408d9e0b07be03b844701588e3ab5dbc395b98e1b"),
"12.14.1-windows_amd64": ("node-v12.14.1-win-x64.zip", "node-v12.14.1-win-x64", "1f96ccce3ba045ecea3f458e189500adb90b8bc1a34de5d82fc10a5bf66ce7e3"),
"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 = "12.14.1",
node_version = "10.16.0",
package_json = ["//:package.json"],
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
# ```
# 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",
)
load("//integration:angular_integration_test.bzl", "npm_package_archives")
yarn_install(
name = "npm",
manual_build_file_contents = npm_package_archives(),
data = [
"//: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",
)
@ -49,22 +96,19 @@ load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
rules_angular_dev_dependencies()
# Load protractor dependencies
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
npm_bazel_protractor_dependencies()
# Load karma dependencies
load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies")
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
npm_bazel_karma_dependencies()
rules_karma_dependencies()
# Setup the rules_webtesting toolchain
load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
web_test_repositories()
load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories")
# Temporary work-around for https://github.com/angular/angular/issues/28681
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
load("//:browser_repositories.bzl", "browser_repositories")
browser_repositories()
@ -91,18 +135,17 @@ rbe_autoconfig(
# Need to specify a base container digest in order to ensure that we can use the checked-in
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
# need to pull the image and run it in order determine the toolchain configuration. See:
# https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
# https://github.com/bazelbuild/bazel-toolchains/blob/0.27.0/configs/ubuntu16_04_clang/versions.bzl
base_container_digest = "sha256:94d7d8552902d228c32c8c148cc13f0effc2b4837757a6e95b73fdc5c5e4b07b",
# 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:f743114235a43355bf8324e2ba0fa6a597236fe06f7bc99aaa9ac703631c306b",
digest = "sha256:76e2e4a894f9ffbea0a0cb2fbde741b5d223d40f265dbb9bca78655430173990",
env = clang_env(),
registry = "marketplace.gcr.io",
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
# a specific Linux kernel that comes with "libx11" in order to run headless browser tests.
repository = "google/rbe-ubuntu16-04-webtest",
use_checked_in_confs = "Force",
)

View File

@ -1,131 +1,125 @@
# Proyecto de documentación Angular (https://docs.angular.lat)
# Angular documentation project (https://angular.io)
Todo en esta carpeta es parte del proyecto de documentación. Esto incluye:
Everything in this folder is part of the documentation project. This includes
* El sitio web para mostrar la documentación
* La configuración de dgeni para convertir los archivos de origen a archivos renderizados que se pueden vizualizar en el sitio web.
* Las herramientas para establecer ejemplos para el desarrollo; y generar archivos en tiempo real y archivos zip desde los ejemplos.
* the web site for displaying the documentation
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
## Tareas de desarrollador
## Developer tasks
Nosotros usamos [Yarn](https://yarnpkg.com) para gestionar las dependencias y crear tareas de compilación.
Debes ejecutar todas estas tareas desde la carpeta `angular/aio`.
Aquí están las tareas más importantes que podrías necesitar usar:
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
You should run all these tasks from the `angular/aio` folder.
Here are the most important tasks you might need to use:
* `yarn` - instalar todas las dependencias.
* `yarn setup` - instalar todas las dependencias, boilerplate, stackblitz, zips y ejecuta dgeni en los documentos.
* `yarn setup-local` - igual que `setup`, pero crea los paquetes de Angular a partir del código y usa estas versiones construidas localmente (en lugar de las recuperadas desde npm) para aio y ejemplos de documentos boilerplate.
* `yarn` - install all the dependencies.
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
* `yarn setup-local` - same as `setup`, but use the locally built Angular packages for aio and docs examples boilerplate.
* `yarn build` - crear una compilación de producción de la aplicación (después de instalar dependencias, boilerplate, etc).
* `yarn build-local` - igual que `build`, pero usa `setup-local` en lugar de `setup`.
* `yarn build-local-with-viewengine` - igual que `build-local`, pero además también enciende el modo `ViewEngine` (pre-Ivy) en aio.
(Nota: Encender el modo `ViewEngine` en ejemplos de documentos, ver `yarn boilerplate:add:viewengine` abajo.)
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
* `yarn start` - ejecutar un servidor web de desarrollo que observa los archivos; luego crea el doc-viewer y vuelve a cargar la página, según sea necesario.
* `yarn serve-and-sync` - ejecutar ambos, el `docs-watch` y `start` en la misma consola.
* `yarn lint` - comprobar que el código del doc-viewer sigue nuestras reglas de estilo.
* `yarn test` - observar todos los archivos de origen, para el doc-viewer, y ejecuta todas las pruebas unitarias cuando haya algún cambio.
* `yarn test --watch=false` -ejecutar todas las pruebas unitarias una sola vez.
* `yarn e2e` - ejecutar todas las pruebas de e2e para el doc-viewer.
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
* `yarn lint` - check that the doc-viewer code follows our style rules.
* `yarn test` - watch all the source files, for the doc-viewer, and run all the unit tests when any change.
* `yarn test --watch=false` - run all the unit tests once.
* `yarn e2e` - run all the e2e tests for the doc-viewer.
* `yarn docs` - generar toda la documentación desde los archivos fuente.
* `yarn docs-watch` - observar el código Angular, los archivos de documentación y ejecutar un 'doc-gen' en corto circuito para los documentos que fueron cambiados.
* `yarn docs-lint` - comprobar que el código del documento generado sigue nuestras reglas de estilo.
* `yarn docs-test` - ejecutar las pruebas unitarias para el código de generación de doc.
* `yarn docs` - generate all the docs from the source files.
* `yarn docs-watch` - watch the Angular source and the docs files and run a short-circuited doc-gen for the docs that changed.
* `yarn docs-lint` - check that the doc gen code follows our style rules.
* `yarn docs-test` - run the unit tests for the doc generation code.
* `yarn boilerplate:add` - generar todo el código boilerplate para los ejemplos, para que puedan ejecutarse localmente.
* `yarn boilerplate:add:viewengine` - igual que `boilerplate:add` pero también enciende el modo `ViewEngine` (pre-Ivy).
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. Add the option `--local` to use your local version of Angular contained in the "dist" folder.
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
* `yarn boilerplate:remove` - eliminar todo el código boilerplate que fue añadido a través`yarn boilerplate:add`.
* `yarn generate-stackblitz` - generar los archivos stackblitz que están usados por la etiqueta `live-example` en documentos.
* `yarn generate-zips` - generar los archivos zip desde los ejemplos. Zip está disponible a través de la etiqueta `live-example` en los documentos.
* `yarn example-e2e` - ejecutar todas las pruebas e2e para ejemplos. Opciones disponibles:
- `--setup`: generar boilerplate, forzar la actualización del controlador web y otras configuraciones, luego ejecutar las pruebas.
- `--local`: ejecutar pruebas e2e con la versión local de Angular contenida en la carpeta "dist".
_Requiere `--setup` para que surta efecto._
- `--viewengine`: ejecutar pruebas e2e en modo `ViewEngine` (pre-Ivy).
- `--filter=foo`: limitar pruebas e2e a las que contienen la palabra "foo".
> **Nota para usuarios Windows**
>
> Configurar los ejemplos implica crear algunos [enlaces simbólicos](https://es.wikipedia.org/wiki/Enlace_simb%C3%B3lico) (ver [Aquí](./tools/examples/README.md#symlinked-node_modules) para más detalles). En Windows, esto requiere tener [Habilitado el Modo de desarrollador ](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (compatible con Windows 10 o más reciente) o ejecutar los comandos de configuración cómo administrador.
>
> Los comandos afectados son:
> - `yarn setup` / `yarn setup-*`
> - `yarn build` / `yarn build-*`
> - `yarn boilerplate:add`
> - `yarn example-e2e --setup`
## Usando ServiceWorker localmente
Ejecutando `yarn start` (incluso cuando se apunta explícitamente al modo de producción) no configura el
ServiceWorker. Si quieres probar el ServiceWorker localmente, puedes usar `yarn build` y luego
ejecutar los archivos en `dist/` con `yarn http-server dist -p 4200`.
* `yarn example-e2e` - run all e2e tests for examples
- `yarn example-e2e --setup` - force webdriver update & other setup, then run tests
- `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
## Guía de autoría
Existen dos tipos de contenido en la documentación:
## Using ServiceWorker locally
* **Documentación de API**: descripciones de los módulos, clases, interfaces, decoradores, etc que son parte de la plataforma Angular.
La documentacion de API está generada directamente desde el código fuente.
El código fuente está contenido en archivos TypeScript , almacenados en la carpeta `angular/packages`.
Cada elemento de la API puede tener un comentario anterior, el cual contiene etiquetas y contenido de estilos JSDoc.
El contenido está escrito en markdown.
Running `yarn start` (even when explicitly targeting production mode) does not set up the
ServiceWorker. If you want to test the ServiceWorker locally, you can use `yarn build` and then
serve the files in `dist/` with `yarn http-server dist -p 4200`.
* **Otro contenido**: guias, tutoriales, y otro material de marketing.
Todos los demás contenidos se escriben utilizando markdown en archivos de texto, ubicados en la carpeta `angular/aio/content`.
Más específicamente, hay subcarpetas que contienen tipos particulares de contenido: guías, tutoriales y marketing.
* **Ejempos de código**: los ejemplos de código deben ser comprobables para garantizar su precisión.
Además, nuestros ejemplos tienen un aspecto específico y permiten al usuario copiar el código fuente. Para mayor
ejemplos se representan en una interfaz con pestañas (e.g. template, HTML, y TypeScript en pestañas separadas). Adicionalmente, algunos son ejemplos en acción, que proporcionan enlaces donde se puede editar el código, ejecutar, y/o descargar. Para obtener más detalles sobre cómo trabajar con ejemplos de código, lea los [fragmentos de código](https://docs.angular.lat/guide/docs-style-guide#code-snippets), [código fuente de marcado ](https://docs.angular.lat/guide/docs-style-guide#source-code-markup), y [ ejemplos en acción ](https://docs.angular.lat/guide/docs-style-guide#live-examples) paginas de los [ autores de guías de estilo ](https://docs.angular.lat/guide/docs-style-guide).
## Guide to authoring
Usamos la herramienta [dgeni](https://github.com/angular/dgeni) para convertir estos archivos en docs que se pueden ver en el doc-viewer.
Las [guías de estilo para Autores](https://docs.angular.lat/guide/docs-style-guide) prescriben pautas para
escribir páginas de guía, explica cómo usar la documentación de clases y componentes, y cómo marcar el código fuente para producir fragmentos de código.
There are two types of content in the documentation:
### Generando documentos completos
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
API docs are generated directly from the source code.
The source code is contained in TypeScript files, located in the `angular/packages` folder.
Each API item may have a preceding comment, which contains JSDoc style tags and content.
The content is written in markdown.
La principal tarea para generar los documentos es `yarn docs`. Esto procesará todos los archivos fuente (API y otros), extrayendo la documentación y generando archivos JSON que pueden ser consumidos por el doc-viewer.
* **Other content**: guides, tutorials, and other marketing material.
All other content is written using markdown in text files, located in the `angular/aio/content` folder.
More specifically, there are sub-folders that contain particular types of content: guides, tutorial and marketing.
### Generación parcial de doc para editores
* **Code examples**: code examples need to be testable to ensure their accuracy.
Also, our examples have a specific look and feel and allow the user to copy the source code. For larger
examples they are rendered in a tabbed interface (e.g. template, HTML, and TypeScript on separate
tabs). Additionally, some are live examples, which provide links where the code can be edited, executed, and/or downloaded. For details on working with code examples, please read the [Code snippets](https://angular.io/guide/docs-style-guide#code-snippets), [Source code markup](https://angular.io/guide/docs-style-guide#source-code-markup), and [Live examples](https://angular.io/guide/docs-style-guide#live-examples) pages of the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
La generación completa de documentos puede llevar hasta un minuto. Eso es demasiado lento para la creación y edición eficiente de documentos.
We use the [dgeni](https://github.com/angular/dgeni) tool to convert these files into docs that can be viewed in the doc-viewer.
Puedes ealizar pequeños cambios en un editor inteligente que muestre un markdown con formato:
>En VS Code, _Cmd-K, V_ abre la vista previa de markdown en el panel lateral; _Cmd-B_ alterna la barra izquierda
The [Authors Style Guide](https://angular.io/guide/docs-style-guide) prescribes guidelines for
writing guide pages, explains how to use the documentation classes and components, and how to markup sample source code to produce code snippets.
Puedes también mirar los cambios que se muestran correctamente en el doc-viewer
con un tiempo de ciclo rápido de edición / visualización.
### Generating the complete docs
Para este propósito, usa la tarea `yarn docs-watch`, que observa los cambios en los archivos de origen y solo vuelve a procesar los archivos necesarios para generar los documentos relacionados con el archivo que ha cambiado.
Dado que esta tarea tiene accesos directos, es mucho más rápido (a menudo menos de 1 segundo) pero no producirá contenido de fidelidad completa. Por ejemplo, los enlaces a otros documentoss y ejemplos de código pueden no mostrarse correctamente. Esto se nota especialmente en los enlaces a otros documentos y en los ejemplos incrustados, que no siempre se representan correctamente.
The main task for generating the docs is `yarn docs`. This will process all the source files (API and other),
extracting the documentation and generating JSON files that can be consumed by the doc-viewer.
La configuración general es la siguiente:
### Partial doc generation for editors
* Abrir una terminal, estar seguro que las dependencias están instaladas; ejecutar una generación inicial del doc; luego iniciar el doc-viewer:
Full doc generation can take up to one minute. That's too slow for efficient document creation and editing.
You can make small changes in a smart editor that displays formatted markdown:
>In VS Code, _Cmd-K, V_ opens markdown preview in side pane; _Cmd-B_ toggles left sidebar
You also want to see those changes displayed properly in the doc viewer
with a quick, edit/view cycle time.
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
re-processes the the files necessary to generate the docs that are related to the file that has changed.
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
fidelity content. For example, links to other docs and code examples may not render correctly. This is
most particularly noticed in links to other docs and in the embedded examples, which may not always render
correctly.
The general setup is as follows:
* Open a terminal, ensure the dependencies are installed; run an initial doc generation; then start the doc-viewer:
```bash
yarn setup
yarn start
```
* Abrir una segunda terminal e iniciar el observador de documentos.
* Open a second terminal and start watching the docs
```bash
yarn docs-watch
```
>Alternativamente, prueba el comando fusionado `serve-and-sync` que crea, observa y ejecuta en la misma ventana de la terminal
>Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window
```bash
yarn serve-and-sync
```
* Abre un navegador con la siguiente dirección https://localhost:4200/ y navega hasta el documento en el que quieras trabajar.
Puedes automáticamente abrir el navegador utilizando `yarn start -o` en la primera terminal.
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
You can automatically open the browser by using `yarn start -o` in the first terminal.
* Realiza cambios en la página de documentación asociada o en los archivos de ejemplo. Cada vez que un archivo es guardado, la documentación se regenerará, la aplicación se reconstruirá y la página se volverá a cargar.
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
be regenerated, the app will rebuild and the page will reload.
*Si recibes un error de compilación acerca de los ejemplos o cualquier otro error, asegúrate de consultar las
[guías de estilo para Autores](https://angular.io/guide/docs-style-guide) para más información.
* If you get a build error complaining about examples or any other odd behavior, be sure to consult
the [Authors Style Guide](https://angular.io/guide/docs-style-guide).

View File

@ -1,5 +1,5 @@
# Image metadata and config
FROM debian:buster
FROM debian:stretch
LABEL name="angular.io PR preview" \
description="This image implements the PR preview functionality for angular.io." \
@ -37,9 +37,9 @@ ARG TEST_AIO_NGINX_PORT_HTTPS=4433
ARG AIO_SIGNIFICANT_FILES_PATTERN='^(?:aio|packages)/(?!.*[._]spec\\.[jt]s$)'
ARG TEST_AIO_SIGNIFICANT_FILES_PATTERN=$AIO_SIGNIFICANT_FILES_PATTERN
ARG AIO_TRUSTED_PR_LABEL="aio: preview"
ARG TEST_AIO_TRUSTED_PR_LABEL=$AIO_TRUSTED_PR_LABEL
ARG TEST_AIO_TRUSTED_PR_LABEL="aio: preview"
ARG AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=$AIO_PREVIEW_SERVER_HOSTNAME
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
ARG AIO_ARTIFACT_MAX_SIZE=26214400
ARG TEST_AIO_ARTIFACT_MAX_SIZE=200
ARG AIO_PREVIEW_SERVER_PORT=3000
@ -72,29 +72,24 @@ RUN mkdir /var/log/aio
# Add extra package sources
RUN apt-get update -y && apt-get install -y curl=7.64.0-4+deb10u1
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_12.x | bash -
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 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 http://ftp.debian.org/debian stretch-backports main" | tee /etc/apt/sources.list.d/backports.list
# Install packages
# NOTE: Some packages (such as `nginx`, `nodejs`, `openssl`) make older versions unavailable on the
# repositories, so we cannot pin to specific versions for these packages :(
# See for example:
# - https://github.com/nodesource/distributions/issues/33
# - https://askubuntu.com/questions/715104/how-can-i-downgrade-openssl-via-apt-get
RUN apt-get update -y && apt-get install -y \
cron=3.0pl1-134+deb10u1 \
dnsmasq=2.80-1 \
nano=3.2-3 \
nginx \
nodejs \
openssl \
rsyslog=8.1901.0-1 \
vim=2:8.1.0875-5 \
yarn=1.22.4-1
RUN yarn global add pm2@4.4.0
cron=3.0pl1-128+deb9u1 \
dnsmasq=2.76-5+deb9u2 \
nano=2.7.4-1 \
nginx=1.10.3-1+deb9u2 \
nodejs=10.15.3-1nodesource1 \
openssl=1.1.0j-1~deb9u1 \
rsyslog=8.24.0-1 \
yarn=1.15.2-1
RUN yarn global add pm2@3.5.0
# Set up log rotation
@ -167,7 +162,8 @@ RUN find $AIO_SCRIPTS_SH_DIR -maxdepth 1 -type f -printf "%P\n" \
# Set up the Node.js scripts
COPY scripts-js/ $AIO_SCRIPTS_JS_DIR/
RUN yarn --cwd="$AIO_SCRIPTS_JS_DIR/" install --production --frozen-lockfile
WORKDIR $AIO_SCRIPTS_JS_DIR/
RUN yarn install --production --frozen-lockfile
# Set up health check

View File

@ -35,7 +35,6 @@ export class BuildCleaner {
]);
} catch (error) {
this.logger.error('ERROR:', error);
throw error;
}
}

View File

@ -1,4 +1,5 @@
import * as express from 'express';
import {promisify} from 'util';
import {PreviewServerError} from './preview-error';
/**
@ -12,7 +13,7 @@ export async function respondWithError(res: express.Response, err: any): Promise
}
res.status(err.status);
return new Promise(resolve => res.end(err.message, resolve));
await promisify(res.end.bind(res))(err.message);
}
/**

View File

@ -93,7 +93,7 @@ class Helper {
return fs.readFileSync(absFilePath, 'utf8');
}
public runCmd(cmd: string, opts: cp.ExecOptions = {}): Promise<CmdResult> {
public runCmd(cmd: string, opts: cp.ExecFileOptions = {}): Promise<CmdResult> {
return new Promise(resolve => {
const proc = cp.exec(cmd, opts, (err, stdout, stderr) => resolve({success: !err, err, stdout, stderr}));
this.createCleanUpFn(() => proc.kill());
@ -101,7 +101,7 @@ class Helper {
}
public runForAllSupportedSchemes(suiteFactory: TestSuiteFactory): void {
Object.entries(this.portPerScheme).forEach(([scheme, port]) => suiteFactory(scheme, port));
Object.keys(this.portPerScheme).forEach(scheme => suiteFactory(scheme, this.portPerScheme[scheme]));
}
public verifyResponse(status: number, regex: string | RegExp = /^/): VerifyCmdResultFn {

View File

@ -15,7 +15,7 @@ describe(`nginx`, () => {
afterEach(() => h.cleanUp());
it('should redirect HTTP to HTTPS', async () => {
it('should redirect HTTP to HTTPS', done => {
const httpHost = `${AIO_NGINX_HOSTNAME}:${AIO_NGINX_PORT_HTTP}`;
const httpsHost = `${AIO_NGINX_HOSTNAME}:${AIO_NGINX_PORT_HTTPS}`;
const urlMap = {
@ -24,15 +24,16 @@ describe(`nginx`, () => {
[`http://foo.${httpHost}/`]: `https://foo.${httpsHost}/`,
};
const verifyRedirection = async (fromUrl: string, toUrl: string) => {
const result = await h.runCmd(`curl -i ${fromUrl}`);
const verifyRedirection = (httpUrl: string) => h.runCmd(`curl -i ${httpUrl}`).then(result => {
h.verifyResponse(307)(result);
const headers = result.stdout.split(/(?:\r?\n){2,}/)[0];
expect(headers).toContain(`Location: ${toUrl}`);
};
expect(headers).toContain(`Location: ${urlMap[httpUrl]}`);
});
await Promise.all(Object.entries(urlMap).map(urls => verifyRedirection(...urls)));
Promise.
all(Object.keys(urlMap).map(verifyRedirection)).
then(done);
});
@ -61,15 +62,15 @@ describe(`nginx`, () => {
});
it('should return /index.html', async () => {
it('should return /index.html', done => {
const origin = `${scheme}://pr${pr}-${shortSha9}.${host}`;
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
await Promise.all([
Promise.all([
h.runCmd(`curl -iL ${origin}/index.html`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}/`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}`).then(h.verifyResponse(200, bodyRegex)),
]);
]).then(done);
});
@ -89,11 +90,12 @@ describe(`nginx`, () => {
});
it('should return /foo/bar.js', async () => {
it('should return /foo/bar.js', done => {
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /foo/bar\\.js$`);
await h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/bar.js`).
then(h.verifyResponse(200, bodyRegex));
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/bar.js`).
then(h.verifyResponse(200, bodyRegex)).
then(done);
});
@ -109,46 +111,47 @@ describe(`nginx`, () => {
});
it('should respond with 403 for directories', async () => {
await Promise.all([
it('should respond with 403 for directories', done => {
Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/`).then(h.verifyResponse(403)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo`).then(h.verifyResponse(403)),
]);
]).then(done);
});
it('should respond with 404 for unknown paths to files', async () => {
await h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/baz.css`).
then(h.verifyResponse(404));
it('should respond with 404 for unknown paths to files', done => {
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/baz.css`).
then(h.verifyResponse(404)).
then(done);
});
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', async () => {
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', done => {
const origin = `${scheme}://pr${pr}-${shortSha9}.${host}`;
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
await Promise.all([
Promise.all([
h.runCmd(`curl -iL ${origin}/foo/baz`).then(h.verifyResponse(200, bodyRegex)),
h.runCmd(`curl -iL ${origin}/foo/baz/`).then(h.verifyResponse(200, bodyRegex)),
]);
]).then(done);
});
it('should respond with 404 for unknown PRs/SHAs', async () => {
it('should respond with 404 for unknown PRs/SHAs', done => {
const otherPr = 54321;
const otherShortSha = computeShortSha('8'.repeat(40));
await Promise.all([
Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}9-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${otherPr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}9.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${otherShortSha}.${host}`).then(h.verifyResponse(404)),
]);
]).then(done);
});
it('should respond with 404 if the subdomain format is wrong', async () => {
await Promise.all([
it('should respond with 404 if the subdomain format is wrong', done => {
Promise.all([
h.runCmd(`curl -iL ${scheme}://xpr${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://prx${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://xx${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
@ -157,25 +160,26 @@ describe(`nginx`, () => {
h.runCmd(`curl -iL ${scheme}://${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}_${shortSha9}.${host}`).then(h.verifyResponse(404)),
]);
]).then(done);
});
it('should reject PRs with leading zeros', async () => {
await h.runCmd(`curl -iL ${scheme}://pr0${pr}-${shortSha9}.${host}`).
then(h.verifyResponse(404));
it('should reject PRs with leading zeros', done => {
h.runCmd(`curl -iL ${scheme}://pr0${pr}-${shortSha9}.${host}`).
then(h.verifyResponse(404)).
then(done);
});
it('should accept SHAs with leading zeros (but not trim the zeros)', async () => {
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
const bodyRegex9 = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
const bodyRegex0 = new RegExp(`^PR: ${pr} | SHA: ${sha0} | File: /index\\.html$`);
await Promise.all([
Promise.all([
h.runCmd(`curl -iL ${scheme}://pr${pr}-0${shortSha9}.${host}`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}`).then(h.verifyResponse(200, bodyRegex9)),
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha0}.${host}`).then(h.verifyResponse(200, bodyRegex0)),
]);
]).then(done);
});
});
@ -227,23 +231,23 @@ describe(`nginx`, () => {
describe(`${host}/health-check`, () => {
it('should respond with 200', async () => {
await Promise.all([
it('should respond with 200', done => {
Promise.all([
h.runCmd(`curl -iL ${scheme}://${host}/health-check`).then(h.verifyResponse(200)),
h.runCmd(`curl -iL ${scheme}://${host}/health-check/`).then(h.verifyResponse(200)),
]);
]).then(done);
});
it('should respond with 404 if the path does not match exactly', async () => {
await Promise.all([
it('should respond with 404 if the path does not match exactly', done => {
Promise.all([
h.runCmd(`curl -iL ${scheme}://${host}/health-check/foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/health-check-foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/health-checknfoo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/foo/health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/foo-health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${scheme}://${host}/foonhealth-check`).then(h.verifyResponse(404)),
]);
]).then(done);
});
});
@ -287,28 +291,29 @@ describe(`nginx`, () => {
describe(`${host}/circle-build`, () => {
it('should disallow non-POST requests', async () => {
it('should disallow non-POST requests', done => {
const url = `${scheme}://${host}/circle-build`;
await Promise.all([
Promise.all([
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
]);
]).then(done);
});
it('should pass requests through to the preview server', async () => {
await h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/));
it('should pass requests through to the preview server', done => {
h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/)).
then(done);
});
it('should respond with 404 for unknown paths', async () => {
it('should respond with 404 for unknown paths', done => {
const cmdPrefix = `curl -iLX POST ${scheme}://${host}`;
await Promise.all([
Promise.all([
h.runCmd(`${cmdPrefix}/foo/circle-build/`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foo-circle-build/`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/fooncircle-build/`).then(h.verifyResponse(404)),
@ -317,7 +322,7 @@ describe(`nginx`, () => {
h.runCmd(`${cmdPrefix}/circle-buildnfoo/`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/circle-build/pr`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/circle-build/42`).then(h.verifyResponse(404)),
]);
]).then(done);
});
});
@ -327,33 +332,38 @@ describe(`nginx`, () => {
const url = `${scheme}://${host}/pr-updated`;
it('should disallow non-POST requests', async () => {
await Promise.all([
it('should disallow non-POST requests', done => {
Promise.all([
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
]);
]).then(done);
});
it('should pass requests through to the preview server', async () => {
await h.runCmd(`curl -iLX POST --header "Content-Type: application/json" ${url}`).
then(h.verifyResponse(400, /Missing or empty 'number' field/));
it('should pass requests through to the preview server', done => {
const cmdPrefix = `curl -iLX POST --header "Content-Type: application/json"`;
const cmd1 = `${cmdPrefix} ${url}`;
Promise.all([
h.runCmd(cmd1).then(h.verifyResponse(400, /Missing or empty 'number' field/)),
]).then(done);
});
it('should respond with 404 for unknown paths', async () => {
it('should respond with 404 for unknown paths', done => {
const cmdPrefix = `curl -iLX POST ${scheme}://${host}`;
await Promise.all([
Promise.all([
h.runCmd(`${cmdPrefix}/foo/pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foo-pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foonpr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated/foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated-foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updatednfoo`).then(h.verifyResponse(404)),
]);
]).then(done);
});
});
@ -364,7 +374,7 @@ describe(`nginx`, () => {
beforeEach(() => {
['index.html', 'foo.js', 'foo/index.html'].forEach(relFilePath => {
const absFilePath = path.join(AIO_BUILDS_DIR, relFilePath);
h.writeFile(absFilePath, {content: `File: /${relFilePath}`});
return h.writeFile(absFilePath, {content: `File: /${relFilePath}`});
});
});

View File

@ -105,8 +105,8 @@ describe('preview-server', () => {
describe(`${host}/circle-build`, () => {
const curl = makeCurl(`${host}/circle-build`);
const curl = makeCurl(`${host}/circle-build`);
it('should disallow non-POST requests', async () => {
const bodyRegex = /^Unknown resource/;
@ -189,7 +189,8 @@ describe('preview-server', () => {
});
it('should respond with 201 if a new public build is created', async () => {
await curl(payload(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).then(h.verifyResponse(201));
await curl(payload(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER))
.then(h.verifyResponse(201));
expect({ prNum: PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER }).toExistAsABuild();
});
@ -198,7 +199,7 @@ describe('preview-server', () => {
expect({ prNum: PrNums.TRUST_CHECK_UNTRUSTED, isPublic: false }).toExistAsABuild();
});
[true, false].forEach(isPublic => {
[true].forEach(isPublic => {
const build = isPublic ? BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER : BuildNums.TRUST_CHECK_UNTRUSTED;
const prNum = isPublic ? PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER : PrNums.TRUST_CHECK_UNTRUSTED;
const label = isPublic ? 'public' : 'non-public';
@ -363,23 +364,23 @@ describe('preview-server', () => {
describe(`${host}/health-check`, () => {
it('should respond with 200', async () => {
await Promise.all([
it('should respond with 200', done => {
Promise.all([
h.runCmd(`curl -iL ${host}/health-check`).then(h.verifyResponse(200)),
h.runCmd(`curl -iL ${host}/health-check/`).then(h.verifyResponse(200)),
]);
]).then(done);
});
it('should respond with 404 if the path does not match exactly', async () => {
await Promise.all([
it('should respond with 404 if the path does not match exactly', done => {
Promise.all([
h.runCmd(`curl -iL ${host}/health-check/foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/health-check-foo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/health-checknfoo`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/foo/health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/foo-health-check`).then(h.verifyResponse(404)),
h.runCmd(`curl -iL ${host}/foonhealth-check`).then(h.verifyResponse(404)),
]);
]).then(done);
});
});
@ -425,18 +426,18 @@ describe('preview-server', () => {
});
it('should respond with 404 for unknown paths', async () => {
it('should respond with 404 for unknown paths', done => {
const mockPayload = JSON.stringify({number: 1}); // MockExternalApiFlags.TRUST_CHECK_ACTIVE_TRUSTED_USER });
const cmdPrefix = `curl -iLX POST --data "${mockPayload}" ${host}`;
await Promise.all([
Promise.all([
h.runCmd(`${cmdPrefix}/foo/pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foo-pr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/foonpr-updated`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated/foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updated-foo`).then(h.verifyResponse(404)),
h.runCmd(`${cmdPrefix}/pr-updatednfoo`).then(h.verifyResponse(404)),
]);
]).then(done);
});
@ -550,10 +551,10 @@ describe('preview-server', () => {
describe(`${host}/*`, () => {
it('should respond with 404 for requests to unknown URLs', async () => {
it('should respond with 404 for requests to unknown URLs', done => {
const bodyRegex = /^Unknown resource/;
await Promise.all([
Promise.all([
h.runCmd(`curl -iL ${host}/index.html`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iL ${host}/`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iL ${host}`).then(h.verifyResponse(404, bodyRegex)),
@ -561,7 +562,7 @@ describe('preview-server', () => {
h.runCmd(`curl -iLX POST ${host}`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iLX PATCH ${host}`).then(h.verifyResponse(404, bodyRegex)),
h.runCmd(`curl -iLX DELETE ${host}`).then(h.verifyResponse(404, bodyRegex)),
]);
]).then(done);
});
});

View File

@ -14,41 +14,42 @@
"predev": "yarn build || true",
"dev": "run-p ~~build-watch ~~test-watch",
"lint": "tslint --project tsconfig.json",
"pretest": "run-s build lint",
"pretest": "yarn build",
"test": "yarn ~~test-only",
"pretest-watch": "yarn pretest",
"test-watch": "yarn ~~test-watch",
"~~build": "tsc",
"~~build-watch": "yarn ~~build --watch",
"pre~~test-only": "yarn lint",
"~~test-only": "node dist/test",
"~~test-watch": "nodemon --delay 1 --exec \"yarn ~~test-only\" --watch dist"
},
"dependencies": {
"body-parser": "^1.19.0",
"delete-empty": "^3.0.0",
"express": "^4.17.1",
"jasmine": "^3.5.0",
"nock": "^12.0.3",
"node-fetch": "^2.6.0",
"shelljs": "^0.8.4",
"source-map-support": "^0.5.19",
"tar-stream": "^2.1.2",
"tslib": "^1.11.1"
"body-parser": "^1.18.3",
"delete-empty": "^2.0.0",
"express": "^4.16.3",
"jasmine": "^3.2.0",
"nock": "^9.6.1",
"node-fetch": "^2.2.0",
"shelljs": "^0.8.2",
"source-map-support": "^0.5.9",
"tar-stream": "^1.6.1",
"tslib": "^1.9.3"
},
"devDependencies": {
"@types/body-parser": "^1.19.0",
"@types/express": "^4.17.6",
"@types/jasmine": "^3.5.10",
"@types/nock": "^11.1.0",
"@types/node": "^13.13.2",
"@types/node-fetch": "^2.5.7",
"@types/shelljs": "^0.8.7",
"@types/supertest": "^2.0.8",
"nodemon": "^2.0.3",
"@types/body-parser": "^1.17.0",
"@types/express": "^4.16.0",
"@types/jasmine": "^2.8.8",
"@types/nock": "^9.3.0",
"@types/node": "^10.9.2",
"@types/node-fetch": "^2.1.2",
"@types/shelljs": "^0.8.0",
"@types/supertest": "^2.0.5",
"nodemon": "^1.18.3",
"npm-run-all": "^4.1.5",
"supertest": "^4.0.2",
"tslint": "^6.1.1",
"supertest": "^3.1.0",
"tslint": "^5.11.0",
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
"typescript": "^3.8.3"
"typescript": "^3.0.1"
}
}

View File

@ -15,6 +15,7 @@ const EXISTING_DOWNLOADS = [
'20-1234567-build.zip',
];
const OPEN_PRS = [10, 40];
const ANY_DATE = jasmine.any(String);
// Tests
describe('BuildCleaner', () => {
@ -76,18 +77,22 @@ describe('BuildCleaner', () => {
let cleanerRemoveUnnecessaryDownloadsSpy: jasmine.Spy;
beforeEach(() => {
cleanerGetExistingBuildNumbersSpy = spyOn(cleaner, 'getExistingBuildNumbers').and.resolveTo(EXISTING_BUILDS);
cleanerGetOpenPrNumbersSpy = spyOn(cleaner, 'getOpenPrNumbers').and.resolveTo(OPEN_PRS);
cleanerGetExistingDownloadsSpy = spyOn(cleaner, 'getExistingDownloads').and.resolveTo(EXISTING_DOWNLOADS);
cleanerGetExistingBuildNumbersSpy = spyOn(cleaner, 'getExistingBuildNumbers')
.and.callFake(() => Promise.resolve(EXISTING_BUILDS));
cleanerGetOpenPrNumbersSpy = spyOn(cleaner, 'getOpenPrNumbers')
.and.callFake(() => Promise.resolve(OPEN_PRS));
cleanerGetExistingDownloadsSpy = spyOn(cleaner, 'getExistingDownloads')
.and.callFake(() => Promise.resolve(EXISTING_DOWNLOADS));
cleanerRemoveUnnecessaryBuildsSpy = spyOn(cleaner, 'removeUnnecessaryBuilds');
cleanerRemoveUnnecessaryDownloadsSpy = spyOn(cleaner, 'removeUnnecessaryDownloads');
});
it('should return a promise', async () => {
const promise = cleaner.cleanUp();
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
// Do not complete the test and release the spies synchronously, to avoid running the actual implementations.
await promise;
@ -125,32 +130,52 @@ describe('BuildCleaner', () => {
it('should reject if \'getOpenPrNumbers()\' rejects', async () => {
cleanerGetOpenPrNumbersSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
try {
cleanerGetOpenPrNumbersSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
});
it('should reject if \'getExistingBuildNumbers()\' rejects', async () => {
cleanerGetExistingBuildNumbersSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
try {
cleanerGetExistingBuildNumbersSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
});
it('should reject if \'getExistingDownloads()\' rejects', async () => {
cleanerGetExistingDownloadsSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
try {
cleanerGetExistingDownloadsSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
});
it('should reject if \'removeUnnecessaryBuilds()\' rejects', async () => {
cleanerRemoveUnnecessaryBuildsSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
try {
cleanerRemoveUnnecessaryBuildsSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
});
it('should reject if \'removeUnnecessaryDownloads()\' rejects', async () => {
cleanerRemoveUnnecessaryDownloadsSpy.and.rejectWith('Test');
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
try {
cleanerRemoveUnnecessaryDownloadsSpy.and.callFake(() => Promise.reject('Test'));
await cleaner.cleanUp();
} catch (err) {
expect(err).toBe('Test');
}
});
});
@ -162,15 +187,13 @@ describe('BuildCleaner', () => {
let promise: Promise<number[]>;
beforeEach(() => {
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake(
((_: string, cb: typeof readdirCb) => readdirCb = cb) as unknown as typeof fs.readdir,
);
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake((_: string, cb: typeof readdirCb) => readdirCb = cb);
promise = cleaner.getExistingBuildNumbers();
});
it('should return a promise', () => {
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
});
@ -180,27 +203,43 @@ describe('BuildCleaner', () => {
});
it('should reject if an error occurs while getting the files', async () => {
it('should reject if an error occurs while getting the files', done => {
promise.catch(err => {
expect(err).toBe('Test');
done();
});
readdirCb('Test');
await expectAsync(promise).toBeRejectedWith('Test');
});
it('should resolve with the returned files (as numbers)', async () => {
it('should resolve with the returned files (as numbers)', done => {
promise.then(result => {
expect(result).toEqual([12, 34, 56]);
done();
});
readdirCb(null, ['12', '34', '56']);
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
});
it('should remove `HIDDEN_DIR_PREFIX` from the filenames', async () => {
it('should remove `HIDDEN_DIR_PREFIX` from the filenames', done => {
promise.then(result => {
expect(result).toEqual([12, 34, 56]);
done();
});
readdirCb(null, [`${HIDDEN_DIR_PREFIX}12`, '34', `${HIDDEN_DIR_PREFIX}56`]);
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
});
it('should ignore files with non-numeric (or zero) names', async () => {
it('should ignore files with non-numeric (or zero) names', done => {
promise.then(result => {
expect(result).toEqual([12, 34, 56]);
done();
});
readdirCb(null, ['12', 'foo', '34', 'bar', '56', '000']);
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
});
});
@ -220,7 +259,7 @@ describe('BuildCleaner', () => {
it('should return a promise', () => {
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
});
@ -229,15 +268,31 @@ describe('BuildCleaner', () => {
});
it('should reject if an error occurs while fetching PRs', async () => {
it('should reject if an error occurs while fetching PRs', done => {
promise.catch(err => {
expect(err).toBe('Test');
done();
});
prDeferred.reject('Test');
await expectAsync(promise).toBeRejectedWith('Test');
});
it('should resolve with the numbers of the fetched PRs', async () => {
it('should resolve with the numbers of the fetched PRs', done => {
promise.then(prNumbers => {
expect(prNumbers).toEqual([1, 2, 3]);
done();
});
prDeferred.resolve([{id: 0, number: 1}, {id: 1, number: 2}, {id: 2, number: 3}]);
await expectAsync(promise).toBeResolvedTo([1, 2, 3]);
});
it('should log the number of open PRs', () => {
promise.then(prNumbers => {
expect(loggerLogSpy).toHaveBeenCalledWith(
ANY_DATE, 'BuildCleaner: ', `Open pull requests: ${prNumbers}`);
});
});
});
@ -249,15 +304,13 @@ describe('BuildCleaner', () => {
let promise: Promise<string[]>;
beforeEach(() => {
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake(
((_: string, cb: typeof readdirCb) => readdirCb = cb) as unknown as typeof fs.readdir,
);
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake((_: string, cb: typeof readdirCb) => readdirCb = cb);
promise = cleaner.getExistingDownloads();
});
it('should return a promise', () => {
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
});
@ -267,21 +320,33 @@ describe('BuildCleaner', () => {
});
it('should reject if an error occurs while getting the files', async () => {
it('should reject if an error occurs while getting the files', done => {
promise.catch(err => {
expect(err).toBe('Test');
done();
});
readdirCb('Test');
await expectAsync(promise).toBeRejectedWith('Test');
});
it('should resolve with the returned file names', async () => {
it('should resolve with the returned file names', done => {
promise.then(result => {
expect(result).toEqual(EXISTING_DOWNLOADS);
done();
});
readdirCb(null, EXISTING_DOWNLOADS);
await expectAsync(promise).toBeResolvedTo(EXISTING_DOWNLOADS);
});
it('should ignore files that do not match the artifactPath', async () => {
it('should ignore files that do not match the artifactPath', done => {
promise.then(result => {
expect(result).toEqual(['10-ABCDEF-build.zip', '30-FFFFFFF-build.zip']);
done();
});
readdirCb(null, ['10-ABCDEF-build.zip', '20-AAAAAAA-otherfile.zip', '30-FFFFFFF-build.zip']);
await expectAsync(promise).toBeResolvedTo(['10-ABCDEF-build.zip', '30-FFFFFFF-build.zip']);
});
});
@ -299,7 +364,7 @@ describe('BuildCleaner', () => {
});
it('should test if the directory exists (and return if it does not)', () => {
it('should test if the directory exists (and return if is does not)', () => {
shellTestSpy.and.returnValue(false);
cleaner.removeDir('/foo/bar');
@ -316,19 +381,22 @@ describe('BuildCleaner', () => {
it('should make the directory and its content writable before removing', () => {
shellRmSpy.and.callFake(() => expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a+w', '/foo/bar'));
cleaner.removeDir('/foo/bar');
expect(shellChmodSpy).toHaveBeenCalledBefore(shellRmSpy);
expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a+w', '/foo/bar');
expect(shellRmSpy).toHaveBeenCalled();
});
it('should catch errors and log them', () => {
shellRmSpy.and.throwError('Test');
shellRmSpy.and.callFake(() => {
// tslint:disable-next-line: no-string-throw
throw 'Test';
});
cleaner.removeDir('/foo/bar');
expect(loggerErrorSpy).toHaveBeenCalledWith('ERROR: Unable to remove \'/foo/bar\' due to:', new Error('Test'));
expect(loggerErrorSpy).toHaveBeenCalledWith('ERROR: Unable to remove \'/foo/bar\' due to:', 'Test');
});
});
@ -381,7 +449,7 @@ describe('BuildCleaner', () => {
expect(cleanerRemoveDirSpy).toHaveBeenCalledTimes(0);
cleanerRemoveDirSpy.calls.reset();
cleaner.removeUnnecessaryBuilds([1, 2, 3, 4], []);
(cleaner as any).removeUnnecessaryBuilds([1, 2, 3, 4], []);
expect(cleanerRemoveDirSpy).toHaveBeenCalledTimes(8);
expect(cleanerRemoveDirSpy).toHaveBeenCalledWith(normalize('/foo/bar/1'));
expect(cleanerRemoveDirSpy).toHaveBeenCalledWith(normalize('/foo/bar/2'));

View File

@ -45,15 +45,25 @@ describe('CircleCIApi', () => {
const errorMessage = 'Invalid request';
const request = nock(BASE_URL).get(`/${buildNum}?circle-token=${TOKEN}`);
request.replyWithError(errorMessage);
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
try {
request.replyWithError(errorMessage);
await api.getBuildInfo(buildNum);
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
`CircleCI build info request failed ` +
`(request to ${BASE_URL}/${buildNum}?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
request.reply(404, errorMessage);
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
try {
request.reply(404, errorMessage);
await api.getBuildInfo(buildNum);
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
`CircleCI build info request failed ` +
`(request to ${BASE_URL}/${buildNum}?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
});
});
@ -68,7 +78,8 @@ describe('CircleCIApi', () => {
.get(`/${buildNum}/artifacts?circle-token=${TOKEN}`)
.reply(200, [artifact0, artifact1, artifact2]);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeResolvedTo('https://url/1');
const artifactUrl = await api.getBuildArtifactUrl(buildNum, 'some/path/1');
expect(artifactUrl).toEqual('https://url/1');
request.done();
});
@ -79,15 +90,25 @@ describe('CircleCIApi', () => {
const errorMessage = 'Invalid request';
const request = nock(BASE_URL).get(`/${buildNum}/artifacts?circle-token=${TOKEN}`);
request.replyWithError(errorMessage);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
try {
request.replyWithError(errorMessage);
await api.getBuildArtifactUrl(buildNum, 'some/path/1');
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
`CircleCI artifact URL request failed ` +
`(request to ${BASE_URL}/${buildNum}/artifacts?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
request.reply(404, errorMessage);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
try {
request.reply(404, errorMessage);
await api.getBuildArtifactUrl(buildNum, 'some/path/1');
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
`CircleCI artifact URL request failed ` +
`(request to ${BASE_URL}/${buildNum}/artifacts?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
}
});
it('should throw an error if the response does not contain the specified artifact', async () => {
@ -100,9 +121,14 @@ describe('CircleCIApi', () => {
.get(`/${buildNum}/artifacts?circle-token=${TOKEN}`)
.reply(200, [artifact0, artifact1, artifact2]);
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/3')).toBeRejectedWithError(
try {
await api.getBuildArtifactUrl(buildNum, 'some/path/3');
throw new Error('Exception Expected');
} catch (err) {
expect(err.message).toEqual(
`CircleCI artifact URL request failed ` +
`(Missing artifact (some/path/3) for CircleCI build: ${buildNum})`);
}
});
});
});

View File

@ -118,7 +118,7 @@ describe('GithubApi', () => {
it('should return a promise', () => {
expect((api as any).getPaginated()).toBeInstanceOf(Promise);
expect((api as any).getPaginated()).toEqual(jasmine.any(Promise));
});
@ -131,30 +131,45 @@ describe('GithubApi', () => {
});
it('should reject if the request fails', async () => {
const responsePromise = (api as any).getPaginated('/foo/bar');
it('should reject if the request fails', done => {
(api as any).getPaginated('/foo/bar').catch((err: any) => {
expect(err).toBe('Test');
done();
});
deferreds[0].reject('Test');
await expectAsync(responsePromise).toBeRejectedWith('Test');
});
it('should resolve with the returned items', async () => {
it('should resolve with the returned items', done => {
const items = [{id: 1}, {id: 2}];
const responsePromise = (api as any).getPaginated('/foo/bar');
deferreds[0].resolve(items);
await expectAsync(responsePromise).toBeResolvedTo(items);
(api as any).getPaginated('/foo/bar').then((data: any) => {
expect(data).toEqual(items);
done();
});
deferreds[0].resolve(items);
});
it('should iteratively call \'get()\' to fetch all items', async () => {
it('should iteratively call \'get()\' to fetch all items', done => {
// Create an array or 250 objects.
const allItems = new Array(250).fill(null).map((_, i) => ({id: i}));
const allItems = '.'.repeat(250).split('').map((_, i) => ({id: i}));
const apiGetSpy = api.get as jasmine.Spy;
const paramsForPage = (page: number) => ({baz: 'qux', page, per_page: 100});
const responsePromise = (api as any).getPaginated('/foo/bar', {baz: 'qux'});
(api as any).getPaginated('/foo/bar', {baz: 'qux'}).then((data: any) => {
const paramsForPage = (page: number) => ({baz: 'qux', page, per_page: 100});
expect(apiGetSpy).toHaveBeenCalledTimes(3);
expect(apiGetSpy.calls.argsFor(0)).toEqual(['/foo/bar', paramsForPage(1)]);
expect(apiGetSpy.calls.argsFor(1)).toEqual(['/foo/bar', paramsForPage(2)]);
expect(apiGetSpy.calls.argsFor(2)).toEqual(['/foo/bar', paramsForPage(3)]);
expect(data).toEqual(allItems);
done();
});
deferreds[0].resolve(allItems.slice(0, 100));
setTimeout(() => {
@ -163,13 +178,6 @@ describe('GithubApi', () => {
deferreds[2].resolve(allItems.slice(200));
}, 0);
}, 0);
await expectAsync(responsePromise).toBeResolvedTo(allItems);
expect(apiGetSpy).toHaveBeenCalledTimes(3);
expect(apiGetSpy.calls.argsFor(0)).toEqual(['/foo/bar', paramsForPage(1)]);
expect(apiGetSpy.calls.argsFor(1)).toEqual(['/foo/bar', paramsForPage(2)]);
expect(apiGetSpy.calls.argsFor(2)).toEqual(['/foo/bar', paramsForPage(3)]);
});
});
@ -209,8 +217,8 @@ describe('GithubApi', () => {
describe('request()', () => {
it('should return a promise', () => {
nock('https://api.github.com').get('/').reply(200);
expect((api as any).request()).toBeInstanceOf(Promise);
nock('https://api.github.com').get('').reply(200);
expect((api as any).request()).toEqual(jasmine.any(Promise));
});
@ -239,8 +247,9 @@ describe('GithubApi', () => {
nock('https://api.github.com')
.intercept('/path', 'method')
.replyWithError('Test');
await expectAsync((api as any).request('method', '/path')).toBeRejectedWithError('Test');
let message = 'Failed to reject error';
await (api as any).request('method', '/path').catch((err: any) => message = err.message);
expect(message).toEqual('Test');
});
@ -254,69 +263,81 @@ describe('GithubApi', () => {
});
it('should reject if response statusCode is <200', async () => {
it('should reject if response statusCode is <200', done => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(199);
const responsePromise = (api as any).request('method', '/path');
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('failed'));
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('status: 199'));
(api as any).request('method', '/path')
.catch((err: string) => {
expect(err).toContain('failed');
expect(err).toContain('status: 199');
done();
});
requestHandler.done();
});
it('should reject if response statusCode is >=400', async () => {
it('should reject if response statusCode is >=400', done => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(400);
const responsePromise = (api as any).request('method', '/path');
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('failed'));
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('status: 400'));
(api as any).request('method', '/path')
.catch((err: string) => {
expect(err).toContain('failed');
expect(err).toContain('status: 400');
done();
});
requestHandler.done();
});
it('should include the response text in the rejection message', async () => {
it('should include the response text in the rejection message', done => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(500, 'Test');
const responsePromise = (api as any).request('method', '/path');
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('Test'));
(api as any).request('method', '/path')
.catch((err: string) => {
expect(err).toContain('Test');
done();
});
requestHandler.done();
});
it('should resolve if returned statusCode is >=200 and <400', async () => {
it('should resolve if returned statusCode is >=200 and <400', done => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(200);
await expectAsync((api as any).request('method', '/path')).toBeResolved();
(api as any).request('method', '/path').then(done);
requestHandler.done();
});
it('should parse the response body into an object using \'JSON.parse\'', async () => {
it('should parse the response body into an object using \'JSON.parse\'', done => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(300, '{"foo": "bar"}');
await expectAsync((api as any).request('method', '/path')).toBeResolvedTo({foo: 'bar'});
(api as any).request('method', '/path').then((data: any) => {
expect(data).toEqual({foo: 'bar'});
done();
});
requestHandler.done();
});
it('should reject if the response text is malformed JSON', async () => {
it('should reject if the response text is malformed JSON', done => {
const requestHandler = nock('https://api.github.com')
.intercept('/path', 'method')
.reply(300, '}');
await expectAsync((api as any).request('method', '/path')).toBeRejectedWithError(SyntaxError);
(api as any).request('method', '/path').catch((err: any) => {
expect(err).toEqual(jasmine.any(SyntaxError));
done();
});
requestHandler.done();
});

View File

@ -1,6 +1,6 @@
// Imports
import {GithubApi} from '../../lib/common/github-api';
import {GithubPullRequests, PullRequest} from '../../lib/common/github-pull-requests';
import {GithubPullRequests} from '../../lib/common/github-pull-requests';
// Tests
describe('GithubPullRequests', () => {
@ -47,21 +47,27 @@ describe('GithubPullRequests', () => {
it('should make a POST request to Github with the correct pathname, params and data', () => {
githubApi.post.and.resolveTo();
githubApi.post.and.callFake(() => Promise.resolve());
prs.addComment(42, 'body');
expect(githubApi.post).toHaveBeenCalledWith('/repos/foo/bar/issues/42/comments', null, {body: 'body'});
});
it('should reject if the request fails', async () => {
githubApi.post.and.rejectWith('Test');
await expectAsync(prs.addComment(42, 'body')).toBeRejectedWith('Test');
it('should reject if the request fails', done => {
githubApi.post.and.callFake(() => Promise.reject('Test'));
prs.addComment(42, 'body').catch(err => {
expect(err).toBe('Test');
done();
});
});
it('should resolve with the data from the Github POST', async () => {
githubApi.post.and.resolveTo('Test');
await expectAsync(prs.addComment(42, 'body')).toBeResolvedTo('Test');
it('should resolve with the data from the Github POST', done => {
githubApi.post.and.callFake(() => Promise.resolve('Test'));
prs.addComment(42, 'body').then(data => {
expect(data).toBe('Test');
done();
});
});
});
@ -81,11 +87,13 @@ describe('GithubPullRequests', () => {
});
it('should resolve with the data returned from GitHub', async () => {
it('should resolve with the data returned from GitHub', done => {
const expected: any = {number: 42};
githubApi.get.and.resolveTo(expected);
await expectAsync(prs.fetch(42)).toBeResolvedTo(expected);
githubApi.get.and.callFake(() => Promise.resolve(expected));
prs.fetch(42).then(data => {
expect(data).toEqual(expected);
done();
});
});
});
@ -117,14 +125,9 @@ describe('GithubPullRequests', () => {
});
it('should forward the value returned by \'getPaginated()\'', async () => {
const mockPrs: PullRequest[] = [
{number: 1, user: {login: 'foo'}, labels: []},
{number: 2, user: {login: 'bar'}, labels: []},
];
githubApi.getPaginated.and.resolveTo(mockPrs);
expect(await prs.fetchAll()).toBe(mockPrs);
it('should forward the value returned by \'getPaginated()\'', () => {
githubApi.getPaginated.and.returnValue('Test');
expect(prs.fetchAll() as any).toBe('Test');
});
});
@ -144,11 +147,13 @@ describe('GithubPullRequests', () => {
});
it('should resolve with the data returned from GitHub', async () => {
it('should resolve with the data returned from GitHub', done => {
const expected: any = [{sha: 'ABCDE', filename: 'a/b/c'}, {sha: '12345', filename: 'x/y/z'}];
githubApi.getPaginated.and.resolveTo(expected);
await expectAsync(prs.fetchFiles(42)).toBeResolvedTo(expected);
githubApi.getPaginated.and.callFake(() => Promise.resolve(expected));
prs.fetchFiles(42).then(data => {
expect(data).toEqual(expected);
done();
});
});
});

View File

@ -1,5 +1,5 @@
import {GithubApi} from '../../lib/common/github-api';
import {GithubTeams, Team} from '../../lib/common/github-teams';
import {GithubTeams} from '../../lib/common/github-teams';
// Tests
describe('GithubTeams', () => {
@ -16,7 +16,6 @@ describe('GithubTeams', () => {
expect(() => new GithubTeams(githubApi, '')).
toThrowError('Missing or empty required parameter \'githubOrg\'!');
});
});
@ -34,14 +33,9 @@ describe('GithubTeams', () => {
});
it('should forward the value returned by \'getPaginated()\'', async () => {
const mockTeams: Team[] = [
{id: 1, slug: 'foo'},
{id: 2, slug: 'bar'},
];
githubApi.getPaginated.and.resolveTo(mockTeams);
expect(await teams.fetchAll()).toBe(mockTeams);
it('should forward the value returned by \'getPaginated()\'', () => {
githubApi.getPaginated.and.returnValue('Test');
expect(teams.fetchAll() as any).toBe('Test');
});
});
@ -56,77 +50,100 @@ describe('GithubTeams', () => {
it('should return a promise', () => {
githubApi.get.and.resolveTo();
githubApi.get.and.callFake(() => Promise.resolve());
const promise = teams.isMemberById('user', [1]);
expect(promise).toBeInstanceOf(Promise);
expect(promise).toEqual(jasmine.any(Promise));
});
it('should resolve with false if called with an empty array', async () => {
await expectAsync(teams.isMemberById('user', [])).toBeResolvedTo(false);
expect(githubApi.get).not.toHaveBeenCalled();
it('should resolve with false if called with an empty array', done => {
teams.isMemberById('user', []).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).not.toHaveBeenCalled();
done();
});
});
it('should call \'get()\' with the correct pathname', async () => {
githubApi.get.and.resolveTo();
await teams.isMemberById('user', [1]);
expect(githubApi.get).toHaveBeenCalledWith('/teams/1/memberships/user');
it('should call \'get()\' with the correct pathname', done => {
githubApi.get.and.callFake(() => Promise.resolve());
teams.isMemberById('user', [1]).then(() => {
expect(githubApi.get).toHaveBeenCalledWith('/teams/1/memberships/user');
done();
});
});
it('should resolve with false if \'get()\' rejects', async () => {
githubApi.get.and.rejectWith(null);
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(false);
expect(githubApi.get).toHaveBeenCalled();
it('should resolve with false if \'get()\' rejects', done => {
githubApi.get.and.callFake(() => Promise.reject(null));
teams.isMemberById('user', [1]).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).toHaveBeenCalled();
done();
});
});
it('should resolve with false if the membership is not active', async () => {
githubApi.get.and.resolveTo({state: 'pending'});
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(false);
expect(githubApi.get).toHaveBeenCalled();
it('should resolve with false if the membership is not active', done => {
githubApi.get.and.callFake(() => Promise.resolve({state: 'pending'}));
teams.isMemberById('user', [1]).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).toHaveBeenCalled();
done();
});
});
it('should resolve with true if the membership is active', async () => {
githubApi.get.and.resolveTo({state: 'active'});
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(true);
it('should resolve with true if the membership is active', done => {
githubApi.get.and.callFake(() => Promise.resolve({state: 'active'}));
teams.isMemberById('user', [1]).then(isMember => {
expect(isMember).toBe(true);
done();
});
});
it('should sequentially call \'get()\' until an active membership is found', async () => {
githubApi.get.
withArgs('/teams/1/memberships/user').and.resolveTo({state: 'pending'}).
withArgs('/teams/2/memberships/user').and.rejectWith(null).
withArgs('/teams/3/memberships/user').and.resolveTo({state: 'active'});
it('should sequentially call \'get()\' until an active membership is found', done => {
const trainedResponses: {[pathname: string]: Promise<{state: string}>} = {
'/teams/1/memberships/user': Promise.resolve({state: 'pending'}),
'/teams/2/memberships/user': Promise.reject(null),
'/teams/3/memberships/user': Promise.resolve({state: 'active'}),
};
githubApi.get.and.callFake((pathname: string) => trainedResponses[pathname]);
await expectAsync(teams.isMemberById('user', [1, 2, 3, 4])).toBeResolvedTo(true);
teams.isMemberById('user', [1, 2, 3, 4]).then(isMember => {
expect(isMember).toBe(true);
expect(githubApi.get).toHaveBeenCalledTimes(3);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
expect(githubApi.get).toHaveBeenCalledTimes(3);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
done();
});
});
it('should resolve with false if no active membership is found', async () => {
githubApi.get.
withArgs('/teams/1/memberships/user').and.resolveTo({state: 'pending'}).
withArgs('/teams/2/memberships/user').and.rejectWith(null).
withArgs('/teams/3/memberships/user').and.resolveTo({state: 'not active'}).
withArgs('/teams/4/memberships/user').and.rejectWith(null);
it('should resolve with false if no active membership is found', done => {
const trainedResponses: {[pathname: string]: Promise<{state: string}>} = {
'/teams/1/memberships/user': Promise.resolve({state: 'pending'}),
'/teams/2/memberships/user': Promise.reject(null),
'/teams/3/memberships/user': Promise.resolve({state: 'not active'}),
'/teams/4/memberships/user': Promise.reject(null),
};
githubApi.get.and.callFake((pathname: string) => trainedResponses[pathname]);
await expectAsync(teams.isMemberById('user', [1, 2, 3, 4])).toBeResolvedTo(false);
teams.isMemberById('user', [1, 2, 3, 4]).then(isMember => {
expect(isMember).toBe(false);
expect(githubApi.get).toHaveBeenCalledTimes(4);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
expect(githubApi.get.calls.argsFor(3)[0]).toBe('/teams/4/memberships/user');
expect(githubApi.get).toHaveBeenCalledTimes(4);
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
expect(githubApi.get.calls.argsFor(3)[0]).toBe('/teams/4/memberships/user');
done();
});
});
});
@ -140,13 +157,14 @@ describe('GithubTeams', () => {
beforeEach(() => {
teams = new GithubTeams(githubApi, 'foo');
teamsFetchAllSpy = spyOn(teams, 'fetchAll').and.resolveTo([{id: 1, slug: 'team1'}, {id: 2, slug: 'team2'}]);
const mockResponse = Promise.resolve([{id: 1, slug: 'team1'}, {id: 2, slug: 'team2'}]);
teamsFetchAllSpy = spyOn(teams, 'fetchAll').and.returnValue(mockResponse);
teamsIsMemberByIdSpy = spyOn(teams, 'isMemberById');
});
it('should return a promise', () => {
expect(teams.isMemberBySlug('user', ['team-slug'])).toBeInstanceOf(Promise);
expect(teams.isMemberBySlug('user', ['team-slug'])).toEqual(jasmine.any(Promise));
});
@ -156,46 +174,55 @@ describe('GithubTeams', () => {
});
it('should resolve with false if \'fetchAll()\' rejects', async () => {
teamsFetchAllSpy.and.rejectWith(null);
await expectAsync(teams.isMemberBySlug('user', ['team-slug'])).toBeResolvedTo(false);
it('should resolve with false if \'fetchAll()\' rejects', done => {
teamsFetchAllSpy.and.callFake(() => Promise.reject(null));
teams.isMemberBySlug('user', ['team-slug']).then(isMember => {
expect(isMember).toBe(false);
done();
});
});
it('should call \'isMemberById()\' with the correct params if no team is found', async () => {
await teams.isMemberBySlug('user', ['no-match']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', []);
it('should call \'isMemberById()\' with the correct params if no team is found', done => {
teams.isMemberBySlug('user', ['no-match']).then(() => {
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', []);
done();
});
});
it('should call \'isMemberById()\' with the correct params if teams are found', async () => {
await teams.isMemberBySlug('userA', ['team1']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userA', [1]);
it('should call \'isMemberById()\' with the correct params if teams are found', done => {
const spy = teamsIsMemberByIdSpy;
await teams.isMemberBySlug('userB', ['team2']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userB', [2]);
await teams.isMemberBySlug('userC', ['team1', 'team2']);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userC', [1, 2]);
Promise.all([
teams.isMemberBySlug('user', ['team1']).then(() => expect(spy).toHaveBeenCalledWith('user', [1])),
teams.isMemberBySlug('user', ['team2']).then(() => expect(spy).toHaveBeenCalledWith('user', [2])),
teams.isMemberBySlug('user', ['team1', 'team2']).then(() => expect(spy).toHaveBeenCalledWith('user', [1, 2])),
]).then(done);
});
it('should resolve with false if \'isMemberById()\' rejects', async () => {
teamsIsMemberByIdSpy.and.rejectWith(null);
await expectAsync(teams.isMemberBySlug('user', ['team1'])).toBeResolvedTo(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalled();
it('should resolve with false if \'isMemberById()\' rejects', done => {
teamsIsMemberByIdSpy.and.callFake(() => Promise.reject(null));
teams.isMemberBySlug('user', ['team1']).then(isMember => {
expect(isMember).toBe(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalled();
done();
});
});
it('should resolve with the value \'isMemberById()\' resolves with', async () => {
teamsIsMemberByIdSpy.and.resolveTo(true);
await expectAsync(teams.isMemberBySlug('userA', ['team1'])).toBeResolvedTo(true);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userA', [1]);
teamsIsMemberByIdSpy.and.resolveTo(false);
await expectAsync(teams.isMemberBySlug('userB', ['team1'])).toBeResolvedTo(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userB', [1]);
teamsIsMemberByIdSpy.and.callFake(() => Promise.resolve(true));
const isMember1 = await teams.isMemberBySlug('user', ['team1']);
expect(isMember1).toBe(true);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', [1]);
teamsIsMemberByIdSpy.and.callFake(() => Promise.resolve(false));
const isMember2 = await teams.isMemberBySlug('user', ['team1']);
expect(isMember2).toBe(false);
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', [1]);
});
});

View File

@ -9,8 +9,7 @@ import {Logger} from '../../lib/common/utils';
import {BuildCreator} from '../../lib/preview-server/build-creator';
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/preview-server/build-events';
import {PreviewServerError} from '../../lib/preview-server/preview-error';
import {customAsyncMatchers} from './jasmine-custom-async-matchers';
import {expectToBePreviewServerError} from './helpers';
// Tests
describe('BuildCreator', () => {
@ -25,7 +24,6 @@ describe('BuildCreator', () => {
const publicShaDir = path.join(publicPrDir, shortSha);
let bc: BuildCreator;
beforeEach(() => jasmine.addAsyncMatchers(customAsyncMatchers));
beforeEach(() => bc = new BuildCreator(buildsDir));
@ -37,8 +35,8 @@ describe('BuildCreator', () => {
it('should extend EventEmitter', () => {
expect(bc).toBeInstanceOf(BuildCreator);
expect(bc).toBeInstanceOf(EventEmitter);
expect(bc).toEqual(jasmine.any(BuildCreator));
expect(bc).toEqual(jasmine.any(EventEmitter));
expect(Object.getPrototypeOf(bc)).toBe(BuildCreator.prototype);
});
@ -69,43 +67,47 @@ describe('BuildCreator', () => {
const shaDir = isPublic ? publicShaDir : hiddenShaDir;
it('should return a promise', async () => {
it('should return a promise', done => {
const promise = bc.create(pr, sha, archive, isPublic);
expect(promise).toBeInstanceOf(Promise);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `extractArchive()`.
// Do not complete the test (and release the spies) synchronously to avoid running the actual
// `extractArchive()`.
await promise;
expect(promise).toEqual(jasmine.any(Promise));
});
it('should update the PR\'s visibility first if necessary', async () => {
await bc.create(pr, sha, archive, isPublic);
it('should update the PR\'s visibility first if necessary', done => {
bcUpdatePrVisibilitySpy.and.callFake(() => expect(shellMkdirSpy).not.toHaveBeenCalled());
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledBefore(shellMkdirSpy);
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(pr, isPublic);
expect(shellMkdirSpy).toHaveBeenCalled();
bc.create(pr, sha, archive, isPublic).
then(() => {
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(pr, isPublic);
expect(shellMkdirSpy).toHaveBeenCalled();
}).
then(done);
});
it('should create the build directory (and any parent directories)', async () => {
await bc.create(pr, sha, archive, isPublic);
expect(shellMkdirSpy).toHaveBeenCalledWith('-p', shaDir);
it('should create the build directory (and any parent directories)', done => {
bc.create(pr, sha, archive, isPublic).
then(() => expect(shellMkdirSpy).toHaveBeenCalledWith('-p', shaDir)).
then(done);
});
it('should extract the archive contents into the build directory', async () => {
await bc.create(pr, sha, archive, isPublic);
expect(bcExtractArchiveSpy).toHaveBeenCalledWith(archive, shaDir);
it('should extract the archive contents into the build directory', done => {
bc.create(pr, sha, archive, isPublic).
then(() => expect(bcExtractArchiveSpy).toHaveBeenCalledWith(archive, shaDir)).
then(done);
});
it('should emit a CreatedBuildEvent on success', async () => {
it('should emit a CreatedBuildEvent on success', done => {
let emitted = false;
bcEmitSpy.and.callFake((type: string, evt: CreatedBuildEvent) => {
expect(type).toBe(CreatedBuildEvent.type);
expect(evt).toBeInstanceOf(CreatedBuildEvent);
expect(evt).toEqual(jasmine.any(CreatedBuildEvent));
expect(evt.pr).toBe(+pr);
expect(evt.sha).toBe(shortSha);
expect(evt.isPublic).toBe(isPublic);
@ -113,108 +115,130 @@ describe('BuildCreator', () => {
emitted = true;
});
await bc.create(pr, sha, archive, isPublic);
expect(emitted).toBe(true);
bc.create(pr, sha, archive, isPublic).
then(() => expect(emitted).toBe(true)).
then(done);
});
describe('on error', () => {
let existsValues: {[dir: string]: boolean};
beforeEach(() => {
bcExistsSpy.and.returnValue(false);
existsValues = {
[prDir]: false,
[shaDir]: false,
};
bcExistsSpy.and.callFake((dir: string) => existsValues[dir]);
});
it('should abort and skip further operations if changing the PR\'s visibility fails', async () => {
it('should abort and skip further operations if changing the PR\'s visibility fails', done => {
const mockError = new PreviewServerError(543, 'Test');
bcUpdatePrVisibilitySpy.and.rejectWith(mockError);
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject(mockError));
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWith(mockError);
bc.create(pr, sha, archive, isPublic).catch(err => {
expect(err).toBe(mockError);
expect(bcExistsSpy).not.toHaveBeenCalled();
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
expect(bcExistsSpy).not.toHaveBeenCalled();
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should abort and skip further operations if the build does already exist', async () => {
bcExistsSpy.withArgs(shaDir).and.returnValue(true);
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
409, `Request to overwrite existing ${isPublic ? '' : 'non-'}public directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
it('should abort and skip further operations if the build does already exist', done => {
existsValues[shaDir] = true;
bc.create(pr, sha, archive, isPublic).catch(err => {
const publicOrNot = isPublic ? 'public' : 'non-public';
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should detect existing build directory after visibility change', async () => {
bcUpdatePrVisibilitySpy.and.callFake(() => bcExistsSpy.and.returnValue(true));
it('should detect existing build directory after visibility change', done => {
bcUpdatePrVisibilitySpy.and.callFake(() => existsValues[prDir] = existsValues[shaDir] = true);
expect(bcExistsSpy(prDir)).toBe(false);
expect(bcExistsSpy(shaDir)).toBe(false);
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
409, `Request to overwrite existing ${isPublic ? '' : 'non-'}public directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.create(pr, sha, archive, isPublic).catch(err => {
const publicOrNot = isPublic ? 'public' : 'non-public';
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
expect(shellMkdirSpy).not.toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should abort and skip further operations if it fails to create the directories', async () => {
it('should abort and skip further operations if it fails to create the directories', done => {
shellMkdirSpy.and.throwError('');
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should abort and skip further operations if it fails to extract the archive', async () => {
it('should abort and skip further operations if it fails to extract the archive', done => {
bcExtractArchiveSpy.and.throwError('');
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should delete the PR directory (for new PR)', done => {
bcExtractArchiveSpy.and.throwError('');
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellRmSpy).toHaveBeenCalledWith('-rf', prDir);
done();
});
});
it('should delete the SHA directory (for existing PR)', done => {
existsValues[prDir] = true;
bcExtractArchiveSpy.and.throwError('');
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellMkdirSpy).toHaveBeenCalled();
expect(bcExtractArchiveSpy).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.create(pr, sha, archive, isPublic).catch(() => {
expect(shellRmSpy).toHaveBeenCalledWith('-rf', shaDir);
done();
});
});
it('should delete the PR directory (for new PR)', async () => {
bcExtractArchiveSpy.and.throwError('');
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellRmSpy).toHaveBeenCalledWith('-rf', prDir);
});
it('should delete the SHA directory (for existing PR)', async () => {
bcExistsSpy.withArgs(prDir).and.returnValue(true);
bcExtractArchiveSpy.and.throwError('');
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
expect(shellRmSpy).toHaveBeenCalledWith('-rf', shaDir);
});
it('should reject with an PreviewServerError', async () => {
it('should reject with an PreviewServerError', done => {
// tslint:disable-next-line: no-string-throw
shellMkdirSpy.and.callFake(() => { throw 'Test'; });
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
500, `Error while creating preview at: ${shaDir}\nTest`);
bc.create(pr, sha, archive, isPublic).catch(err => {
expectToBePreviewServerError(err, 500, `Error while creating preview at: ${shaDir}\nTest`);
done();
});
});
it('should pass PreviewServerError instances unmodified', async () => {
it('should pass PreviewServerError instances unmodified', done => {
shellMkdirSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(543, 'Test');
bc.create(pr, sha, archive, isPublic).catch(err => {
expectToBePreviewServerError(err, 543, 'Test');
done();
});
});
});
@ -241,12 +265,12 @@ describe('BuildCreator', () => {
});
it('should return a promise', async () => {
it('should return a promise', done => {
const promise = bc.updatePrVisibility(pr, true);
expect(promise).toBeInstanceOf(Promise);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `extractArchive()`.
// Do not complete the test (and release the spies) synchronously to avoid running the actual `extractArchive()`.
await promise;
expect(promise).toEqual(jasmine.any(Promise));
});
@ -255,53 +279,58 @@ describe('BuildCreator', () => {
const newPrDir = makePublic ? publicPrDir : hiddenPrDir;
it('should rename the directory', async () => {
await bc.updatePrVisibility(pr, makePublic);
expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir);
it('should rename the directory', done => {
bc.updatePrVisibility(pr, makePublic).
then(() => expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir)).
then(done);
});
describe('when the visibility is updated', () => {
it('should resolve to true', async () => {
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(true);
it('should resolve to true', done => {
bc.updatePrVisibility(pr, makePublic).
then(result => expect(result).toBe(true)).
then(done);
});
it('should rename the directory', async () => {
await bc.updatePrVisibility(pr, makePublic);
expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir);
it('should rename the directory', done => {
bc.updatePrVisibility(pr, makePublic).
then(() => expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir)).
then(done);
});
it('should emit a ChangedPrVisibilityEvent on success', async () => {
it('should emit a ChangedPrVisibilityEvent on success', done => {
let emitted = false;
bcEmitSpy.and.callFake((type: string, evt: ChangedPrVisibilityEvent) => {
expect(type).toBe(ChangedPrVisibilityEvent.type);
expect(evt).toBeInstanceOf(ChangedPrVisibilityEvent);
expect(evt).toEqual(jasmine.any(ChangedPrVisibilityEvent));
expect(evt.pr).toBe(+pr);
expect(evt.shas).toBeInstanceOf(Array);
expect(evt.shas).toEqual(jasmine.any(Array));
expect(evt.isPublic).toBe(makePublic);
emitted = true;
});
await bc.updatePrVisibility(pr, makePublic);
expect(emitted).toBe(true);
bc.updatePrVisibility(pr, makePublic).
then(() => expect(emitted).toBe(true)).
then(done);
});
it('should include all shas in the emitted event', async () => {
it('should include all shas in the emitted event', done => {
const shas = ['foo', 'bar', 'baz'];
let emitted = false;
bcListShasByDate.and.resolveTo(shas);
bcListShasByDate.and.callFake(() => Promise.resolve(shas));
bcEmitSpy.and.callFake((type: string, evt: ChangedPrVisibilityEvent) => {
expect(bcListShasByDate).toHaveBeenCalledWith(newPrDir);
expect(type).toBe(ChangedPrVisibilityEvent.type);
expect(evt).toBeInstanceOf(ChangedPrVisibilityEvent);
expect(evt).toEqual(jasmine.any(ChangedPrVisibilityEvent));
expect(evt.pr).toBe(+pr);
expect(evt.shas).toBe(shas);
expect(evt.isPublic).toBe(makePublic);
@ -309,82 +338,94 @@ describe('BuildCreator', () => {
emitted = true;
});
await bc.updatePrVisibility(pr, makePublic);
expect(emitted).toBe(true);
bc.updatePrVisibility(pr, makePublic).
then(() => expect(emitted).toBe(true)).
then(done);
});
});
it('should do nothing if the visibility is already up-to-date', async () => {
it('should do nothing if the visibility is already up-to-date', done => {
bcExistsSpy.and.callFake((dir: string) => dir === newPrDir);
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.updatePrVisibility(pr, makePublic).
then(result => {
expect(result).toBe(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
}).
then(done);
});
it('should do nothing if the PR directory does not exist', async () => {
it('should do nothing if the PR directory does not exist', done => {
bcExistsSpy.and.returnValue(false);
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.updatePrVisibility(pr, makePublic).
then(result => {
expect(result).toBe(false);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
}).
then(done);
});
describe('on error', () => {
it('should abort and skip further operations if both directories exist', async () => {
it('should abort and skip further operations if both directories exist', done => {
bcExistsSpy.and.returnValue(true);
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(
409, `Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.updatePrVisibility(pr, makePublic).catch(err => {
expectToBePreviewServerError(err, 409,
`Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
expect(shellMvSpy).not.toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should abort and skip further operations if it fails to rename the directory', async () => {
it('should abort and skip further operations if it fails to rename the directory', done => {
shellMvSpy.and.throwError('');
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejected();
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.updatePrVisibility(pr, makePublic).catch(() => {
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).not.toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should abort and skip further operations if it fails to list the SHAs', async () => {
it('should abort and skip further operations if it fails to list the SHAs', done => {
bcListShasByDate.and.throwError('');
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejected();
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
bc.updatePrVisibility(pr, makePublic).catch(() => {
expect(shellMvSpy).toHaveBeenCalled();
expect(bcListShasByDate).toHaveBeenCalled();
expect(bcEmitSpy).not.toHaveBeenCalled();
done();
});
});
it('should reject with an PreviewServerError', async () => {
it('should reject with an PreviewServerError', done => {
// tslint:disable-next-line: no-string-throw
shellMvSpy.and.callFake(() => { throw 'Test'; });
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(
500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
bc.updatePrVisibility(pr, makePublic).catch(err => {
expectToBePreviewServerError(err, 500,
`Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
done();
});
});
it('should pass PreviewServerError instances unmodified', async () => {
it('should pass PreviewServerError instances unmodified', done => {
shellMvSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(543, 'Test');
bc.updatePrVisibility(pr, makePublic).catch(err => {
expectToBePreviewServerError(err, 543, 'Test');
done();
});
});
});
@ -402,14 +443,12 @@ describe('BuildCreator', () => {
beforeEach(() => {
fsAccessCbs = [];
fsAccessSpy = spyOn(fs, 'access').and.callFake(
((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb)) as unknown as typeof fs.access,
);
fsAccessSpy = spyOn(fs, 'access').and.callFake((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb));
});
it('should return a promise', () => {
expect((bc as any).exists('foo')).toBeInstanceOf(Promise);
expect((bc as any).exists('foo')).toEqual(jasmine.any(Promise));
});
@ -419,29 +458,25 @@ describe('BuildCreator', () => {
});
it('should resolve with \'true\' if \'fs.access()\' succeeds', async () => {
const existsPromises = [
(bc as any).exists('foo'),
(bc as any).exists('bar'),
];
it('should resolve with \'true\' if \'fs.access()\' succeeds', done => {
Promise.
all([(bc as any).exists('foo'), (bc as any).exists('bar')]).
then(results => expect(results).toEqual([true, true])).
then(done);
fsAccessCbs[0]();
fsAccessCbs[1](null);
await expectAsync(Promise.all(existsPromises)).toBeResolvedTo([true, true]);
});
it('should resolve with \'false\' if \'fs.access()\' errors', async () => {
const existsPromises = [
(bc as any).exists('foo'),
(bc as any).exists('bar'),
];
it('should resolve with \'false\' if \'fs.access()\' errors', done => {
Promise.
all([(bc as any).exists('foo'), (bc as any).exists('bar')]).
then(results => expect(results).toEqual([false, false])).
then(done);
fsAccessCbs[0]('Error');
fsAccessCbs[1](new Error());
await expectAsync(Promise.all(existsPromises)).toBeResolvedTo([false, false]);
});
});
@ -460,15 +495,12 @@ describe('BuildCreator', () => {
consoleWarnSpy = spyOn(Logger.prototype, 'warn');
shellChmodSpy = spyOn(shell, 'chmod');
shellRmSpy = spyOn(shell, 'rm');
cpExecSpy = spyOn(cp, 'exec').and.callFake(
((_: string, cb: (...args: any[]) => void) =>
cpExecCbs.push(cb)) as unknown as typeof cp.exec,
);
cpExecSpy = spyOn(cp, 'exec').and.callFake((_: string, cb: (...args: any[]) => void) => cpExecCbs.push(cb));
});
it('should return a promise', () => {
expect((bc as any).extractArchive('foo', 'bar')).toBeInstanceOf(Promise);
expect((bc as any).extractArchive('foo', 'bar')).toEqual(jasmine.any(Promise));
});
@ -480,68 +512,78 @@ describe('BuildCreator', () => {
});
it('should log (as a warning) any stderr output if extracting succeeded', async () => {
const extractPromise = (bc as any).extractArchive('foo', 'bar');
it('should log (as a warning) any stderr output if extracting succeeded', done => {
(bc as any).extractArchive('foo', 'bar').
then(() => expect(consoleWarnSpy).toHaveBeenCalledWith('This is stderr')).
then(done);
cpExecCbs[0](null, 'This is stdout', 'This is stderr');
await expectAsync(extractPromise).toBeResolved();
expect(consoleWarnSpy).toHaveBeenCalledWith('This is stderr');
});
it('should make the build directory non-writable', async () => {
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]();
it('should make the build directory non-writable', done => {
(bc as any).extractArchive('foo', 'bar').
then(() => expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a-w', 'bar')).
then(done);
await expectAsync(extractPromise).toBeResolved();
expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a-w', 'bar');
cpExecCbs[0]();
});
it('should delete the build artifact file on success', async () => {
const extractPromise = (bc as any).extractArchive('input/file', 'output/dir');
cpExecCbs[0]();
it('should delete the build artifact file on success', done => {
(bc as any).extractArchive('input/file', 'output/dir').
then(() => expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file')).
then(done);
await expectAsync(extractPromise).toBeResolved();
expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file');
cpExecCbs[0]();
});
describe('on error', () => {
it('should abort and skip further operations if it fails to extract the archive', async () => {
const extractPromise = (bc as any).extractArchive('foo', 'bar');
it('should abort and skip further operations if it fails to extract the archive', done => {
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
expect(shellChmodSpy).not.toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
expect(err).toBe('Test');
done();
});
cpExecCbs[0]('Test');
await expectAsync(extractPromise).toBeRejectedWith('Test');
expect(shellChmodSpy).not.toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
});
it('should abort and skip further operations if it fails to make non-writable', async () => {
// tslint:disable-next-line: no-string-throw
shellChmodSpy.and.callFake(() => { throw 'Test'; });
it('should abort and skip further operations if it fails to make non-writable', done => {
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
expect(err).toBe('Test');
done();
});
shellChmodSpy.and.callFake(() => {
// tslint:disable-next-line: no-string-throw
throw 'Test';
});
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]();
await expectAsync(extractPromise).toBeRejectedWith('Test');
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).not.toHaveBeenCalled();
});
it('should abort and reject if it fails to remove the build artifact file', async () => {
// tslint:disable-next-line: no-string-throw
shellRmSpy.and.callFake(() => { throw 'Test'; });
it('should abort and reject if it fails to remove the build artifact file', done => {
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).toHaveBeenCalled();
expect(err).toBe('Test');
done();
});
shellRmSpy.and.callFake(() => {
// tslint:disable-next-line: no-string-throw
throw 'Test';
});
const extractPromise = (bc as any).extractArchive('foo', 'bar');
cpExecCbs[0]();
await expectAsync(extractPromise).toBeRejectedWith('Test');
expect(shellChmodSpy).toHaveBeenCalled();
expect(shellRmSpy).toHaveBeenCalled();
});
});
@ -558,54 +600,62 @@ describe('BuildCreator', () => {
});
beforeEach(() => {
shellLsSpy = spyOn(shell, 'ls').and.returnValue([] as unknown as shell.ShellArray);
shellLsSpy = spyOn(shell, 'ls').and.returnValue([]);
});
it('should return a promise', async () => {
it('should return a promise', done => {
const promise = (bc as any).listShasByDate('input/dir');
expect(promise).toBeInstanceOf(Promise);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `ls()`.
// Do not complete the test (and release the spies) synchronously to avoid running the actual `ls()`.
await promise;
expect(promise).toEqual(jasmine.any(Promise));
});
it('should `ls()` files with their metadata', async () => {
await (bc as any).listShasByDate('input/dir');
expect(shellLsSpy).toHaveBeenCalledWith('-l', 'input/dir');
it('should `ls()` files with their metadata', done => {
(bc as any).listShasByDate('input/dir').
then(() => expect(shellLsSpy).toHaveBeenCalledWith('-l', 'input/dir')).
then(done);
});
it('should reject if listing files fails', async () => {
shellLsSpy.and.rejectWith('Test');
await expectAsync((bc as any).listShasByDate('input/dir')).toBeRejectedWith('Test');
it('should reject if listing files fails', done => {
shellLsSpy.and.callFake(() => Promise.reject('Test'));
(bc as any).listShasByDate('input/dir').catch((err: string) => {
expect(err).toBe('Test');
done();
});
});
it('should return the filenames', async () => {
shellLsSpy.and.resolveTo([
it('should return the filenames', done => {
shellLsSpy.and.callFake(() => Promise.resolve([
lsResult('foo', 100),
lsResult('bar', 200),
lsResult('baz', 300),
]);
]));
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['foo', 'bar', 'baz']);
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => expect(shas).toEqual(['foo', 'bar', 'baz'])).
then(done);
});
it('should sort by date', async () => {
shellLsSpy.and.resolveTo([
it('should sort by date', done => {
shellLsSpy.and.callFake(() => Promise.resolve([
lsResult('foo', 300),
lsResult('bar', 100),
lsResult('baz', 200),
]);
]));
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['bar', 'baz', 'foo']);
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => expect(shas).toEqual(['bar', 'baz', 'foo'])).
then(done);
});
it('should not break with ShellJS\' custom `sort()` method', async () => {
it('should not break with ShellJS\' custom `sort()` method', done => {
const mockArray = [
lsResult('foo', 300),
lsResult('bar', 100),
@ -613,21 +663,26 @@ describe('BuildCreator', () => {
];
mockArray.sort = jasmine.createSpy('sort');
shellLsSpy.and.resolveTo(mockArray);
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['bar', 'baz', 'foo']);
expect(mockArray.sort).not.toHaveBeenCalled();
shellLsSpy.and.callFake(() => Promise.resolve(mockArray));
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => {
expect(shas).toEqual(['bar', 'baz', 'foo']);
expect(mockArray.sort).not.toHaveBeenCalled();
}).
then(done);
});
it('should only include directories', async () => {
shellLsSpy.and.resolveTo([
it('should only include directories', done => {
shellLsSpy.and.callFake(() => Promise.resolve([
lsResult('foo', 100),
lsResult('bar', 200, false),
lsResult('baz', 300),
]);
]));
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['foo', 'baz']);
(bc as any).listShasByDate('input/dir').
then((shas: string[]) => expect(shas).toEqual(['foo', 'baz'])).
then(done);
});
});

View File

@ -32,18 +32,18 @@ describe('BuildRetriever', () => {
};
api = new CircleCiApi('ORG', 'REPO', 'TOKEN');
spyOn(api, 'getBuildInfo').and.resolveTo(BUILD_INFO);
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl').and.resolveTo(BASE_URL + ARTIFACT_PATH);
spyOn(api, 'getBuildInfo').and.callFake(() => Promise.resolve(BUILD_INFO));
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl')
.and.callFake(() => Promise.resolve(BASE_URL + ARTIFACT_PATH));
WRITEFILE_RESULT = undefined;
writeFileSpy = spyOn(fs, 'writeFile').and.callFake(
((_path: string, _buffer: Buffer, callback: fs.NoParamCallback) =>
callback(WRITEFILE_RESULT)) as typeof fs.writeFile,
(_path: string, _buffer: Buffer, callback: (err?: any) => {}) => callback(WRITEFILE_RESULT),
);
EXISTS_RESULT = false;
existsSpy = spyOn(fs, 'exists').and.callFake(
((_path, callback) => callback(EXISTS_RESULT)) as typeof fs.exists,
(_path: string, callback: (exists: boolean) => {}) => callback(EXISTS_RESULT),
);
});
@ -56,7 +56,6 @@ describe('BuildRetriever', () => {
expect(() => new BuildRetriever(api, -1, DOWNLOAD_DIR))
.toThrowError(`Invalid parameter "downloadSizeLimit" should be a number greater than 0.`);
});
it('should fail if the "downloadDir" is missing', () => {
expect(() => new BuildRetriever(api, MAX_DOWNLOAD_SIZE, ''))
.toThrowError(`Missing or empty required parameter 'downloadDir'!`);
@ -73,10 +72,14 @@ describe('BuildRetriever', () => {
});
it('should error if it is not possible to extract the PR number from the branch', async () => {
BUILD_INFO.branch = 'master';
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
await expectAsync(retriever.getGithubInfo(12345)).toBeRejectedWithError('No PR found in branch field: master');
try {
BUILD_INFO.branch = 'master';
await retriever.getGithubInfo(12345);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('No PR found in branch field: master');
}
});
});
@ -107,10 +110,12 @@ describe('BuildRetriever', () => {
it('should fail if the artifact is too large', async () => {
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(200, ARTIFACT_CONTENTS);
retriever = new BuildRetriever(api, 10, DOWNLOAD_DIR);
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWith(jasmine.objectContaining({status: 413}));
try {
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.status).toEqual(413);
}
artifactRequest.done();
});
@ -138,40 +143,50 @@ describe('BuildRetriever', () => {
artifactRequest.done();
});
it('should fail if the CircleCI API fails', async () => {
getBuildArtifactUrlSpy.and.rejectWith('getBuildArtifactUrl failed');
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWithError('CircleCI artifact download failed (getBuildArtifactUrl failed)');
it('should fail if the CircleCI API fails', async () => {
try {
getBuildArtifactUrlSpy.and.callFake(() => Promise.reject('getBuildArtifactUrl failed'));
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed (getBuildArtifactUrl failed)');
}
});
it('should fail if the URL fetch errors', async () => {
it('should fail if the URL fetch errors', async () => {
// create a new handler that errors
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).replyWithError('Artifact Request Failed');
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).toBeRejectedWithError(
'CircleCI artifact download failed ' +
try {
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed ' +
'(request to http://test.com/some/path/build.zip failed, reason: Artifact Request Failed)');
}
artifactRequest.done();
});
it('should fail if the URL fetch 404s', async () => {
it('should fail if the URL fetch 404s', async () => {
// create a new handler that errors
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(404, 'No such artifact');
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWithError('CircleCI artifact download failed (Error 404 - Not Found)');
try {
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed (Error 404 - Not Found)');
}
artifactRequest.done();
});
it('should fail if file write fails', async () => {
it('should fail if file write fails', async () => {
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(200, ARTIFACT_CONTENTS);
WRITEFILE_RESULT = 'Test Error';
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
toBeRejectedWithError('CircleCI artifact download failed (Test Error)');
try {
WRITEFILE_RESULT = 'Test Error';
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
throw new Error('Exception Expected');
} catch (error) {
expect(error.message).toEqual('CircleCI artifact download failed (Test Error)');
}
artifactRequest.done();
});
});

View File

@ -51,10 +51,7 @@ describe('BuildVerifier', () => {
describe('getSignificantFilesChanged', () => {
it('should return false if none of the fetched files match the given pattern', async () => {
const fetchFilesSpy = spyOn(prs, 'fetchFiles');
fetchFilesSpy.and.resolveTo([
{filename: 'a/b/c', sha: 'a1'},
{filename: 'd/e/f', sha: 'b2'},
]);
fetchFilesSpy.and.callFake(() => Promise.resolve([{filename: 'a/b/c'}, {filename: 'd/e/f'}]));
expect(await bv.getSignificantFilesChanged(777, /^x/)).toEqual(false);
expect(fetchFilesSpy).toHaveBeenCalledWith(777);
@ -81,30 +78,37 @@ describe('BuildVerifier', () => {
user: {login: 'username'},
};
prsFetchSpy = spyOn(GithubPullRequests.prototype, 'fetch').and.resolveTo(mockPrInfo);
teamsIsMemberBySlugSpy = spyOn(GithubTeams.prototype, 'isMemberBySlug').and.resolveTo(true);
prsFetchSpy = spyOn(GithubPullRequests.prototype, 'fetch').
and.callFake(() => Promise.resolve(mockPrInfo));
teamsIsMemberBySlugSpy = spyOn(GithubTeams.prototype, 'isMemberBySlug').
and.callFake(() => Promise.resolve(true));
});
it('should return a promise', async () => {
it('should return a promise', done => {
const promise = bv.getPrIsTrusted(pr);
expect(promise).toBeInstanceOf(Promise);
promise.then(done); // Do not complete the test (and release the spies) synchronously
// to avoid running the actual `GithubTeams#isMemberBySlug()`.
// Do not complete the test (and release the spies) synchronously to avoid running the actual
// `GithubTeams#isMemberBySlug()`.
await promise;
expect(promise).toEqual(jasmine.any(Promise));
});
it('should fetch the corresponding PR', async () => {
await bv.getPrIsTrusted(pr);
expect(prsFetchSpy).toHaveBeenCalledWith(pr);
it('should fetch the corresponding PR', done => {
bv.getPrIsTrusted(pr).then(() => {
expect(prsFetchSpy).toHaveBeenCalledWith(pr);
done();
});
});
it('should fail if fetching the PR errors', async () => {
prsFetchSpy.and.rejectWith('Test');
await expectAsync(bv.getPrIsTrusted(pr)).toBeRejectedWith('Test');
it('should fail if fetching the PR errors', done => {
prsFetchSpy.and.callFake(() => Promise.reject('Test'));
bv.getPrIsTrusted(pr).catch(err => {
expect(err).toBe('Test');
done();
});
});
@ -113,14 +117,19 @@ describe('BuildVerifier', () => {
beforeEach(() => mockPrInfo.labels.push({name: 'trusted: pr-label'}));
it('should resolve to true', async () => {
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(true);
it('should resolve to true', done => {
bv.getPrIsTrusted(pr).then(isTrusted => {
expect(isTrusted).toBe(true);
done();
});
});
it('should not try to verify the author\'s membership status', async () => {
await expectAsync(bv.getPrIsTrusted(pr));
expect(teamsIsMemberBySlugSpy).not.toHaveBeenCalled();
it('should not try to verify the author\'s membership status', done => {
bv.getPrIsTrusted(pr).then(() => {
expect(teamsIsMemberBySlugSpy).not.toHaveBeenCalled();
done();
});
});
});
@ -128,27 +137,40 @@ describe('BuildVerifier', () => {
describe('when the PR does not have the "trusted PR" label', () => {
it('should verify the PR author\'s membership in the specified teams', async () => {
await bv.getPrIsTrusted(pr);
expect(teamsIsMemberBySlugSpy).toHaveBeenCalledWith('username', ['team1', 'team2']);
it('should verify the PR author\'s membership in the specified teams', done => {
bv.getPrIsTrusted(pr).then(() => {
expect(teamsIsMemberBySlugSpy).toHaveBeenCalledWith('username', ['team1', 'team2']);
done();
});
});
it('should fail if verifying membership errors', async () => {
teamsIsMemberBySlugSpy.and.rejectWith('Test');
await expectAsync(bv.getPrIsTrusted(pr)).toBeRejectedWith('Test');
it('should fail if verifying membership errors', done => {
teamsIsMemberBySlugSpy.and.callFake(() => Promise.reject('Test'));
bv.getPrIsTrusted(pr).catch(err => {
expect(err).toBe('Test');
done();
});
});
it('should resolve to true if the PR\'s author is a member', async () => {
teamsIsMemberBySlugSpy.and.resolveTo(true);
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(true);
it('should resolve to true if the PR\'s author is a member', done => {
teamsIsMemberBySlugSpy.and.callFake(() => Promise.resolve(true));
bv.getPrIsTrusted(pr).then(isTrusted => {
expect(isTrusted).toBe(true);
done();
});
});
it('should resolve to false if the PR\'s author is not a member', async () => {
teamsIsMemberBySlugSpy.and.resolveTo(false);
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(false);
it('should resolve to false if the PR\'s author is not a member', done => {
teamsIsMemberBySlugSpy.and.callFake(() => Promise.resolve(false));
bv.getPrIsTrusted(pr).then(isTrusted => {
expect(isTrusted).toBe(false);
done();
});
});
});

View File

@ -0,0 +1,11 @@
import {PreviewServerError} from '../../lib/preview-server/preview-error';
export const expectToBePreviewServerError = (actual: PreviewServerError, status?: number, message?: string) => {
expect(actual).toEqual(jasmine.any(PreviewServerError));
if (status != null) {
expect(actual.status).toBe(status);
}
if (message != null) {
expect(actual.message).toBe(message);
}
};

View File

@ -1,5 +0,0 @@
declare module jasmine {
interface AsyncMatchers {
toBeRejectedWithPreviewServerError(status: number, message?: string | RegExp): Promise<void>;
}
}

View File

@ -1,59 +0,0 @@
import {PreviewServerError} from '../../lib/preview-server/preview-error';
// Matchers
const toBeRejectedWithPreviewServerError: jasmine.CustomAsyncMatcherFactory = () => {
return {
async compare(actualPromise: Promise<never>, expectedStatus: number, expectedMessage?: string | RegExp) {
if (!(actualPromise instanceof Promise)) {
throw new Error(`Expected '${toBeRejectedWithPreviewServerError.name}()' to be called on a promise.`);
}
try {
await actualPromise;
return {
pass: false,
message: `Expected a promise to be rejected with a '${PreviewServerError.name}', but it was resolved.`,
};
} catch (actualError) {
const actualPrintValue = stringify(actualError);
const expectedPrintValue =
stringify(new PreviewServerError(expectedStatus, expectedMessage && `${expectedMessage}`));
const pass = errorMatches(actualError, expectedStatus, expectedMessage);
const message =
`Expected a promise ${pass ? 'not ' : ''}to be rejected with ${expectedPrintValue}, but is was` +
`${pass ? '' : ` rejected with ${actualPrintValue}`}.`;
return {pass, message};
}
},
};
// Helpers
function errorMatches(actualErr: unknown, expectedStatus: number, expectedMsg?: string | RegExp): boolean {
if (!(actualErr instanceof PreviewServerError)) return false;
if (actualErr.status !== expectedStatus) return false;
return messageMatches(actualErr.message, expectedMsg);
}
function messageMatches(actualMsg: string, expectedMsg?: string | RegExp): boolean {
if (typeof expectedMsg === 'undefined') return true;
if (typeof expectedMsg === 'string') return actualMsg === expectedMsg;
return expectedMsg.test(actualMsg);
}
function stringify(value: unknown): string {
if (value instanceof PreviewServerError) {
return `${PreviewServerError.name}(${value.status}${value.message ? `, ${value.message}` : ''})`;
}
return jasmine.pp(value);
}
};
// Exports
export const customAsyncMatchers: jasmine.CustomAsyncMatcherFactories = {
toBeRejectedWithPreviewServerError,
};

View File

@ -9,8 +9,8 @@ describe('PreviewServerError', () => {
it('should extend Error', () => {
expect(err).toBeInstanceOf(PreviewServerError);
expect(err).toBeInstanceOf(Error);
expect(err).toEqual(jasmine.any(PreviewServerError));
expect(err).toEqual(jasmine.any(Error));
expect(Object.getPrototypeOf(err)).toBe(PreviewServerError.prototype);
});

View File

@ -1,4 +1,5 @@
// Imports
import * as express from 'express';
import * as http from 'http';
import * as supertest from 'supertest';
import {CircleCiApi} from '../../lib/common/circle-ci-api';
@ -133,7 +134,7 @@ describe('PreviewServerFactory', () => {
const buildCreator = jasmine.any(BuildCreator);
expect(usfCreateMiddlewareSpy).toHaveBeenCalledWith(buildRetriever, buildVerifier, buildCreator, defaultConfig);
const middleware = usfCreateMiddlewareSpy.calls.mostRecent().returnValue;
const middleware: express.Express = usfCreateMiddlewareSpy.calls.mostRecent().returnValue;
expect(httpCreateServerSpy).toHaveBeenCalledWith(middleware);
});
@ -229,7 +230,7 @@ describe('PreviewServerFactory', () => {
expect(prsAddCommentSpy).toHaveBeenCalledTimes(2);
expect(prs).toBe(allCalls[1].object);
expect(prs).toBeInstanceOf(GithubPullRequests);
expect(prs).toEqual(jasmine.any(GithubPullRequests));
expect(prs.repoSlug).toBe('organisation/repo');
});
@ -301,8 +302,9 @@ describe('PreviewServerFactory', () => {
let bvGetSignificantFilesChangedSpy: jasmine.Spy;
beforeEach(() => {
bvGetPrIsTrustedSpy = spyOn(buildVerifier, 'getPrIsTrusted').and.resolveTo(true);
bvGetSignificantFilesChangedSpy = spyOn(buildVerifier, 'getSignificantFilesChanged').and.resolveTo(true);
bvGetPrIsTrustedSpy = spyOn(buildVerifier, 'getPrIsTrusted').and.returnValue(Promise.resolve(true));
bvGetSignificantFilesChangedSpy = spyOn(buildVerifier, 'getSignificantFilesChanged').
and.returnValue(Promise.resolve(true));
});
@ -329,7 +331,7 @@ describe('PreviewServerFactory', () => {
it('should respond appropriately if the PR did not touch any significant files', async () => {
bvGetSignificantFilesChangedSpy.and.resolveTo(false);
bvGetSignificantFilesChangedSpy.and.returnValue(Promise.resolve(false));
const expectedResponse = {canHavePublicPreview: false, reason: 'No significant files touched.'};
const expectedLog = `PR:${pr} - Cannot have a public preview, because it did not touch any significant files.`;
@ -343,7 +345,7 @@ describe('PreviewServerFactory', () => {
it('should respond appropriately if the PR is not automatically verifiable as "trusted"', async () => {
bvGetPrIsTrustedSpy.and.resolveTo(false);
bvGetPrIsTrustedSpy.and.returnValue(Promise.resolve(false));
const expectedResponse = {canHavePublicPreview: false, reason: 'Not automatically verifiable as "trusted".'};
const expectedLog =
@ -370,7 +372,7 @@ describe('PreviewServerFactory', () => {
it('should respond with error if `getSignificantFilesChanged()` fails', async () => {
bvGetSignificantFilesChangedSpy.and.rejectWith('getSignificantFilesChanged error');
bvGetSignificantFilesChangedSpy.and.callFake(() => Promise.reject('getSignificantFilesChanged error'));
await agent.get(url).expect(500, 'getSignificantFilesChanged error');
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', 'getSignificantFilesChanged error');
@ -378,10 +380,11 @@ describe('PreviewServerFactory', () => {
it('should respond with error if `getPrIsTrusted()` fails', async () => {
bvGetPrIsTrustedSpy.and.throwError('getPrIsTrusted error');
const error = new Error('getPrIsTrusted error');
bvGetPrIsTrustedSpy.and.callFake(() => { throw error; });
await agent.get(url).expect(500, 'getPrIsTrusted error');
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', new Error('getPrIsTrusted error'));
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', error);
});
});
@ -494,7 +497,7 @@ describe('PreviewServerFactory', () => {
// Note it is important to put the `reject` into `and.callFake`;
// If you just `and.returnValue` the rejected promise
// then you get an "unhandled rejection" message in the console.
getGithubInfoSpy.and.rejectWith('Test Error');
getGithubInfoSpy.and.callFake(() => Promise.reject('Test Error'));
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
@ -515,7 +518,7 @@ describe('PreviewServerFactory', () => {
});
it('should fail if the artifact fetch request fails', async () => {
downloadBuildArtifactSpy.and.rejectWith('Test Error');
downloadBuildArtifactSpy.and.callFake(() => Promise.reject('Test Error'));
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
@ -524,7 +527,7 @@ describe('PreviewServerFactory', () => {
});
it('should fail if verifying the PR fails', async () => {
getPrIsTrustedSpy.and.rejectWith('Test Error');
getPrIsTrustedSpy.and.callFake(() => Promise.reject('Test Error'));
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
@ -533,7 +536,7 @@ describe('PreviewServerFactory', () => {
});
it('should fail if creating the preview build fails', async () => {
createBuildSpy.and.rejectWith('Test Error');
createBuildSpy.and.callFake(() => Promise.reject('Test Error'));
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
@ -602,7 +605,7 @@ describe('PreviewServerFactory', () => {
it('should propagate errors from BuildVerifier', async () => {
bvGetPrIsTrustedSpy.and.rejectWith('Test');
bvGetPrIsTrustedSpy.and.callFake(() => Promise.reject('Test'));
await createRequest(+pr).expect(500, 'Test');
@ -612,9 +615,7 @@ describe('PreviewServerFactory', () => {
it('should call \'BuildCreator#updatePrVisibility()\' with the correct arguments', async () => {
bvGetPrIsTrustedSpy.
withArgs(24).and.resolveTo(false).
withArgs(42).and.resolveTo(true);
bvGetPrIsTrustedSpy.and.callFake((pr2: number) => Promise.resolve(pr2 === 42));
await createRequest(24);
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(24, false);
@ -625,7 +626,7 @@ describe('PreviewServerFactory', () => {
it('should propagate errors from BuildCreator', async () => {
bcUpdatePrVisibilitySpy.and.rejectWith('Test');
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject('Test'));
await createRequest(+pr).expect(500, 'Test');
});
@ -633,9 +634,7 @@ describe('PreviewServerFactory', () => {
describe('on success', () => {
it('should respond with 200 (action: undefined)', async () => {
bvGetPrIsTrustedSpy.
withArgs(2).and.resolveTo(false).
withArgs(4).and.resolveTo(true);
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
const reqs = [4, 2].map(num => createRequest(num).expect(200, http.STATUS_CODES[200]));
await Promise.all(reqs);
@ -643,9 +642,7 @@ describe('PreviewServerFactory', () => {
it('should respond with 200 (action: labeled)', async () => {
bvGetPrIsTrustedSpy.
withArgs(2).and.resolveTo(false).
withArgs(4).and.resolveTo(true);
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
const reqs = [4, 2].map(num => createRequest(num, 'labeled').expect(200, http.STATUS_CODES[200]));
await Promise.all(reqs);
@ -653,9 +650,7 @@ describe('PreviewServerFactory', () => {
it('should respond with 200 (action: unlabeled)', async () => {
bvGetPrIsTrustedSpy.
withArgs(2).and.resolveTo(false).
withArgs(4).and.resolveTo(true);
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
const reqs = [4, 2].map(num => createRequest(num, 'unlabeled').expect(200, http.STATUS_CODES[200]));
await Promise.all(reqs);

View File

@ -39,7 +39,7 @@ describe('preview-server/utils', () => {
throwRequestError(505, 'ERROR MESSAGE', request);
} catch (error) {
caught = true;
expect(error).toBeInstanceOf(PreviewServerError);
expect(error).toEqual(jasmine.any(PreviewServerError));
expect(error.status).toEqual(505);
expect(error.message).toEqual(`ERROR MESSAGE in request: POST some.domain.com/path "The request body"`);
}

File diff suppressed because it is too large Load Diff

View File

@ -8,32 +8,10 @@ exitCode=0
# Helpers
function checkCert {
local certPath=$1
if [[ ! -f "$certPath" ]]; then
echo "Certificate '$certPath' does not exist. Skipping expiration check..."
return
fi
openssl x509 -checkend 0 -in "$certPath" -noout > /dev/null
reportStatus "Certificate '$certPath'"
if [[ $? -ne 0 ]]; then
echo " [WARN]"
echo " If you did not provide the certificate explicitly, try running the"
echo " 'docker build' command again with the '--no-cache' option to generate"
echo " a new self-signed certificate."
fi
}
function reportStatus {
local lastExitCode=$?
echo "$1: $([[ $lastExitCode -eq 0 ]] && echo OK || echo NOT OK)"
[[ $lastExitCode -eq 0 ]] || exitCode=1
return $lastExitCode
}
@ -50,16 +28,6 @@ for s in ${services[@]}; do
done
# Check SSL/TLS certificates expiration
certs=(
"$AIO_LOCALCERTS_DIR/$AIO_DOMAIN_NAME.crt"
"$TEST_AIO_LOCALCERTS_DIR/$TEST_AIO_DOMAIN_NAME.crt"
)
for c in ${certs[@]}; do
checkCert $c
done
# Check servers
origins=(
http://$AIO_PREVIEW_SERVER_HOSTNAME:$AIO_PREVIEW_SERVER_PORT

View File

@ -3,7 +3,7 @@
## Create `aio-builds` persistent disk (if not already exists)
- Follow instructions [here](https://cloud.google.com/compute/docs/disks/add-persistent-disk#create_disk).
- `sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-aio-builds`
- `sudo mkfs.ext4 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-aio-builds`
## Mount disk
@ -14,7 +14,7 @@
## Mount disk on boot
- Run:
```sh
echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-aio-builds` \
/mnt/disks/aio-builds ext4 defaults,discard,nofail 0 2 | sudo tee -a /etc/fstab
```
echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-aio-builds` \
/mnt/disks/aio-builds ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab
```

View File

@ -1,11 +1,10 @@
# VM setup - Create docker image
## Install git, Node.js and yarn
- `sudo apt-get update`
- `sudo apt-get install -y git`
- Install the latest stable version of [Node.js](https://nodejs.org/en/download).
- Install the latest stable version of [yarn](https://classic.yarnpkg.com/en/docs/install).
## Install node and yarn
- Install [nvm](https://github.com/creationix/nvm#installation).
- Install node.js: `nvm install 8`
- Install yarn: `npm -g install yarn`
## Checkout repository
@ -17,11 +16,7 @@
- You can overwrite the default environment variables inside the image, by passing new values using
`--build-arg`.
**Note 1:** The script has to execute docker commands with `sudo`.
**Note 2:**
The script has to execute `yarn` commands, so make sure `yarn` is on the `PATH` when invoking the
script.
**Note:** The script has to execute docker commands with `sudo`.
## Example
@ -31,7 +26,7 @@ The following commands would create a docker image from GitHub repo `foo/bar` to
- `git clone https://github.com/foo/bar.git foobar`
- Run:
```sh
```
./foobar/aio-builds-setup/scripts/create-image.sh foobar-builds \
--build-arg AIO_REPO_SLUG=foo/bar \
--build-arg AIO_DOMAIN_NAME=foobar-builds.io \

View File

@ -3,17 +3,24 @@
## Install docker
Official installation instructions: https://docs.docker.com/engine/install
Example:
_Debian (jessie):_
- `sudo apt-get update`
- `sudo apt-get install -y apt-transport-https ca-certificates curl git software-properties-common`
- `curl -fsSL https://apt.dockerproject.org/gpg | sudo apt-key add -`
- `apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D`
- `sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ debian-$(lsb_release -cs) main"`
- `sudo apt-get update`
- `sudo apt-get -y install docker-engine`
_Debian (buster):_
_Ubuntu (16.04):_
- `sudo apt-get update`
- `sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common`
- `curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -`
- `sudo apt-key fingerprint 0EBFCD88`
- `sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"`
- `sudo apt-get install -y curl git linux-image-extra-$(uname -r) linux-image-extra-virtual`
- `sudo apt-get install -y apt-transport-https ca-certificates`
- `curl -fsSL https://yum.dockerproject.org/gpg | sudo apt-key add -`
- `apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D`
- `sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ ubuntu-$(lsb_release -cs) main"`
- `sudo apt-get update`
- `sudo apt-get -y install docker-ce docker-ce-cli containerd.io`
- `sudo apt-get -y install docker-engine`
## Start the docker

View File

@ -8,16 +8,16 @@ VM host to update the preview server based on changes in the source code.
The script will pull the latest changes from the origin's master branch and examine if there have
been any changes in files inside the preview server source code directory (see below). If there are,
it will create a new image and verify that it works as expected. Finally, it will stop and remove
it will create a new image and verify that is works as expected. Finally, it will stop and remove
the old docker container and image, create a new container based on the new image and start it.
The script assumes that the preview server source code is in the repository's
`aio/aio-builds-setup/` directory and expects the following inputs:
- **$1**: `HOST_REPO_DIR`
- **$2**: `HOST_SECRETS_DIR`
- **$3**: `HOST_BUILDS_DIR`
- **$4**: `HOST_LOCALCERTS_DIR`
- **$2**: `HOST_LOCALCERTS_DIR`
- **$3**: `HOST_SECRETS_DIR`
- **$4**: `HOST_BUILDS_DIR`
- **$5**: `HOST_LOGS_DIR`
See [here](vm-setup--create-host-dirs-and-files.md) for more info on what each input directory is
@ -25,38 +25,28 @@ used for.
**Note 1:** The script has to execute docker commands with `sudo`.
**Note 2:**
The script has to execute `yarn` commands, so make sure `yarn` is on the `PATH` when invoking the
script.
**Note 3:** Make sure the user that executes the script has access to update the repository.
**Note 2:** Make sure the user that executes the script has access to update the repository
## Run the script manually
You may choose to manually run the script, when necessary. Example:
```sh
```
update-preview-server.sh \
/path/to/repo \
/path/to/localcerts \
/path/to/secrets \
/path/to/builds \
/path/to/localcerts \
/path/to/logs
```
## Run the script automatically
You may choose to automatically trigger the script, e.g. using a cronjob. For example, the following
cronjob entry would run the script every 30 minutes, update the preview server (if necessary) and
log its output to `update-preview-server.log` (assuming the user has the necessary permissions):
cronjob entry would run the script every hour and update the preview server (assuming the user has
the necessary permissions):
```
# Periodically check for changes and update the preview server (if necessary)
*/30 * * * * /path/to/update-preview-server.sh /path/to/repo /path/to/secrets /path/to/builds /path/to/localcerts /path/to/logs >> /path/to/update-preview-server.log 2>&1
*/30 * * * * /path/to/update-preview-server.sh /path/to/repo /path/to/localcerts /path/to/secrets /path/to/builds /path/to/logs
```
**Note:**
Keep in mind that cron jobs run in non-interactive, non-login shells. This means that the execution
context might be different compared to when running the same commands from an interactive, login
shell. For example, `.bashrc` files are normally _not_ sourced automatically in cron jobs. See
[here](http://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html) for more info.

View File

@ -7,14 +7,13 @@ echo -e "\n\n[`date`] - Updating the preview server..."
# Input
readonly HOST_REPO_DIR=$1
readonly HOST_SECRETS_DIR=$2
readonly HOST_BUILDS_DIR=$3
readonly HOST_LOCALCERTS_DIR=$4
readonly HOST_LOCALCERTS_DIR=$2
readonly HOST_SECRETS_DIR=$3
readonly HOST_BUILDS_DIR=$4
readonly HOST_LOGS_DIR=$5
# Constants
readonly PROVISIONAL_TAG=provisional
readonly PROVISIONAL_IMAGE_NAME=aio-builds:$PROVISIONAL_TAG
readonly PROVISIONAL_IMAGE_NAME=aio-builds:provisional
readonly LATEST_IMAGE_NAME=aio-builds:latest
readonly CONTAINER_NAME=aio
@ -31,7 +30,7 @@ readonly CONTAINER_NAME=aio
# Do not update the server unless files inside `aio-builds-setup/` have changed
# or the last attempt failed (identified by the provisional image still being around).
readonly relevantChangedFilesCount=$(git diff --name-only $lastDeployedCommit...HEAD | grep -P "^aio/aio-builds-setup/" | wc -l)
readonly lastAttemptFailed=$(sudo docker image ls | grep "$PROVISIONAL_TAG" >> /dev/fd/3 && echo "true" || echo "false")
readonly lastAttemptFailed=$(sudo docker rmi "$PROVISIONAL_IMAGE_NAME" >> /dev/fd/3 && echo "true" || echo "false")
if [[ $relevantChangedFilesCount -eq 0 ]] && [[ "$lastAttemptFailed" != "true" ]]; then
echo "Skipping update because no relevant files have been touched."
exit 0
@ -61,9 +60,9 @@ readonly CONTAINER_NAME=aio
--publish 80:80 \
--publish 443:443 \
--restart unless-stopped \
--volume $HOST_LOCALCERTS_DIR:/etc/ssl/localcerts:ro \
--volume $HOST_SECRETS_DIR:/aio-secrets:ro \
--volume $HOST_BUILDS_DIR:/var/www/aio-builds \
--volume $HOST_LOCALCERTS_DIR:/etc/ssl/localcerts:ro \
--volume $HOST_LOGS_DIR:/var/log/aio \
"$LATEST_IMAGE_NAME"

View File

@ -5,8 +5,7 @@
"packageManager": "yarn",
"warnings": {
"typescriptMismatch": false
},
"analytics": false
}
},
"newProjectRoot": "projects",
"projects": {
@ -58,15 +57,9 @@
}
],
"styles": [
"src/styles/main.scss"
"src/styles.scss"
],
"scripts": [],
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
]
"scripts": []
},
"configurations": {
"fast": {
@ -98,9 +91,6 @@
}
],
"serviceWorker": true
},
"ci": {
"progress": false
}
}
},
@ -123,7 +113,7 @@
"browserTarget": "site:build:archive"
},
"ci": {
"browserTarget": "site:build:ci"
"progress": false
}
}
},
@ -158,7 +148,7 @@
}
],
"styles": [
"src/styles/main.scss"
"src/styles.scss"
],
"scripts": []
}

View File

@ -1,13 +1,13 @@
# CLI Overview and Command Reference
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell.
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).
## Installing Angular CLI
Major versions of Angular CLI follow the supported major version of Angular, but minor versions can be released separately.
Install the CLI using the `npm` package manager:
<code-example language="bash">
<code-example format="." language="bash">
npm install -g @angular/cli
</code-example>
@ -20,14 +20,14 @@ Invoke the tool on the command line through the `ng` executable.
Online help is available on the command line.
Enter the following to list commands or options for a given command (such as [generate](cli/generate)) with a short description.
<code-example language="bash">
<code-example format="." language="bash">
ng help
ng generate --help
</code-example>
To create, build, and serve a new, basic Angular project on a development server, go to the parent directory of your new workspace use the following commands:
<code-example language="bash">
<code-example format="." language="bash">
ng new my-first-project
cd my-first-project
ng serve
@ -36,14 +36,6 @@ ng serve
In your browser, open http://localhost:4200/ to see the new app run.
When you use the [ng serve](cli/serve) command to build an app and serve it locally, the server automatically rebuilds the app and reloads the page when you change any of the source files.
<div class="alert is-helpful">
When you run `ng new my-first-project` a new folder, named `my-first-project`, will be created in the current working directory. Since you want to be able to create files inside that folder, make sure you have sufficient rights in the current working directory before running the command.
If the current working directory is not the right place for your project, you can change to a more appropriate directory by running `cd <path-to-other-directory>` first.
</div>
## Workspaces and project files
The [ng new](cli/new) command creates an *Angular workspace* folder and generates a new app skeleton.
@ -82,8 +74,8 @@ Command syntax is shown as follows:
* Option names are prefixed with a double dash (--).
Option aliases are prefixed with a single dash (-).
Arguments are not prefixed.
For example:
<code-example language="bash">
For example:
<code-example format="." language="bash">
ng build my-app -c production
</code-example>
@ -109,3 +101,9 @@ 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.
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.
### 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).

View File

@ -18,7 +18,6 @@
**/src/karma.conf.js
**/.angular-cli.json
**/.editorconfig
**/.gitignore
**/angular.json
**/tsconfig.json
**/bs-config.e2e.json
@ -83,6 +82,9 @@ upgrade-phonecat-2-hybrid/aot/**/*
# styleguide
!styleguide/src/systemjs.custom.js
# universal
!universal/webpack.server.config.js
# stackblitz
*stackblitz.no-link.html
@ -95,4 +97,4 @@ upgrade-phonecat-3-final/rollup-config.js
!upgrade-phonecat-*/**/karma-test-shim.js
# schematics
!schematics-for-libraries/projects/my-lib/package.json
!schematics-for-libraries/projects/my-lib/package.json

View File

@ -1,19 +0,0 @@
import { browser, element, by } from 'protractor';
describe('Accessibility example e2e tests', () => {
beforeEach(() => {
browser.get('');
});
it('should display Accessibility Example', () => {
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
});
it('should take a number and change progressbar width', () => {
element(by.css('input')).sendKeys('16');
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
});
});

View File

@ -1,13 +0,0 @@
<h1>Accessibility Example</h1>
<!-- #docregion template -->
<label>
Enter an example progress value
<input type="number" min="0" max="100"
[value]="progress" (input)="progress = $event.target.value">
</label>
<!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->
<app-example-progressbar [value]="progress" aria-label="Example of a progress bar">
</app-example-progressbar>
<!-- #enddocregion template -->

View File

@ -1,10 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
progress = 0;
}

Some files were not shown because too many files have changed in this diff Show More