Skip to content

Commit 2354c94

Browse files
Merge pull request #19 from timothywarner/combined-fixes
Combined fixes: pipelines + nodeapp-1 updates
2 parents 9efa7bd + 62f96a4 commit 2354c94

File tree

14 files changed

+247
-172
lines changed

14 files changed

+247
-172
lines changed

.github/workflows/node-azure-deploy.yml

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ env:
2626
NODE_VERSION: '18.x'
2727
AZURE_WEBAPP_NAME: 'webapp-az400-demo'
2828
AZURE_WEBAPP_PACKAGE_PATH: './nodeapp-1'
29+
WORKING_DIRECTORY: 'nodeapp-1'
2930

3031
jobs:
3132
# ========================================
@@ -44,42 +45,38 @@ jobs:
4445
with:
4546
node-version: ${{ env.NODE_VERSION }}
4647
cache: 'npm'
47-
cache-dependency-path: '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/package-lock.json'
48+
cache-dependency-path: '${{ env.WORKING_DIRECTORY }}/package-lock.json'
4849

4950
- name: 📦 Install dependencies
5051
run: npm ci
51-
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
52+
working-directory: ${{ env.WORKING_DIRECTORY }}
5253

5354
- name: 🔒 Security audit
5455
run: npm audit --audit-level=high
55-
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
56+
working-directory: ${{ env.WORKING_DIRECTORY }}
5657
continue-on-error: true
5758

5859
- name: 🧹 Lint code
59-
run: npm run lint || echo "No lint script configured"
60-
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
60+
run: npm run lint
61+
working-directory: ${{ env.WORKING_DIRECTORY }}
6162

62-
- name: 🧪 Run tests
63-
run: npm test -- --coverage || npm test
64-
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
63+
- name: 🧪 Run tests with Mocha
64+
run: npm test
65+
working-directory: ${{ env.WORKING_DIRECTORY }}
6566

66-
- name: 📊 Upload coverage reports
67-
uses: codecov/codecov-action@v3
67+
- name: 📊 Upload test results
68+
uses: actions/upload-artifact@v4
69+
if: always()
6870
with:
69-
directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/coverage
70-
flags: unittests
71-
name: codecov-umbrella
72-
fail_ci_if_error: false
73-
74-
- name: 🔨 Build application
75-
run: npm run build || echo "No build required"
76-
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
71+
name: mochawesome-report
72+
path: ${{ env.WORKING_DIRECTORY }}/mochawesome-report
73+
retention-days: 7
7774

7875
- name: 📤 Upload artifact for deployment
7976
uses: actions/upload-artifact@v4
8077
with:
8178
name: node-app
82-
path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
79+
path: ${{ env.WORKING_DIRECTORY }}
8380
retention-days: 5
8481

8582
# ========================================
@@ -137,6 +134,9 @@ jobs:
137134
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
138135

139136
steps:
137+
- name: 📥 Checkout for tests
138+
uses: actions/checkout@v4
139+
140140
- name: 📥 Download artifact
141141
uses: actions/download-artifact@v4
142142
with:
@@ -158,9 +158,11 @@ jobs:
158158

159159
- name: 🧪 Run integration tests
160160
run: |
161-
echo "Running integration tests against staging..."
162-
# Add your integration test commands here
163-
echo "✅ Integration tests passed!"
161+
cd ${{ env.WORKING_DIRECTORY }}
162+
npm ci
163+
export TEST_URL=https://${{ env.AZURE_WEBAPP_NAME }}-staging.azurewebsites.net
164+
npm test
165+
continue-on-error: true
164166

165167
# ========================================
166168
# JOB 4: DEPLOY TO PRODUCTION
@@ -204,12 +206,6 @@ jobs:
204206
});
205207
console.log(`✅ Created tag: ${tag}`);
206208
207-
- name: 📊 Monitor deployment
208-
run: |
209-
echo "Monitoring production deployment..."
210-
# Add Application Insights queries here
211-
echo "✅ Production deployment healthy!"
212-
213209
# ========================================
214210
# REUSABLE WORKFLOW: SECURITY SCAN
215211
# ========================================
@@ -222,12 +218,7 @@ jobs:
222218
- name: 📥 Checkout code
223219
uses: actions/checkout@v4
224220

225-
- name: 🔍 Run CodeQL Analysis
226-
uses: github/codeql-action/analyze@v2
227-
with:
228-
languages: javascript
229-
230-
- name: 🛡️ Run Dependabot scan
221+
- name: 🔍 Run Dependabot scan
231222
uses: github/super-linter@v5
232223
env:
233224
DEFAULT_BRANCH: main

nodeapp-1/.dockerignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
node_modules
2+
npm-debug.log
3+
mochawesome-report
4+
.git
5+
.gitignore
6+
.npmrc
7+
.eslintrc.json
8+
.mocharc.json
9+
test
10+
debug-solution.txt
11+
*.code-workspace
12+
.vscode
13+
.devcontainer
14+
.github
15+
.azure

nodeapp-1/.eslintrc.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"env": {
3+
"node": true,
4+
"es2021": true,
5+
"mocha": true
6+
},
7+
"extends": "eslint:recommended",
8+
"parserOptions": {
9+
"ecmaVersion": "latest",
10+
"sourceType": "module"
11+
},
12+
"rules": {
13+
"indent": ["error", 2],
14+
"linebreak-style": ["error", "unix"],
15+
"quotes": ["error", "single"],
16+
"semi": ["error", "always"],
17+
"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
18+
"no-console": "off"
19+
}
20+
}

nodeapp-1/.mocharc.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"timeout": 5000,
3+
"exit": true,
4+
"reporter": "mochawesome",
5+
"reporter-options": [
6+
"reportDir=mochawesome-report",
7+
"reportFilename=test-results",
8+
"html=true",
9+
"json=true",
10+
"overwrite=true",
11+
"inline=true"
12+
]
13+
}

