Skip to content

Commit f590cdc

Browse files
authored
(chore) Add automated dependency update workflow (#103)
Adds a workflow and script to automatically check for and update OpenMRS dependencies, including verification and deduplication. Other changes include: - Augmenting the existing Transifex integration pull workflow with auto-approve/merge capabilities - Improving workflow documentation - Moving config files such as the i18next parser config and Jest setup into the tools directory - Updating the primary CI workflow to use Node 20
1 parent 99ddf3a commit f590cdc

File tree

10 files changed

+282
-108
lines changed

10 files changed

+282
-108
lines changed

.github/workflows/e2e.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,52 @@ jobs:
1212
main:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- name: Checkout repo
15+
- name: 📥 Checkout repo
1616
uses: actions/checkout@v4
1717

18-
- name: Copy test environment variables
18+
- name: 📋 Copy test environment variables
1919
run: cp example.env .env
2020

21-
- name: Setup node
21+
- name: ⚙️ Setup node
2222
uses: actions/setup-node@v4
2323
with:
24-
node-version: 18
24+
node-version: 20
2525

26-
- name: Cache dependencies
26+
- name: 💾 Cache dependencies
2727
id: cache-dependencies
2828
uses: actions/cache@v4
2929
with:
3030
path: '**/node_modules'
3131
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
3232

33-
- name: Install dependencies
33+
- name: 📦 Install dependencies
3434
if: steps.cache-dependencies.outputs.cache-hit != 'true'
3535
run: yarn install --immutable
3636

37-
- name: Cache Playwright browsers
37+
- name: 🎭 Cache Playwright browsers
3838
id: cache-playwright
3939
uses: actions/cache@v4
4040
with:
4141
path: ~/.cache/ms-playwright
4242
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json', 'e2e/support/bamboo/playwright.Dockerfile') }}
4343

44-
- name: Install Playwright Browsers
44+
- name: 🌐 Install Playwright Browsers
4545
if: steps.cache-playwright.outputs.cache-hit != 'true'
4646
run: npx playwright install chromium --with-deps
4747

48-
- name: Build app
48+
- name: 🏗️ Build app
4949
run: yarn run build
5050

51-
- name: Run dev server
51+
- name: 🚀 Run dev server
5252
run: bash e2e/support/github/run-e2e-docker-env.sh
5353

54-
- name: Wait for OpenMRS instance to start
54+
- name: Wait for OpenMRS instance to start
5555
run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:8080/openmrs/login.htm)" != "200" ]]; do sleep 10; done
5656

57-
- name: Run E2E tests
57+
- name: 🧪 Run E2E tests
5858
run: yarn playwright test
5959

60-
- name: Stop dev server
60+
- name: 🛑 Stop dev server
6161
if: '!cancelled()'
6262
run: docker stop $(docker ps -a -q)
6363

.github/workflows/node.js.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Node.js CI
1+
name: OpenMRS CI
22

33
on:
44
push:
@@ -19,11 +19,12 @@ jobs:
1919
runs-on: ubuntu-latest
2020

2121
steps:
22-
- uses: actions/checkout@v4
22+
- name: 📥 Checkout repo
23+
uses: actions/checkout@v4
2324
- name: 🛠️ Setup Node.js
2425
uses: actions/setup-node@v4
2526
with:
26-
node-version: "18"
27+
node-version: 20
2728

2829
- name: 💾 Cache dependencies
2930
id: cache
@@ -62,11 +63,12 @@ jobs:
6263
if: ${{ github.event_name == 'push' }}
6364

6465
steps:
65-
- uses: actions/checkout@v4
66+
- name: 📥 Checkout repo
67+
uses: actions/checkout@v4
6668
- name: 🛠️ Setup Node.js
6769
uses: actions/setup-node@v4
6870
with:
69-
node-version: "18"
71+
node-version: 20
7072

