├── .prettierrc.json ├── test ├── simple.test.js └── users.test.js ├── src ├── server.js ├── routes │ ├── greet │ │ └── index.js │ └── users │ │ └── index.js └── app.js ├── .eslintrc.json ├── .github └── workflows │ ├── simple_cd.yaml │ └── simple_ci.yaml ├── package.json └── .gitignore /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /test/simple.test.js: -------------------------------------------------------------------------------- 1 | describe('Sample Test', () => { 2 | it('should test that true === true', () => { 3 | expect(true).toBe(true) 4 | }) 5 | }) 6 | -------------------------------------------------------------------------------- /src/server.js: -------------------------------------------------------------------------------- 1 | const app = require('./app') 2 | 3 | const port = 3000 4 | 5 | app.listen(port, () => { 6 | console.log(`App listening at ${port}`) 7 | }) 8 | 9 | module.exports = app 10 | -------------------------------------------------------------------------------- /src/routes/greet/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | // eslint-disable-next-line new-cap 3 | const router = express.Router() 4 | 5 | router.get('/', (req, res) => { 6 | res.send('Hello There !!') 7 | }) 8 | 9 | module.exports = router 10 | -------------------------------------------------------------------------------- /src/routes/users/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | // eslint-disable-next-line new-cap 3 | const router = express.Router() 4 | 5 | router.get('/', (req, res) => { 6 | res.json({ users: ['Akram', 'Ahmed', 'Sohaib', 'Abdelghani'] }) 7 | }) 8 | 9 | module.exports = router 10 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": ["google", "prettier"], 8 | "parserOptions": { 9 | "ecmaVersion": "latest" 10 | }, 11 | "plugins": ["prettier"], 12 | "rules": { "prettier/prettier": "error" } 13 | } 14 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const morgan = require('morgan') 3 | 4 | const greetRouter = require('./routes/greet') 5 | const usersRouter = require('./routes/users') 6 | 7 | const app = express() 8 | 9 | // set up morgan for logging 10 | app.use(morgan('combined')) 11 | 12 | app.use('/greet', greetRouter) 13 | app.use('/users', usersRouter) 14 | 15 | app.get('/', (req, res) => { 16 | res.send('Hello WOrld ') 17 | }) 18 | 19 | module.exports = app 20 | -------------------------------------------------------------------------------- /test/users.test.js: -------------------------------------------------------------------------------- 1 | const server = require('../src/app') 2 | const supertest = require('supertest') 3 | const requestWithSupertest = supertest(server) 4 | 5 | describe('User Endpoints', () => { 6 | it('GET /users should show all users', async () => { 7 | const res = await requestWithSupertest.get('/users') 8 | expect(res.status).toEqual(200) 9 | expect(res.type).toEqual(expect.stringContaining('json')) 10 | expect(res.body).toHaveProperty('users') 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /.github/workflows/simple_cd.yaml: -------------------------------------------------------------------------------- 1 | name: Simple Deployment to VM 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | # This job will deploy our application to a server 9 | deploy: 10 | runs-on: ubuntu-latest 11 | 12 | strategy: 13 | matrix: 14 | node-version: [16.x] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v2 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | cache: 'npm' 23 | - name: 'Install' 24 | run: npm ci 25 | - name: 'Testing' 26 | run: npm test 27 | - name: SSH and deploy to the host 28 | uses: appleboy/ssh-action@master 29 | with: 30 | host: ${{ secrets.HOST }} 31 | command_timeout: 200m 32 | username: ${{ secrets.USERNAME }} 33 | key: ${{ secrets.KEY }} 34 | port: 22 35 | script: | 36 | killall node 37 | cd githubActionsWorkshop 38 | git checkout main 39 | git pull 40 | npm install 41 | npm start >log/$(date +"%s").log 2>&1 & 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "githubactionsworkshop", 3 | "version": "1.0.0", 4 | "description": "Github Actions Workshop ", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest --testTimeout=10000 --detectOpenHandles", 8 | "format": "prettier src/**/*.js", 9 | "lint": "eslint src/**/*.js", 10 | "start": "node src/server.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/akram09/githubActionsWorkshop.git" 15 | }, 16 | "jest": { 17 | "testEnvironment": "node", 18 | "coveragePathIgnorePatterns": [ 19 | "/node_modules/" 20 | ] 21 | }, 22 | "keywords": [ 23 | "Github", 24 | "Actions", 25 | "CI/CD" 26 | ], 27 | "author": "akram09", 28 | "license": "ISC", 29 | "bugs": { 30 | "url": "https://github.com/akram09/githubActionsWorkshop/issues" 31 | }, 32 | "homepage": "https://github.com/akram09/githubActionsWorkshop#readme", 33 | "dependencies": { 34 | "express": "^4.18.1", 35 | "morgan": "^1.10.0" 36 | }, 37 | "devDependencies": { 38 | "eslint": "^8.15.0", 39 | "eslint-config-google": "^0.14.0", 40 | "eslint-config-prettier": "^8.5.0", 41 | "eslint-plugin-prettier": "^4.0.0", 42 | "jest": "^28.1.0", 43 | "prettier": "^2.6.2", 44 | "supertest": "^6.2.3" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/simple_ci.yaml: -------------------------------------------------------------------------------- 1 | name: Rest API CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | pull_request: 8 | branches: 9 | - main 10 | - develop 11 | jobs: 12 | # This job will verify the quality of the code 13 | lint: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [16.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v2 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | cache: 'npm' 27 | - name: 'Install' 28 | run: npm ci 29 | - name: 'Formatting' 30 | run: npm run format 31 | - name: 'Linting' 32 | run: npm run lint 33 | # This job will test the code with jest and supertest 34 | test: 35 | runs-on: ubuntu-latest 36 | needs: [lint] 37 | 38 | strategy: 39 | matrix: 40 | node-version: [16.x] 41 | 42 | steps: 43 | - uses: actions/checkout@v2 44 | - name: Use Node.js ${{ matrix.node-version }} 45 | uses: actions/setup-node@v2 46 | with: 47 | node-version: ${{ matrix.node-version }} 48 | cache: 'npm' 49 | - name: 'Install' 50 | run: npm ci 51 | - name: 'Test' 52 | run: npm test 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Serverless directories 108 | .serverless/ 109 | 110 | # FuseBox cache 111 | .fusebox/ 112 | 113 | # DynamoDB Local files 114 | .dynamodb/ 115 | 116 | # TernJS port file 117 | .tern-port 118 | 119 | # Stores VSCode versions used for testing VSCode extensions 120 | .vscode-test 121 | 122 | # yarn v2 123 | .yarn/cache 124 | .yarn/unplugged 125 | .yarn/build-state.yml 126 | .yarn/install-state.gz 127 | .pnp.* 128 | log/ --------------------------------------------------------------------------------