nodeapp-1/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM node:18-alpine
2+
3+
# Create app directory
4+
WORKDIR /usr/src/app
5+
6+
# Install app dependencies
7+
# A wildcard is used to ensure both package.json AND package-lock.json are copied
8+
COPY package*.json ./
9+
10+
RUN npm ci --only=production
11+
12+
# Bundle app source
13+
COPY . .
14+
15+
# Expose port
16+
EXPOSE 3000
17+
18+
# Start the application
19+
CMD [ "node", "app.js" ]

nodeapp-1/README.md

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,77 @@
1-
# Node & Express Demo App for GitHub Actions, Azure DevOps, and Beyond
1+
# Node Express Azure - AZ-400 Demo App
22

3-
## Last edited by Tim Warner
3+
Sample Node.js Express application for demonstrating CI/CD pipelines in AZ-400 training.
44

5-
> Build Your First CI/CD Pipeline using Azure DevOps with this Demo App.
5+
## Features
66

7-
This is a Node and Express web application used to demonstrate CI/CD with Azure DevOps. You can clone this repo and use it within Azure DevOps to build, test, and release to an Azure App Service web app.
7+
- Express.js web application
8+
- Handlebars templating
9+
- Mocha/Chai testing with mochawesome reports
10+
- ESLint for code quality
11+
- Docker support
12+
- Azure DevOps and GitHub Actions ready
813

9-
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/timothywarner/node-express-azure)
14+
## Getting Started
1015

11-
## Running and Testing Locally:
16+
### Prerequisites
1217

13-
You can use these commands to install, test, and run the app locally. (Not Required)
18+
- Node.js 18.x or higher
19+
- npm 8.x or higher
1420

15-
### Install
21+
### Installation
1622

17-
```
23+
```bash
1824
npm install
1925
```
2026

21-
### Test
27+
### Running Locally
2228

29+
```bash
30+
npm start
2331
```
32+
33+
The app will be available at http://localhost:3000
34+
35+
### Running Tests
36+
37+
```bash
2438
npm test
2539
```
2640

27-
![alt text](https://user-images.githubusercontent.com/5126491/51065379-c1743280-15c1-11e9-80fd-6a3d7ab4ac1b.jpg "Unit Test")
41+
### Linting
2842

29-
Navigate to the `/test` folder to review the unit tests for this project. These tests will run as part of your Azure DevOps Build pipeline. See `azure-pipelines.yml` in this repo.
43+
```bash
44+
npm run lint
45+
```
3046

31-
### Start
47+
### Docker
3248

49+
Build the image:
50+
```bash
51+
docker build -t nodeapp-1 .
3352
```
34-
npm start
53+
54+
Run the container:
55+
```bash
56+
docker run -p 3000:3000 nodeapp-1
3557
```
3658

59+
## CI/CD Pipelines
60+
61+
This app includes example pipelines for:
62+
- Azure Pipelines (see `/pipelines` folder in repo root)
63+
- GitHub Actions (see `.github/workflows` in repo root)
64+
65+
## Azure Artifacts
66+
67+
To publish to Azure Artifacts:
68+
69+
1. Create `.npmrc` from `.npmrc.template`
70+
2. Set up authentication
71+
3. Run `npm run publish:dev` or `npm run publish:prod`
3772

38-
### License
73+
## Environment Variables
3974

40-
This project is licensed under the Apache License 2.0
75+
- `PORT` - Server port (default: 3000)
76+
- `NODE_ENV` - Environment (development/production)
77+
- `AZURE_ARTIFACTS_FEED` - Azure Artifacts feed URL

nodeapp-1/app.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ app.use('/', index);
2727
app.use('/who', who);
2828
app.use('/contact', contact);
2929

30-
// Start the server
31-
app.listen(app.get('port'), () => {
32-
console.log(`Server running on port ${app.get('port')}`);
33-
});
30+
// Export the app for testing
31+
module.exports = app;
32+
33+
// Only start the server if this file is run directly
34+
if (require.main === module) {
35+
app.listen(app.get('port'), () => {
36+
console.log(`Server running on port ${app.get('port')}`);
37+
});
38+
}

nodeapp-1/config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
module.exports = {
2-
port: process.env.PORT || 443,
2+
port: process.env.PORT || 3000,
3+
environment: process.env.NODE_ENV || 'development',
4+
azure: {
5+
artifactsFeed: process.env.AZURE_ARTIFACTS_FEED || 'https://pkgs.dev.azure.com/certstarorg/_packaging/az400-npm-feed/npm/registry/'
6+
}
37
};

nodeapp-1/server.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Server entry point for production
2+
const app = require('./app');
3+
4+
const port = process.env.PORT || app.get('port');
5+
6+
app.listen(port, () => {
7+
console.log(`Server running on port ${port}`);
8+
console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
9+
});

nodeapp-1/test/contact_test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ const config = require('../config');
33
const chai = require('chai');
44
const chaiHttp = require('chai-http');
55
const should = chai.should();
6-
const server = require('../app');
6+
const app = require('../app');
77

88
chai.use(chaiHttp);
99

10-
describe('/GET', () => {
10+
describe('/GET contact', () => {
1111
it('returns the contact page', (done) => {
12-
chai.request(`http://localhost:${config.port}`)
12+
chai.request(app)
1313
.get('/contact')
1414
.end((err, res) => {
1515
res.should.have.status(200);
16-
res.text.should.contain('Contact Us');
16+
res.text.should.contain('Contact information');
1717
done();
1818
});
1919
});

0 commit comments

Comments
 (0)