7173
- name: 💾 Cache dependencies
7274
id: cache
@@ -114,13 +116,14 @@ jobs:
114116
if: ${{ github.event_name == 'release' }}
115117

116118
steps:
117-
- uses: actions/checkout@v4
119+
- name: 📥 Checkout repo
120+
uses: actions/checkout@v4
118121
- name: 📥 Download Artifacts
119122
uses: actions/download-artifact@v4
120123
- name: 🛠️ Use Node.js
121124
uses: actions/setup-node@v4
122125
with:
123-
node-version: "18"
126+
node-version: 20
124127
registry-url: 'https://registry.npmjs.org'
125128

126129
- name: 💾 Cache dependencies
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Workflow to automatically check and update OpenMRS dependencies
2+
# Runs hourly and can be triggered manually
3+
4+
name: 'Check for OpenMRS Dependency Updates'
5+
6+
on:
7+
workflow_dispatch:
8+
schedule:
9+
# Runs every hour at minute 30
10+
- cron: '30 * * * *'
11+
12+
jobs:
13+
check-for-updates:
14+
name: Check for updates to OpenMRS libraries
15+
runs-on: ubuntu-latest
16+
17+
if: github.repository_owner == 'openmrs'
18+
19+
permissions:
20+
contents: write
21+
pull-requests: write
22+
23+
steps:
24+
# Step 1: Check out repository
25+
- name: 📥 Checkout repository
26+
uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 1 # Shallow clone for better performance
29+
30+
# Step 2: Setup Node.js environment
31+
- name: 🟢 Setup Node.js
32+
uses: actions/setup-node@v4
33+
with:
34+
node-version: 20
35+
36+
# Step 3: Cache dependencies
37+
- name: 💾 Cache dependencies
38+
id: cache
39+
uses: actions/cache@v4
40+
with:
41+
path: '**/node_modules'
42+
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
43+
44+
# Step 4: Install dependencies if cache miss
45+
- name: 📦 Install dependencies
46+
if: steps.cache.outputs.cache-hit != 'true'
47+
run: yarn install --immutable
48+
49+
# Step 5: Run dependency update check
50+
- name: ✅ Check for updates
51+
run: node ./tools/update-openmrs-deps.mjs
52+
53+
# Step 6: Create PR with updates if necessary
54+
- name: ⬆️ Create PR if necessary
55+
id: cpr
56+
uses: peter-evans/create-pull-request@v7
57+
with:
58+
commit-message: '(chore) Update OpenMRS dependencies'
59+
title: '(chore) Update OpenMRS dependencies'
60+
body: |
61+
# OpenMRS Dependencies Update
62+
63+
This PR contains updates to OpenMRS dependencies.
64+
65+
## Changes
66+
* Automated dependency updates for OpenMRS packages
67+
* Generated by the OpenMRS Dependency Update workflow
68+
69+
## Verification
70+
- [ ] All dependencies are valid versions
71+
- [ ] No breaking changes introduced
72+
73+
> This PR was automatically generated and will be automatically merged if checks pass.
74+
branch: 'chore/update-openmrs-deps'
75+
author: 'OpenMRS Bot <infrastructure@openmrs.org>'
76+
token: ${{ secrets.OMRS_BOT_GH_TOKEN }}
77+
labels: |
78+
dependencies
79+
automated-pr
80+
delete-branch: true # Clean up branch after merge
81+
82+
# Step 7: Auto-approve the PR if created or updated
83+
- name: ✅ Auto approve PR
84+
if: steps.cpr.outputs.pull-request-operation == 'created' || steps.cpr.outputs.pull-request-operation == 'updated'
85+
run: gh pr review --approve "${{ steps.cpr.outputs.pull-request-number }}"
86+
env:
87+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
88+
89+
# Step 8: Auto-merge the PR if created or updated
90+
- name: 🔀 Auto merge PR
91+
if: steps.cpr.outputs.pull-request-operation == 'created' || steps.cpr.outputs.pull-request-operation == 'updated'
92+
run: gh pr merge --auto --squash "${{ steps.cpr.outputs.pull-request-number }}"
93+
env:
94+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jest.config.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1+
/**
2+
* @returns {Promise<import('jest').Config>}
3+
*/
14
module.exports = {
25
clearMocks: true,
36
transform: {
4-
"^.+\\.tsx?$": "@swc/jest",
7+
'^.+\\.tsx?$': '@swc/jest',
58
},
6-
transformIgnorePatterns: ["/node_modules/(?!@openmrs)"],
9+
transformIgnorePatterns: ['/node_modules/(?!@openmrs)'],
710
moduleNameMapper: {
8-
"\\.(s?css)$": "identity-obj-proxy",
9-
"@openmrs/esm-framework": "@openmrs/esm-framework/mock",
10-
"^dexie$": require.resolve("dexie"),
11-
"^lodash-es/(.*)$": "lodash/$1",
12-
"^lodash-es$": "lodash",
13-
"^uuid$": "<rootDir>/node_modules/uuid/dist/index.js",
11+
'\\.(s?css)$': 'identity-obj-proxy',
12+
'@openmrs/esm-framework': '@openmrs/esm-framework/mock',
13+
'^dexie$': require.resolve('dexie'),
14+
'^lodash-es/(.*)$': 'lodash/$1',
15+
'^lodash-es$': 'lodash',
16+
'^uuid$': '<rootDir>/node_modules/uuid/dist/index.js',
1417
},
15-
setupFilesAfterEnv: ["<rootDir>/src/setup-tests.ts"],
16-
testEnvironment: "jsdom",
18+
setupFilesAfterEnv: ['<rootDir>/tools/setup-tests.ts'],
19+
testEnvironment: 'jsdom',
1720
testEnvironmentOptions: {
18-
url: "http://localhost/",
21+
url: 'http://localhost/',
1922
},
20-
testPathIgnorePatterns: ["<rootDir>/e2e"],
23+
testPathIgnorePatterns: ['<rootDir>/e2e'],
2124
};

