Skip to content

Commit

Permalink
chore: add multi-gitter script for auto upgrading repos
Browse files Browse the repository at this point in the history
  • Loading branch information
kabaros committed Oct 24, 2024
1 parent 93ccf76 commit a45f1e5
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 0 deletions.
8 changes: 8 additions & 0 deletions multi-gitter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# PoC for multi-gitter

PoC for using [multi-gitter](https://github.com/lindell/multi-gitter) to do bulk upgrade over multiple repos

## Steps
1. install multi-gitter as [described in the repo](https://github.com/lindell/multi-gitter?tab=readme-ov-file#install)
1. update the `config.yml` as you see fit (i.e. to include certain repos)
1. run `multi-gitter run "node $PWD/script.js" --config ./config.yml`
18 changes: 18 additions & 0 deletions multi-gitter/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
commit-message: "fix(app-platform): upgrade platform tools to use vite and react 18"
repo:
- dhis2/scheduler-app
- dhis2/maintenance-app-beta
- dhis2/login-app
- dhis2/dashboard-app
- dhis2/maps-app
- dhis2/data-exchange-app
# repo-include: /-app/ # this can replace the list of repos to target all apps once we're confident with the script
repo-exclude: /(app-hub|capture-app|social-media-video-app|dashboard-classic-app|core-resource-app|maps-climate-pilot-app|dhis2-android-skeleton-app|metadata-integrity-app|who-data-quality-app|gf-adex-flow-app)/
draft: true
clone-dir: .
# token: X # add GitHub token here or pass it to the command with GITHUB_TOKEN=XXX
log-level: debug
branch: upgrade-vite-react
conflict-strategy: replace
pr-body: This is a test PR to see if we can automate upgrading app-platform. Relates to https://github.com/dhis2/app-platform/pull/887.

204 changes: 204 additions & 0 deletions multi-gitter/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/**
* script to be run on all repos to upgrade to the latest version of app-platform tools
* which uses Vite and upgrades to React 18.
*
* It does few things to make the process easier:
* 1. Upgrade to the latest version of cli-app-scripts, cli-style and UI library
* 2. Removes the resolutions for these packages from package.json
* 3. Runs d2 migrate script, which mainly updates d2.config and js extensions to use jsx (which is needed to optimise Vite performance)
* 4. Dedupes the dependencies with npx yarn-deduplicate
* 5. Upgrades test dependencies (@testing-library et al.) to a version compatible with React@18
* 6. Run `yarn format`
* 7. Check that React is definitely version 18
* 8. Adds a React-18 badge to the README
* To run it, do: multi-gitter run "node $PWD/script.js" --config ./config.yml
*/

const assert = require('assert')
const { execSync, exec } = require('child_process')

Check failure on line 18 in multi-gitter/script.js

View workflow job for this annotation

GitHub Actions / lint

'exec' is assigned a value but never used
const fs = require('fs')
const path = require('path')

const packageFile = require(path.join(process.cwd(), './package.json'))

const dependencies = [
...Object.keys(packageFile.dependencies),
...Object.keys(packageFile.devDependencies),
]

// ToDO: change from alpha to main once merged
console.info('upgrading cli-app-scripts')
execSync('yarn add --dev "@dhis2/cli-app-scripts@alpha"', { stdio: 'inherit' })

console.info('upgrading cli-style')
execSync('yarn add --dev "@dhis2/cli-style"', { stdio: 'inherit' })
// ToDo: run style apply and change d2.config direction to auto??

console.info('upgrading the UI library')
execSync('yarn add --dev "@dhis2/ui"', { stdio: 'inherit' }) // get the latest version to avoid warnings about defaultProps in React 18

execSync(
'git add --all && git commit --allow-empty --no-verify -m "chore: bump dhis2 dependencies"'
)

/**
* Updating package.json - removing react, and react-dom, resolutions and deduping
*/
execSync(
`jq -r 'del(.dependencies["react"])' package.json > _.json && mv _.json package.json`
)
execSync(
`jq -r 'del(.dependencies["react-dom"])' package.json > _.json && mv _.json package.json`
)

// removing resolutions as well
const resolutionsToRemove = [
'@dhis2/ui',
'@dhis2/cli-app-scripts',
'@dhis2/cli-style',
'react',
'react-dom',
]

resolutionsToRemove.forEach((resolution) => {
execSync(
`jq -r 'del(.resolutions["${resolution}"])' package.json > _.json && mv _.json package.json`
)
})
// ToDO: double check if we also need to bump react-router

execSync(`yarn add package.json && yarn d2-style apply --staged`)

execSync('npx yarn-deduplicate yarn.lock && yarn', { stdio: 'inherit' })
execSync(
'git add --all && git commit --allow-empty --no-verify -m "chore: remove react, react-dom and deduplicate dependencies"'
)

/**
* d2 migrate script
*/
console.info('Run migration script from d2-app-scripts')
execSync('yarn d2-app-scripts migrate js-to-jsx', { stdio: 'inherit' })
execSync(
'git add --all && git commit --allow-empty --no-verify -m "chore: run d2 migrate script"'
)

if (dependencies.includes('@testing-library/react')) {
console.info('upgrading @testing-library/react')
execSync('yarn add @testing-library/react', { stdio: 'inherit' })
}

if (dependencies.includes('@testing-library/user-event')) {
console.info('upgrading @testing-library/user-event')
execSync('yarn add @testing-library/user-event', { stdio: 'inherit' })
}

if (dependencies.includes('@testing-library/jest-dom')) {
console.info('upgrading @testing-library/jest-dom')
execSync('yarn add @testing-library/jest-dom', { stdio: 'inherit' })
}

if (dependencies.includes('@testing-library/react-hooks')) {
console.info('removing @testing-library/react-hooks')
execSync('yarn remove @testing-library/react-hooks', { stdio: 'inherit' })

// make sure @testing-library/react is installed - sometimes it is not (like in Login app)
execSync('yarn add @testing-library/react', { stdio: 'inherit' })
// ToDo: next do a codemod to upgrade uses of old react-hooks
// ! this is a naive version of such a codemod
execSync(
`find ./src -type f -exec sed -i "s#import { renderHook } from '@testing-library/react-hooks'#import { renderHook } from '@testing-library/react'#g" {} \\;`,
{ stdio: 'inherit' }
)
}

if (dependencies.includes('enzyme-adapter-react-16')) {
console.info(
'replace enzyme-adapter-react-16 with @cfaester/enzyme-adapter-react-18'
)
execSync('yarn remove enzyme-adapter-react-16', {
stdio: 'inherit',
})
execSync('yarn add --dev @cfaester/enzyme-adapter-react-18', {
stdio: 'inherit',
})

execSync(
`find ./src -type f -exec sed -i "s#enzyme-adapter-react-16#@cfaester/enzyme-adapter-react-18#g" {} \\;`,
{ stdio: 'inherit' }
)
}

try {
// special case for identity-obj-proxy which needs to be installed separately now (it used to be a transitive dependency of CRA)
const result = execSync(
'grep -ri identity --exclude-dir=node_modules --exclude-dir=.d2 --exclude-dir=build --exclude=yarn.lock',
{ stdio: 'inherit' }
)
if (result && result?.toString().length > 0) {
execSync('yarn add --dev identity-obj-proxy')
}
} catch (err) {
// I don't know why this fails sometimes, but wrapping it in try/catch for now
}

execSync('npx yarn-deduplicate yarn.lock && yarn', { stdio: 'inherit' })

execSync(
'git add --all && git commit --allow-empty --no-verify -m "chore: update test dependencies"'
)

/**
* format all files
*/
try {
execSync('yarn d2-style apply', { stdio: 'inherit' })
execSync(
'git add --all && git commit --allow-empty --no-verify -m "chore: format all files"'
)
} catch (err) {
// some issues are not automatically fixable
// Todo: decide how to do this better
console.error(err)
}
/**
* Check we only have React@18 installed
*/
execSync('yarn why react', { stdio: 'inherit' })

const version = execSync(
`yarn why react | grep '=> Found' | sed -r 's/=> Found "react\\@(.+).+/\\1/'`
).toString()

console.log(`Checking installed React version: react@${version}`)
assert.match(version, /18\./, `Version found "${version}" - not version 18 :(`)

const patchPath = `${__dirname}/patches/${process.env.REPOSITORY}/0001-fix-manual-updates-for-react-vite-migration.patch`

if (fs.existsSync(patchPath)) {
const command = `git am --signoff < ${patchPath}`

console.info(`Running patch command: ${command}`)
execSync(command, {
stdio: 'inherit',
})
}

execSync(
`sed -i '1i![React 18](https://img.shields.io/badge/react-18-blue)\n' README.md`,
{
stdio: 'inherit',
}
)

execSync('git add README.md && yarn d2-style apply --staged', {
stdio: 'inherit',
})

/**
* - needed to remove React dependency from apps (feels a bit crude)
* - are the changes for tests helpful?
* - some apps still don't have a PR preview - it would be nice to add that to make testing apps easier
* - typescript apps (like maintenance) need to be revisited after the changes to cli-style eslint are done
* and dhis/ui alpha is merged to main
*/

0 comments on commit a45f1e5

Please sign in to comment.