-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add dependabot.yml * add increase-if-necessary strategy * Update .github/dependabot.yml Co-authored-by: Kamil Sobol <[email protected]> * dependabot adds e2e label and action to add changesets to dependabot PRs * fix health checks * fix this * try this * add to eslint dictionary * PR feedback * add testing * try this * try that * mock git push * fix changeset file path * update way ghContext is mocked * try this * try this * PR feedback * Delete scripts/components/test-resources/github_pull_request_event.json --------- Co-authored-by: Kamil Sobol <[email protected]>
- Loading branch information
Showing
9 changed files
with
426 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--- | ||
--- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Dependabot version updates raises a maximum of five pull requests each time it checks dependencies. | ||
# Note that there is some overlap with Dependabot security updates so some options can effect security updates as well, | ||
# see https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file. | ||
|
||
version: 2 | ||
updates: | ||
# Maintain dependencies for npm ecosystem | ||
- package-ecosystem: 'npm' | ||
# Checks all directories from the current layer and below recursively for package.json files | ||
directories: | ||
- '**/*' | ||
schedule: | ||
# Runs every Monday | ||
interval: 'weekly' | ||
# Update package.json files if new version is outside of version range specified there. Otherwise lock file only. | ||
versioning-strategy: increase-if-necessary |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
199 changes: 199 additions & 0 deletions
199
scripts/components/dependabot_version_update_handler.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
import { randomUUID } from 'crypto'; | ||
import { $ as chainableExeca } from 'execa'; | ||
import fsp from 'fs/promises'; | ||
import { after, before, beforeEach, describe, it, mock } from 'node:test'; | ||
import { EOL, tmpdir } from 'os'; | ||
import path from 'path'; | ||
import { GitClient } from './git_client.js'; | ||
import { GithubClient } from './github_client.js'; | ||
import { NpmClient } from './npm_client.js'; | ||
import { | ||
readPackageJson, | ||
writePackageJson, | ||
} from './package-json/package_json.js'; | ||
import { DependabotVersionUpdateHandler } from './dependabot_version_update_handler.js'; | ||
import assert from 'assert'; | ||
|
||
const originalEnv = process.env; | ||
|
||
/** | ||
* This test suite is more of an integration test than a unit test. | ||
* It uses the real file system and git repo but mocks the GitHub API client and GitHub context | ||
*/ | ||
void describe('dependabot version update handler', async () => { | ||
let testWorkingDir: string; | ||
let gitClient: GitClient; | ||
let npmClient: NpmClient; | ||
|
||
let cantaloupePackageName: string; | ||
let cantaloupePackagePath: string; | ||
let platypusPackageName: string; | ||
let platypusPackagePath: string; | ||
|
||
let baseRef: string; | ||
|
||
const pullRequestBody = 'Bumps testDep from 1.0.0 to 1.1.0.'; | ||
|
||
before(async () => { | ||
process.env.GITHUB_TOKEN = 'testToken'; | ||
}); | ||
|
||
after(async () => { | ||
process.env = originalEnv; | ||
}); | ||
|
||
beforeEach(async ({ name: testName }) => { | ||
// create temp dir | ||
const shortId = randomUUID().split('-')[0]; | ||
const testNameNormalized = testName.slice(0, 15).replaceAll(/\s/g, ''); | ||
testWorkingDir = await fsp.mkdtemp( | ||
path.join(tmpdir(), `${testNameNormalized}-${shortId}`) | ||
); | ||
console.log(testWorkingDir); | ||
|
||
gitClient = new GitClient(testWorkingDir); | ||
npmClient = new NpmClient(null, testWorkingDir); | ||
|
||
const $ = chainableExeca({ stdio: 'inherit', cwd: testWorkingDir }); | ||
|
||
// converting to lowercase because npm init creates packages with all lowercase | ||
cantaloupePackageName = | ||
`${testNameNormalized}-cantaloupe-${shortId}`.toLocaleLowerCase(); | ||
platypusPackageName = | ||
`${testNameNormalized}-platypus-${shortId}`.toLocaleLowerCase(); | ||
|
||
cantaloupePackagePath = path.join( | ||
testWorkingDir, | ||
'packages', | ||
cantaloupePackageName | ||
); | ||
platypusPackagePath = path.join( | ||
testWorkingDir, | ||
'packages', | ||
platypusPackageName | ||
); | ||
|
||
await gitClient.init(); | ||
await gitClient.switchToBranch('main'); | ||
await npmClient.init(); | ||
|
||
await npmClient.initWorkspacePackage(cantaloupePackageName); | ||
await setPackageToPublic(cantaloupePackagePath); | ||
|
||
await npmClient.initWorkspacePackage(platypusPackageName); | ||
await setPackageToPublic(platypusPackagePath); | ||
|
||
await npmClient.install(['@changesets/cli']); | ||
await setPackageDependencies(cantaloupePackagePath, { testDep: '^1.0.0' }); | ||
await setPackageDependencies(platypusPackagePath, { testDep: '^1.0.0' }); | ||
|
||
await $`npx changeset init`; | ||
await gitClient.commitAllChanges('Initial setup'); | ||
baseRef = await gitClient.getHashForCurrentCommit(); | ||
}); | ||
|
||
void it('can generate changeset with version updates', async () => { | ||
const githubClient = new GithubClient('garbage'); | ||
const labelPullRequestMocked = mock.method( | ||
githubClient, | ||
'labelPullRequest', | ||
async () => {} | ||
); | ||
const gitPushMocked = mock.method(gitClient, 'push', async () => {}); | ||
const ghContextMocked = { | ||
eventName: '', | ||
sha: '', | ||
ref: '', | ||
workflow: '', | ||
action: '', | ||
actor: '', | ||
job: '', | ||
runNumber: 0, | ||
runId: 0, | ||
apiUrl: '', | ||
serverUrl: '', | ||
graphqlUrl: '', | ||
payload: { | ||
pull_request: { | ||
number: 1, | ||
body: pullRequestBody, | ||
}, | ||
}, | ||
issue: { | ||
owner: '', | ||
repo: '', | ||
number: 0, | ||
}, | ||
repo: { | ||
owner: '', | ||
repo: '', | ||
}, | ||
}; | ||
|
||
// Update package.json files for both packages and commit to match what Dependabot will do for a version update PR | ||
await gitClient.switchToBranch('dependabot/test_update'); | ||
await setPackageDependencies(cantaloupePackagePath, { testDep: '^1.1.0' }); | ||
await setPackageDependencies(platypusPackagePath, { testDep: '^1.1.0' }); | ||
await gitClient.commitAllChanges('Bump dependencies'); | ||
const headRef = await gitClient.getHashForCurrentCommit(); | ||
|
||
const dependabotVersionUpdateHandler = new DependabotVersionUpdateHandler( | ||
baseRef, | ||
headRef, | ||
gitClient, | ||
githubClient, | ||
testWorkingDir, | ||
ghContextMocked | ||
); | ||
|
||
await dependabotVersionUpdateHandler.handleVersionUpdate(); | ||
|
||
const changesetFilePath = path.join( | ||
testWorkingDir, | ||
`.changeset/dependabot-${headRef}.md` | ||
); | ||
|
||
await assertChangesetFile( | ||
changesetFilePath, | ||
[cantaloupePackageName, platypusPackageName], | ||
pullRequestBody | ||
); | ||
assert.deepEqual(labelPullRequestMocked.mock.calls[0].arguments, [ | ||
1, | ||
['run-e2e'], | ||
]); | ||
assert.deepEqual(gitPushMocked.mock.callCount(), 1); | ||
}); | ||
}); | ||
|
||
const setPackageToPublic = async (packagePath: string) => { | ||
const packageJson = await readPackageJson(packagePath); | ||
packageJson.publishConfig = { | ||
access: 'public', | ||
}; | ||
await writePackageJson(packagePath, packageJson); | ||
}; | ||
|
||
const setPackageDependencies = async ( | ||
packagePath: string, | ||
dependencies: Record<string, string> | ||
) => { | ||
const packageJson = await readPackageJson(packagePath); | ||
packageJson.dependencies = dependencies; | ||
await writePackageJson(packagePath, packageJson); | ||
}; | ||
|
||
const assertChangesetFile = async ( | ||
filePath: string, | ||
packageNames: string[], | ||
message: string | ||
) => { | ||
const changesetFileContent = await fsp.readFile(filePath, 'utf-8'); | ||
const frontmatterContent = packageNames | ||
.map((name) => `'${name}': patch`) | ||
.join(EOL); | ||
|
||
const expectedContent = `---${EOL}${frontmatterContent}${EOL}---${EOL}${EOL}${message}${EOL}`; | ||
|
||
assert.deepEqual(changesetFileContent, expectedContent); | ||
}; |
Oops, something went wrong.