Keeping angular apps up to date and vulnerability free

Laimonas Simutis
6 min readNov 10, 2023

--

When you have been writing code for as long as I have, you start to stick to certain patterns and use templates for new projects to make sticking to the pattern easier.

I have been cranking out a few angular/dotnetcore apps over the last few years and I wanted to share some parts of my setup that I think are very useful and help me write better apps.

The bit I will talk about here is how I keep the angular apps up to date with latest features, and more importantly, security updates. The key component of it is having a shell script to bootstrap my project whenever I need to write code. This script, before running the hot reload aspects and setting environment up, checks for angular updates and gives an option to apply them.

Console screen showing which angular updates are available when starting your app development
Keep your apps up to date

Automated check and application sounds like such an easy and simple thing, but it has been a big time saver and overall has streamlined angular update process for me.

Angular updates as part of your development process

I do use windows and thus bat and powershell files for scripting. But what I am about to show next could easily be adopted to Macs and unix style shell scripts.

So first, let’s see this script in action and then you can see the full script.

When I start my day and want to start working on a project, I open the IDE and at the same time run dev.bat script that sets up and kicks off hot reload type environment for me. But it also, before it does anything else, checks for angular updates.

I will use a real world scenario and a project I am currently working on. Just yesterday I coded on it and there were no angular updates, but this morning when I kicked it off, here is what I saw:

PS D:\programming\stock-analysis> .\dev.bat
The following updates are available:
@angular-eslint/schematics 17.0.0 -> 17.0.1 ng update @angular-eslint/schematics
@angular/core 17.0.0 -> 17.0.2 ng update @angular/core
Continue? (y/n)

How cool is that? You start a new day, open your laptop, boot the app with dev.bat and you are automatically informed that there is an update available. You can choose to update it right now or say no and come back to it later, in case you are in a rush to work or fix a bug, etc.

Now, what happens if you choose to continue? Here is what the script does:

  • executes ng update for each package at a time
  • after each update creates a git commit stating that angular package was updated
  • if error occurs during the update, the script bails

How neat is that? Updates done, commits done, you can now proceed with your app development.

Here is the full output from this morning’s run:

PS D:\programming\stock-analysis> .\dev.bat
The following updates are available:
@angular-eslint/schematics 17.0.0 -> 17.0.1 ng update @angular-eslint/schematics
@angular/core 17.0.0 -> 17.0.2 ng update @angular/core
Continue? (y/n)
y
Applying update: @angular-eslint/schematics
Using package manager: npm
Collecting installed dependencies...
Found 53 dependencies.
Fetching dependency metadata from registry...
Updating package.json with dependency @angular-eslint/builder @ "17.0.1" (was "17.0.0")...
Updating package.json with dependency @angular-eslint/eslint-plugin @ "17.0.1" (was "17.0.0")...
Updating package.json with dependency @angular-eslint/eslint-plugin-template @ "17.0.1" (was "17.0.0")...
Updating package.json with dependency @angular-eslint/schematics @ "17.0.1" (was "17.0.0")...
Updating package.json with dependency @angular-eslint/template-parser @ "17.0.1" (was "17.0.0")...
UPDATE package.json (2263 bytes)
✔ Packages successfully installed.
warning: in the working copy of 'src/web/ClientApp/package-lock.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/web/ClientApp/package.json', LF will be replaced by CRLF the next time Git touches it
[main 816ede23] Angular updates: @angular-eslint/schematics
2 files changed, 39 insertions(+), 39 deletions(-)
Applying update: @angular/core
Using package manager: npm
Collecting installed dependencies...
Found 53 dependencies.
Fetching dependency metadata from registry...
Updating package.json with dependency @angular/compiler-cli @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/language-service @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/animations @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/common @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/compiler @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/core @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/forms @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/platform-browser @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/platform-browser-dynamic @ "17.0.2" (was "17.0.0")...
Updating package.json with dependency @angular/router @ "17.0.2" (was "17.0.0")...
UPDATE package.json (2263 bytes)
✔ Packages successfully installed.
warning: in the working copy of 'src/web/ClientApp/package-lock.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/web/ClientApp/package.json', LF will be replaced by CRLF the next time Git touches it
[main 6a447fed] Angular updates: @angular/core
2 files changed, 67 insertions(+), 67 deletions(-)

