Skip to content
Open
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
10 changes: 10 additions & 0 deletions packages/angular/cli/src/commands/update/schematic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,16 @@ export default function (options: UpdateSchema): Rule {
registry: options.registry,
usingYarn,
verbose: options.verbose,
}).catch((error: unknown) => {
// If the package cannot be fetched (e.g. private registry, JSR, AWS CodeArtifact,
// or local workspace packages), return a partial object so the reduce below can
// decide whether to warn or hard-fail based on whether it was explicitly requested.
const message = (error as { message?: string }).message ?? String(error);
logger.warn(
`Package '${depName}' could not be fetched from the registry: ${message}`,
);

return { requestedName: depName } as Partial<NpmRepositoryPackageJson>;
}),
),
);
Expand Down
47 changes: 47 additions & 0 deletions packages/angular/cli/src/commands/update/schematic/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,53 @@ describe('@schematics/update', () => {
expect(resultTreeContent.endsWith('}')).toBeTrue();
});

it('continues updating others when one package fetch fails', async () => {
// Regression test for https://github.com/angular/angular-cli/issues/28834
// Packages from private registries, JSR, AWS CodeArtifact, or local workspaces
// may resolve as npm-registry packages (pass isPkgFromRegistry) but fail to fetch
// with a 404. The schematic should warn and skip them rather than hard-failing,
// and other explicitly-requested packages should still be updated.
const inputTree = new UnitTestTree(
new HostTree(
new virtualFs.test.TestHost({
'/package.json': JSON.stringify({
name: 'blah',
dependencies: {
// A real package that should be updated:
'@angular-devkit-tests/update-base': '1.0.0',
// A scoped package that does not exist on the npm registry (simulates a
// private / JSR / CodeArtifact package that passes the registry specifier
// check but returns a 404 when fetched):
'@private-nonexistent/package-ng-update-issue-28834': '1.0.0',
},
}),
}),
),
);

const messages: string[] = [];
schematicRunner.logger.subscribe((x) => messages.push(x.message));

// Should NOT throw even though one package cannot be fetched.
const resultTree = await schematicRunner.runSchematic(
'update',
{ packages: ['@angular-devkit-tests/update-base'] },
inputTree,
);

// The unfetchable package should produce a warning.
expect(
messages.some((m) => m.includes('@private-nonexistent/package-ng-update-issue-28834')),
).toBeTrue();

// The valid package should have been updated despite the other package failing.
const { dependencies } = resultTree.readJson('/package.json') as {
dependencies: Record<string, string>;
};
expect(dependencies['@angular-devkit-tests/update-base']).toBe('1.1.0');
expect(dependencies['@private-nonexistent/package-ng-update-issue-28834']).toBe('1.0.0');
}, 45000);

it('updates group members to the same version as the targeted package', async () => {
const packageJsonContent = `{
"name": "test",
Expand Down
Loading