Skip to content

feat: ng-add with Angular 14 #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![GitHub Actions](https://github.com/angular-schule/angular-cli-ghpages/actions/workflows/main.yml/badge.svg)](https://github.com/angular-schule/angular-cli-ghpages/actions/workflows/main.yml)
[![The MIT License](https://img.shields.io/badge/license-MIT-orange.svg?color=blue&style=flat-square)](http://opensource.org/licenses/MIT)

**Deploy your Angular app to GitHub pages directly from the Angular CLI! 🚀**
**Deploy your Angular app to GitHub Pages or any other Git repo directly from the Angular CLI! 🚀**

![Screenshot](docs/img/angular-cli-ghpages-deploy.gif)

Expand All @@ -14,8 +14,9 @@
1. [📖 Changelog](#changelog)
2. [⚠️ Prerequisites](#prerequisites)
3. [🚀 Quick Start (local development)](#quickstart-local)
4. [🚀 Continuous Delivery](#continuous-delivery)
5. [📦 Options](#options)
4. [⚙️ Installation](#installation)
5. [🚀 Continuous Delivery](#continuous-delivery)
6. [📦 Deployment Options](#options)
- [--base-href](#base-href)
- [--build-target](#build-target)
- [--no-build](#no-build)
Expand All @@ -27,9 +28,9 @@
- [--no-dotfiles](#no-dotfiles)
- [--cname](#cname)
- [--dry-run](#dry-run)
6. [📁 Configuration File](#configuration-file)
7. [🌍 Environments](#environments)
8. [⁉️ FAQ](#faq)
7. [📁 Configuration File](#configuration-file)
8. [🌍 Environments](#environments)
9. [⁉️ FAQ](#faq)

<hr>

Expand Down Expand Up @@ -59,20 +60,16 @@ If you use the old syntax, you will probably receive the following error:

<br>

**🐙 GitHub Actions** is now properly supported alongside Travis CI and CircleCi. The token `GITHUB_TOKEN` is also supported. Learn everything you need to know in the following article.
**🐙 GitHub Actions** is now properly supported alongside Travis CI and CircleCi. The token `GITHUB_TOKEN` is also supported. Learn everything you need to know in the following article:

[![Banner](https://angular-schule.github.io/website-articles/blog/2020-01-everything-github/everything-github.png)](https://angular.schule/blog/2020-01-everything-github)

**Everything GitHub: Continuous Integration, Deployment and Hosting for your Angular App**

In this article we show several tools from the GitHub universe to launch a website with Angular. We will establish a professional pipeline, including version management, continuous deployment and web hosting. Best of all, for public repositories, this will not cost you a single cent! [Read more...](https://angular.schule/blog/2020-01-everything-github)
**[Everything GitHub: Continuous Integration, Deployment and Hosting for your Angular App](https://angular.schule/blog/2020-01-everything-github)**

## ⚠️ Prerequisites <a name="prerequisites"></a>

This command has the following prerequisites:

- Git 1.9 or higher (execute `git --version` to check your version)
- Angular project created via [Angular CLI](https://github.com/angular/angular-cli) v9.0.0 or greater (execute `ng update` to upgrade your project if necessary)
- Angular project created via [Angular CLI](https://github.com/angular/angular-cli) v9.0.0 or greater
- older Angular projects can still use the standalone program. See the documentation at [README_standalone](https://github.com/angular-schule/angular-cli-ghpages/blob/master/docs/README_standalone.md).

## 🚀 Quick Start (local development) <a name="quickstart-local"></a>
Expand Down Expand Up @@ -103,7 +100,7 @@ If you already have an existing Angular project on GitHub, skip step 1 and 2.
- Please enter the URL `https://github.com/<username>/<repositoryname>.git` into your browser – you should see your existing repository on GitHub.
- Please double-check that you have the necessary rights to make changes to the given project!

3. Add `angular-cli-ghpages` to your project.
3. Add `angular-cli-ghpages` to your project. For details, see the [installation section](#installation).

```sh
ng add angular-cli-ghpages
Expand All @@ -127,6 +124,24 @@ If you already have an existing Angular project on GitHub, skip step 1 and 2.
5. Your project should be available at `https://<username>.github.io/<repositoryname>`.
Learn more about GitHub pages on the [official website](https://pages.github.com/).

## ⚙️ Installation <a name="installation"></a>

`angular-cli-ghpages` can be installed via `ng add`.
This will install the NPM package and add the necessary `deploy` configuration to your `angular.json` file.

```sh
ng add angular-cli-ghpages
```

The `deploy` config will be added for the specified `defaultProject`.
If there is no `defaultProject` set and there is only one project in your workspace, this project will be used.

If you have multiple projects in one workspace, you can manually define the project name:

```sh
ng add angular-cli-ghpages --project MYPROJECTNAME
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For later, it would be cool if we would have an interactive choice during installation.

```

## 🚀 Continuous Delivery <a name="continuous-delivery"></a>

If you run this command from a CI/CD environment, the deployment will most likely not work out of the box.
Expand Down Expand Up @@ -159,7 +174,7 @@ ng deploy --repo=https://github.com/<username>/<repositoryname>.git --name="Your
>
> The `GITHUB_TOKEN` (installation access token) will only trigger a release of a new website if the action runs in a private repository. In a public repo, a commit is generated, but the site does not change. See this [GitHub Community post](https://github.community/t5/GitHub-Actions/Github-action-not-triggering-gh-pages-upon-push/m-p/26869) for more info. If your repo is public, you must still use the `GH_TOKEN` (personal access token).

## 📦 Options <a name="options"></a>
## 📦 Deployment Options <a name="options"></a>

#### --base-href <a name="base-href"></a>

Expand Down
2 changes: 2 additions & 0 deletions docs/README_contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ Once you have completed the previous steps to `npm link` the local copy of `angu

```sh
ng add angular-cli-ghpages
# OR alternatively
ng generate angular-cli-ghpages:ng-add
```

4. You can now deploy your angular app to GitHub pages.
Expand Down
2 changes: 0 additions & 2 deletions src/__snapshots__/ng-add.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
exports[`ng-add generating files generates new files if starting from scratch 1`] = `
"{
\\"version\\": 1,
\\"defaultProject\\": \\"THEPROJECT\\",
\\"projects\\": {
\\"THEPROJECT\\": {
\\"projectType\\": \\"application\\",
Expand Down Expand Up @@ -37,7 +36,6 @@ exports[`ng-add generating files generates new files if starting from scratch 1`
exports[`ng-add generating files overrides existing files 1`] = `
"{
\\"version\\": 1,
\\"defaultProject\\": \\"THEPROJECT\\",
\\"projects\\": {
\\"THEPROJECT\\": {
\\"projectType\\": \\"application\\",
Expand Down
7 changes: 6 additions & 1 deletion src/ng-add-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
"$id": "angular-cli-ghpages-ng-add-schematic",
"title": "angular-cli-ghpages ng-add schematic",
"type": "object",
"properties": {},
"properties": {
"project": {
"type": "string",
"description": "The project for which the deploy config should be added"
}
},
"required": [],
"additionalProperties": false
}
85 changes: 66 additions & 19 deletions src/ng-add.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,77 @@ describe('ng-add', () => {
});
});

describe('project selection', () => {
it('should select the default project when not explicitly given (for compatibility!)', async () => {
const tree = Tree.empty();
const angularJSON = generateAngularJson();

(angularJSON as any).defaultProject = PROJECT_NAME; // explicitly set default project
tree.create('angular.json', JSON.stringify(angularJSON));

const resultTree = await ngAdd({ project: '' })(
tree,
{} as SchematicContext
);

const resultConfig = readJSONFromTree(resultTree, 'angular.json');
expect(resultConfig.projects[PROJECT_NAME].architect.deploy).toBeTruthy();
expect(
resultConfig.projects[OTHER_PROJECT_NAME].architect.deploy
).toBeFalsy();
});

it('should select the explicitly defined project', async () => {
const tree = Tree.empty();
const angularJSON = generateAngularJson();
tree.create('angular.json', JSON.stringify(angularJSON));

const resultTree = await ngAdd({ project: OTHER_PROJECT_NAME })(
tree,
{} as SchematicContext
);

const resultConfig = readJSONFromTree(resultTree, 'angular.json');
expect(
resultConfig.projects[OTHER_PROJECT_NAME].architect.deploy
).toBeTruthy();
expect(resultConfig.projects[PROJECT_NAME].architect.deploy).toBeFalsy();
});

it('should select the first project if there is only one', async () => {
const tree = Tree.empty();
const angularJSON = generateAngularJson();
delete (angularJSON as any).projects[PROJECT_NAME]; // delete one project so that one is left
tree.create('angular.json', JSON.stringify(angularJSON));

const resultTree = await ngAdd({ project: '' })(
tree,
{} as SchematicContext
);

const resultConfig = readJSONFromTree(resultTree, 'angular.json');
expect(
resultConfig.projects[OTHER_PROJECT_NAME].architect.deploy
).toBeTruthy();
});
});

describe('error handling', () => {
it('should fail if project not defined', async () => {
it('should fail if there are multiple projects in workspace and project is not explicitly defined', async () => {
const tree = Tree.empty();
const angularJSON = generateAngularJson();
delete angularJSON.defaultProject;
tree.create('angular.json', JSON.stringify(angularJSON));

await expect(
ngAdd({
project: ''
})(tree, {} as SchematicContext)
ngAdd({ project: '' })(tree, {} as SchematicContext)
).rejects.toThrowError(
'No Angular project selected and no default project in the workspace'
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
);
});

it('should throw if angular.json not found', async () => {
await expect(
ngAdd({
project: PROJECT_NAME
})(Tree.empty(), {} as SchematicContext)
ngAdd({ project: PROJECT_NAME })(Tree.empty(), {} as SchematicContext)
).rejects.toThrowError('Unable to determine format for workspace path.');
});

Expand All @@ -68,9 +118,7 @@ describe('ng-add', () => {
tree.create('angular.json', 'hi');

await expect(
ngAdd({
project: PROJECT_NAME
})(tree, {} as SchematicContext)
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
).rejects.toThrowError('Invalid JSON character: "h" at 0:0.');
});

Expand All @@ -79,9 +127,7 @@ describe('ng-add', () => {
tree.create('angular.json', JSON.stringify({ version: 1, projects: {} }));

await expect(
ngAdd({
project: PROJECT_NAME
})(tree, {} as SchematicContext)
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
).rejects.toThrowError(
'The specified Angular project is not defined in this workspace'
);
Expand All @@ -98,9 +144,7 @@ describe('ng-add', () => {
);

await expect(
ngAdd({
project: PROJECT_NAME
})(tree, {} as SchematicContext)
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
).rejects.toThrowError(
'Deploy requires an Angular project type of "application" in angular.json'
);
Expand Down Expand Up @@ -131,10 +175,13 @@ function prettifyJSON(json: string) {
return JSON.stringify(JSON.parse(json), null, 2);
}

function readJSONFromTree(tree: Tree, file: string) {
return JSON.parse(tree.read(file)!.toString());
}

function generateAngularJson() {
return {
version: 1,
defaultProject: PROJECT_NAME as string | undefined,
projects: {
[PROJECT_NAME]: {
projectType: 'application',
Expand Down
6 changes: 5 additions & 1 deletion src/ng-add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ export const ngAdd = (options: NgAddOptions) => async (
const { workspace } = await workspaces.readWorkspace('/', host);

if (!options.project) {
// TODO: defaultProject is deprecated as for Angular 14. Remove support here when officially removed from Angular.
if (workspace.extensions.defaultProject) {
options.project = workspace.extensions.defaultProject as string;
} else if (workspace.projects.size === 1) {
// If there is only one project, return that one.
options.project = Array.from(workspace.projects.keys())[0];
} else {
throw new SchematicsException(
'No Angular project selected and no default project in the workspace'
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
);
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
},
"homepage": "https://github.com/angular-schule/angular-cli-ghpages/#readme",
"devDependencies": {
"@angular-devkit/architect": ">= 0.900 < 0.1400",
"@angular-devkit/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0",
"@angular-devkit/schematics": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0",
"@angular-devkit/architect": ">= 0.900 < 0.1500",
"@angular-devkit/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
"@angular-devkit/schematics": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
"@types/fs-extra": "^9.0.4",
"@types/jest": "^26.0.15",
"@types/node": "^14.14.7",
Expand All @@ -69,9 +69,9 @@
"typescript": ">=4.0.0 <4.1.0"
},
"peerDependencies": {
"@angular-devkit/architect": ">= 0.900 < 0.1400",
"@angular-devkit/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0",
"@angular-devkit/schematics": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0"
"@angular-devkit/architect": ">= 0.900 < 0.1500",
"@angular-devkit/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
"@angular-devkit/schematics": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0"
},
"dependencies": {
"commander": "^3.0.0-0",
Expand Down