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(); }); }); });