diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ac42c4e..3845c3f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -2,7 +2,10 @@ name: Build and test
on:
push:
- branches: [main, big-update]
+ branches: [main]
+ pull_request:
+ branches: [main]
+ workflow_dispatch:
jobs:
build-and-test:
@@ -124,3 +127,16 @@ jobs:
npx ng deploy
cd /tmp/remote-21.git && git branch | grep gh-pages
echo "Angular 21: build + deploy successful"
+
+ - name: Test Angular 22
+ run: |
+ cd /tmp
+ git init --bare remote-22.git
+ npx @angular/cli@22 new test-app-22 --defaults
+ cd test-app-22
+ git remote add origin /tmp/remote-22.git
+ npm link angular-cli-ghpages
+ npx ng add angular-cli-ghpages
+ npx ng deploy
+ cd /tmp/remote-22.git && git branch | grep gh-pages
+ echo "Angular 22: build + deploy successful"
diff --git a/README.md b/README.md
index 97408ca..d7cff71 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@
A detailed changelog is available in the [releases](https://github.com/angular-schule/angular-cli-ghpages/releases) section.
-`angular-cli-ghpages` v3 supports Angular 18 to 21.
+`angular-cli-ghpages` v3 supports Angular 18 to 22.
For previous versions of Angular, use v1 or v2.
## ⚠️ Prerequisites
diff --git a/src/package.json b/src/package.json
index 759a74b..63973d1 100644
--- a/src/package.json
+++ b/src/package.json
@@ -1,11 +1,11 @@
{
"name": "angular-cli-ghpages",
- "version": "3.0.3",
+ "version": "3.1.0",
"description": "Deploy your Angular app to GitHub Pages or Cloudflare Pages directly from the Angular CLI (ng deploy)",
"main": "index.js",
"types": "index.d.ts",
"engines": {
- "node": ">=18.0.0",
+ "node": ">=18.19.1",
"npm": ">=9.0.0"
},
"bin": {
@@ -71,12 +71,12 @@
"typescript": "~5.2.2"
},
"dependencies": {
- "@angular-devkit/architect": ">=0.1800.0 <0.2200.0",
- "@angular-devkit/core": ">=18.0.0 <22.0.0",
- "@angular-devkit/schematics": ">=18.0.0 <22.0.0",
+ "@angular-devkit/architect": ">=0.1800.0 <0.2300.0",
+ "@angular-devkit/core": ">=18.0.0 <23.0.0",
+ "@angular-devkit/schematics": ">=18.0.0 <23.0.0",
"gh-pages": "6.3.0"
},
"peerDependencies": {
- "@angular/cli": ">=18.0.0 <22.0.0"
+ "@angular/cli": ">=18.0.0 <23.0.0"
}
}
diff --git a/src/test-fixtures/angular-22.json b/src/test-fixtures/angular-22.json
new file mode 100644
index 0000000..8b6a50d
--- /dev/null
+++ b/src/test-fixtures/angular-22.json
@@ -0,0 +1,73 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "cli": {
+ "packageManager": "npm"
+ },
+ "newProjectRoot": "projects",
+ "projects": {
+ "ng22": {
+ "projectType": "application",
+ "schematics": {},
+ "root": "",
+ "sourceRoot": "src",
+ "prefix": "app",
+ "architect": {
+ "build": {
+ "builder": "@angular/build:application",
+ "options": {
+ "browser": "src/main.ts",
+ "tsConfig": "tsconfig.app.json",
+ "assets": [
+ {
+ "glob": "**/*",
+ "input": "public"
+ }
+ ],
+ "styles": [
+ "src/styles.css"
+ ]
+ },
+ "configurations": {
+ "production": {
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "500kB",
+ "maximumError": "1MB"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "4kB",
+ "maximumError": "8kB"
+ }
+ ],
+ "outputHashing": "all"
+ },
+ "development": {
+ "optimization": false,
+ "extractLicenses": false,
+ "sourceMap": true
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "builder": "@angular/build:dev-server",
+ "configurations": {
+ "production": {
+ "buildTarget": "ng22:build:production"
+ },
+ "development": {
+ "buildTarget": "ng22:build:development"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "test": {
+ "builder": "@angular/build:unit-test"
+ }
+ }
+ }
+ }
+}
diff --git a/src/test-fixtures/angular-versions.spec.ts b/src/test-fixtures/angular-versions.spec.ts
index 99e58c3..fda4b23 100644
--- a/src/test-fixtures/angular-versions.spec.ts
+++ b/src/test-fixtures/angular-versions.spec.ts
@@ -7,7 +7,7 @@
*
* Key difference relevant to us:
* - Angular 18-19: outputPath is a string like "dist/"
- * - Angular 20-21: outputPath is MISSING (uses default dist/)
+ * - Angular 20-22: outputPath is MISSING (uses default dist/)
*/
import { SchematicContext, Tree } from '@angular-devkit/schematics';
@@ -34,6 +34,7 @@ const angular18Config = JSON.parse(fs.readFileSync(path.join(fixturesDir, 'angul
const angular19Config = JSON.parse(fs.readFileSync(path.join(fixturesDir, 'angular-19.json'), 'utf-8'));
const angular20Config = JSON.parse(fs.readFileSync(path.join(fixturesDir, 'angular-20.json'), 'utf-8'));
const angular21Config = JSON.parse(fs.readFileSync(path.join(fixturesDir, 'angular-21.json'), 'utf-8'));
+const angular22Config = JSON.parse(fs.readFileSync(path.join(fixturesDir, 'angular-22.json'), 'utf-8'));
describe('Angular Version Compatibility', () => {
describe('Angular 18', () => {
@@ -104,12 +105,30 @@ describe('Angular Version Compatibility', () => {
});
});
+ describe('Angular 22', () => {
+ it('has NO outputPath (uses default)', () => {
+ const options = angular22Config.projects.ng22.architect.build.options;
+ expect(options.outputPath).toBeUndefined();
+ });
+
+ it('ng add succeeds despite missing outputPath', async () => {
+ const tree = Tree.empty();
+ tree.create('angular.json', JSON.stringify(angular22Config));
+
+ const result = await ngAdd({ project: 'ng22' })(tree, mockContext);
+ const resultConfig = JSON.parse(result.read('angular.json')!.toString());
+
+ expect(resultConfig.projects.ng22.architect.deploy.builder).toBe('angular-cli-ghpages:deploy');
+ });
+ });
+
describe('Cross-version compatibility', () => {
it('all versions have projectType: application', () => {
expect(angular18Config.projects.ng18.projectType).toBe('application');
expect(angular19Config.projects.ng19.projectType).toBe('application');
expect(angular20Config.projects.ng20.projectType).toBe('application');
expect(angular21Config.projects.ng21.projectType).toBe('application');
+ expect(angular22Config.projects.ng22.projectType).toBe('application');
});
it('all versions have build target', () => {
@@ -117,13 +136,15 @@ describe('Angular Version Compatibility', () => {
expect(angular19Config.projects.ng19.architect.build).toBeDefined();
expect(angular20Config.projects.ng20.architect.build).toBeDefined();
expect(angular21Config.projects.ng21.architect.build).toBeDefined();
+ expect(angular22Config.projects.ng22.architect.build).toBeDefined();
});
- it('outputPath evolution: string → string → undefined → undefined', () => {
+ it('outputPath evolution: string → string → undefined → undefined → undefined', () => {
expect(typeof angular18Config.projects.ng18.architect.build.options.outputPath).toBe('string');
expect(typeof angular19Config.projects.ng19.architect.build.options.outputPath).toBe('string');
expect(angular20Config.projects.ng20.architect.build.options.outputPath).toBeUndefined();
expect(angular21Config.projects.ng21.architect.build.options.outputPath).toBeUndefined();
+ expect(angular22Config.projects.ng22.architect.build.options.outputPath).toBeUndefined();
});
});
});