In this particular case, there were two packages available for updates, angular-eslint/schematics and angular/core. Once I choose to continue, the script goes one by one and applies updates. You can see the update being applied, and then also can observe git commits in action as well.

The script also bails if there are pending commits in the repository. Thus making sure you have a clean history and your unrelated changes do not get lumped with angular update changes. Here is an example of the output where in my project I have made some code changes and angular update was attempted:

PS D:\programming\stock-analysis> .\dev.bat
The following updates are available:
@angular-eslint/schematics 17.0.0 -> 17.0.1 ng update @angular-eslint/schematics
@angular/core 17.0.0 -> 17.0.2 ng update @angular/core
Continue? (y/n)
y
There are uncommitted changes in git. Please commit or stash them and try again.
Git status:
M src/web/BackgroundServices/WeeklyUpsideReversalService.css

It tells you that hey, you have some pending changes that you might want to commit first. Or stash. Either way, take care of this before the update is run.

Full Script

Finally, here is the full PowerShell script that I use:

# store current directory that I can back to
$scriptPath = $MyInvocation.MyCommand.Path | Split-Path

# change directory to where your angular web app is located
Set-Location src/web/ClientApp

# get list of packages that need updating
$updates = ng update | Where-Object { $_.Contains("@angular")}

# if there are no updates available, tell that and exit
if ($updates.Count -eq 0) {
Write-Host "No updates available"
exit
}

# ask if to continue
Write-Host "The following updates are available:"
$updates | ForEach-Object { Write-Host $_ }
Write-Host "Continue? (y/n)"
$answer = Read-Host

# if answer is not y, exit
if ($answer -ne "y") {
exit
}

# check if there are any git changes, and if there are, report them and exit
$gitStatus = git status --porcelain
if ($null -ne $gitStatus) {
Write-Host "There are uncommitted changes in git. Please commit or stash them and try again."
Write-Host "Git status:"
Write-Host $gitStatus

# exit with error code
exit 1
}

# loop through each package and update
$updates | ForEach-Object {
$package = [regex]::Match($_, "@[^\s]+").Value
Write-Host "Applying update: $package"
ng update $package

# check if the above commit was successful, if not, exit
if ($LASTEXITCODE -ne 0) {
Write-Host "Update failed, exiting"
exit 1
}

git add .
git commit -m "Angular updates: $package"
}


# change directory back to original
Set-Location $scriptPath

I tried to put comments above so that it’s clear what it does. And here is how I call it from my dev.bat script:

@echo off
title "Checking angular updates"
@powershell -ExecutionPolicy Bypass -File ./angular_update.ps1

REM check if the exit code was non zero, and if it was, exit
if %errorlevel% neq 0 exit /b %errorlevel%
@echo on

cd src\web
dotnet watch run --urls "https://localhost:5002"

If you need this in any other language, you can attempt to rewrite it, or ask claude.ai or bard or chatgpt to rewrite it for you to the language of your choice. I tried it and it looks like it gives great results, but be sure to check the output that it does everything properly.

Conclusion

I have had a really positive experience with this flow. Before I had this automated, I would run ng update on adhoc basis or when I saw major angular version update go through, or when github would create security warning about some package having vulnerability. It was very adhoc and required me always remembering “oh run ng update”, “ok, copy this command, copy that command, remember to git commit” etc. Now, it just happens.

If your organization requires PRs with each update, it will be pretty straightforward to update the script to first create a branch, make changes, and push the new branch to the repo so that the PR could be made.

I love this setup and hopefully you will find it useful as well.

--

--

No responses yet