How To Set Up CI/CD For An Angular And .NET Project

A reliable CI/CD pipeline turns every code change into a repeatable path from commit to production. For an Angular frontend and a .NET API, that path usually includes dependency installation, compilation, automated tests, packaging, security checks and deployment. The goal is to make delivery predictable rather than dependent on a developer remembering a sequence of local commands.

The most useful pipeline is not necessarily the most complicated one. A small team may need only pull request validation and a deployment to one staging environment, while a larger product may require separate approvals, infrastructure checks, database migration controls and deployment slots. The design should reflect the risk and release rhythm of the application.

This guide uses common tools and patterns that work with GitHub Actions, Azure DevOps and similar automation platforms. The examples assume an Angular workspace in one directory and a .NET solution in another, but the same principles apply when the frontend and backend live in separate repositories.

Australian teams should also account for local operating conditions. An application serving customers in Sydney, Melbourne or Brisbane may use an Australian cloud region for latency and data residency, while a team working across Perth and the eastern states must make time zones explicit. A pipeline that reports times in UTC, AEST or AEDT without a clear convention can create avoidable release confusion.

Define The Delivery Path

Start by describing the journey a change should take. A pull request should install dependencies, compile the Angular application, build the .NET solution and run fast tests. A merge into the main branch can produce versioned artefacts and deploy to a test or staging environment. Production deployment should happen only after the relevant checks and approval have passed.

Keeping continuous integration separate from continuous delivery makes failures easier to understand. CI answers whether the code is safe to merge. CD answers whether a validated build can be promoted. These activities can run in one workflow with separate jobs, or in multiple workflows connected through published artefacts.

A useful pipeline has a quick feedback loop for developers and a cautious promotion path for operations. Linting, unit tests and compilation belong near the start. Browser tests, container scanning and infrastructure validation may take longer, so they can run after the basic build succeeds or in parallel where the automation platform supports it.

Prepare The Repository And Environments

The repository should make local and automated builds behave similarly. Commit the Angular package manifest and lock file, the .NET solution and project files, test projects, configuration templates and scripts used by the pipeline. Avoid relying on files that exist only on a developer’s computer. A new contributor should be able to clone the repository, install the supported SDKs and run the same commands used by CI.

Pin major tool versions wherever practical. The pipeline can use a specific Node.js release, npm version, .NET SDK and browser test version. This reduces unexpected failures when a hosted runner changes its default software. Cache package directories to improve speed, but treat the lock file as part of the cache key so that dependency changes invalidate stale content.

Use separate configuration for development, staging and production. Angular environment files can select API endpoints at build time, while ASP.NET Core configuration can read environment variables, JSON files and secret stores at runtime. Never commit passwords, signing keys, connection strings or OAuth client secrets. Store them in the CI/CD platform’s protected secret facility or a service such as Azure Key Vault.

For Australian deployments, decide whether workloads belong in an Azure Australia East or Australia Southeast region, or in an equivalent local region from another cloud provider. The choice can affect latency, backup policy and contractual data residency. Document the choice alongside retention requirements and any obligations relevant to the Australian Privacy Act.

Build And Test Both Applications

A typical CI job checks out the code, installs the required toolchains and restores dependencies. The Angular portion can run commands such as npm ci, npm run lint, npm test -- --watch=false and npm run build -- --configuration production. Using npm ci rather than a general install command ensures that the lock file controls the dependency tree.

The .NET portion commonly runs dotnet restore, dotnet build --no-restore and dotnet test --no-build --collect:"XPlat Code Coverage". Unit tests should cover business logic and API behaviour without requiring external services. Integration tests can use a disposable database, test container or an isolated test instance. The pipeline should publish test results and coverage reports even when a later step fails.

Frontend and backend tests should also verify their contract. A changed API response shape can break an Angular service even when both projects compile independently. Consumer-driven contract tests, shared API schemas or a generated TypeScript client can expose this kind of mismatch before deployment. End-to-end tests should cover a small number of high-value journeys rather than attempt to exercise every screen on every commit.

Performance work can also be part of the build strategy. An Angular application may need an efficient cache for reference data or repeated requests; a time-based caching service can provide a reusable approach without scattering cache logic through components. Keep performance checks focused, since a noisy benchmark can make developers ignore meaningful regressions.

Package Immutable Release Artefacts