src/setup-tests.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

tools/setup-tests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import '@testing-library/jest-dom';

tools/update-openmrs-deps.mjs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { execSync } from 'node:child_process';
2+
3+
try {
4+
execSync(`yarn up --fixed '@openmrs/esm-framework@next' '@openmrs/esm-form-engine-lib@next' 'openmrs@next'`, {
5+
stdio: ['ignore', 'inherit', 'inherit'],
6+
windowsHide: true,
7+
});
8+
} catch (error) {
9+
console.error(`Error while updating dependencies: ${error.message ?? error}`);
10+
process.exit(1);
11+
}
12+
13+
try {
14+
execSync(`yarn dedupe`, {
15+
stdio: ['ignore', 'inherit', 'inherit'],
16+
windowsHide: true,
17+
});
18+
} catch (error) {
19+
console.error(`Error while deduplicating dependencies: ${error.message ?? error}`);
20+
process.exit(1);
21+
}
22+
23+
try {
24+
execSync(`git diff-index --quiet HEAD --`, {
25+
stdio: 'ignore',
26+
windowsHide: true,
27+
});
28+
process.exit(0);
29+
} catch (error) {
30+
// git diff-index --quite HEAD --
31+
// exits with status 1 if there are changes; we only need to run yarn verify if there are changes
32+
}
33+
34+
try {
35+
execSync(`yarn verify`, {
36+
stdio: ['ignore', 'inherit', 'inherit'],
37+
windowsHide: true,
38+
});
39+
} catch (error) {
40+
console.error(`Error while running yarn verify: ${error.message ?? error}. Updates require manual intervention.`);
41+
process.exit(1);
42+
}

webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const config = (module.exports = require("openmrs/default-webpack-config"));
1+
const config = (module.exports = require('openmrs/default-webpack-config'));
22
module.exports = config;

0 commit comments

Comments
 (0)