Once validation succeeds, create artefacts that can be promoted without rebuilding. For Angular, the production output is normally the generated dist directory. It can be compressed and uploaded to object storage, copied to a web server or included in a container image. For .NET, publish the application with the appropriate runtime options and package the resulting files or image.

An immutable artefact has a commit identifier, build number or semantic version attached to it. The staging and production environments should receive the same compiled files. Rebuilding during production deployment can introduce a different dependency resolution, timestamp or compiler result, making it harder to prove what was tested.

A release bundle should include enough metadata for diagnosis: the source revision, build timestamp, application version and perhaps a link to the pipeline run. Expose a safe version endpoint in the API and display the frontend version in an internal diagnostics screen. Do not expose secrets or detailed infrastructure information through public endpoints.

Infrastructure should be treated with the same discipline as application code. Store deployment templates, environment definitions and access policies in version control. Whether the team uses Bicep, Terraform, CloudFormation or provider-specific scripts, run validation during CI and apply changes through an authenticated deployment stage rather than manually modifying production.

Deploy Safely Across Environments

The first deployment target should be an environment that resembles production. It should use the same database engine, authentication model, reverse proxy behaviour and important third-party integrations, with safe test credentials and data. A staging deployment can then run smoke tests against the actual hosted Angular application and .NET API.

Database changes need special care. A migration that removes a column before the old API stops using it can break a rolling deployment. Prefer backwards-compatible changes: add new structures, deploy code that can use both versions, migrate data, then remove obsolete structures in a later release. Run migrations through a controlled step with an explicit identity and backup policy, rather than allowing every application instance to modify the schema at startup.

A blue-green deployment or platform slot can reduce downtime. Deploy the new application to an inactive slot, run health checks and switch traffic only after it responds correctly. Canary releases provide an even smaller exposure by directing a percentage of traffic to the new version. These patterns are valuable for public-facing services where a failed release could disrupt customers during Australian business hours.

Secrets and approvals should be scoped by environment. Developers may deploy to a sandbox, while production requires a protected branch, a nominated approver and short-lived cloud credentials. Use workload identity federation where available instead of storing a long-lived cloud access key in the pipeline.

Add Quality Gates And Operational Feedback

A pipeline is incomplete if it can deploy successfully but cannot show whether the service is healthy. Add a post-deployment smoke test that checks the frontend loads, the API responds, authentication works and a low-risk endpoint reaches its dependencies. Health checks should distinguish basic process availability from deeper readiness, such as database connectivity.

Monitor logs, request failures, latency, dependency errors and frontend JavaScript exceptions after release. Keep correlation IDs consistent between Angular requests and .NET logs so that a support engineer can trace one customer action across the browser, API and database. Alert thresholds should reflect normal traffic instead of firing for every brief network issue.

The following controls provide a practical baseline for a production pipeline:

Teams serving Australian customers should define an operational time standard. A release scheduled for 9:00 am Sydney time needs to account for daylight saving changes and coordination with colleagues in Queensland, Western Australia or overseas. It is also sensible to avoid high-risk releases immediately before a long weekend, such as the Australia Day or Labour Day holiday period, when the usual support roster may be smaller.

Keep The Pipeline Fast And Maintainable

Pipeline configuration is application code. Break repeated work into reusable jobs or templates, give steps clear names and fail with actionable messages. A developer should be able to tell whether a failure came from dependency restore, compilation, a test assertion, an environment permission or an external service.

Use parallel jobs where they shorten feedback without making logs difficult to follow. Angular linting and unit tests can run separately from .NET tests, while artefact packaging waits for all required checks. Cache npm and NuGet packages, but avoid caching generated build output unless the cache key includes every input that affects the result.

The following maintenance practices keep delivery dependable as the project grows:

Rollback should be a designed operation rather than an emergency improvisation. Keep the previous artefact available, make the deployment tool capable of selecting it and document how to revert configuration and database changes. If a database change cannot be reversed safely, use a forward fix with a compatible application version and pause further promotion until the data state is understood.

A mature pipeline gradually becomes a shared engineering asset. Developers receive rapid feedback on every pull request, release managers gain a clear audit trail and customers get safer updates. The implementation can begin with a few scripts and a single staging environment, then expand as the Angular and .NET system, team and compliance requirements evolve.

Create the first workflow around the commands that already build and test the project locally. Commit it, run it against a non-production environment and inspect every log and generated artefact. Then add protected production promotion, monitoring and rollback support so that each release becomes a repeatable, observable step rather than a manual event.