diff --git a/src/strategies/python.ts b/src/strategies/python.ts index c1ac89b06..db9805aa6 100644 --- a/src/strategies/python.ts +++ b/src/strategies/python.ts @@ -26,6 +26,7 @@ import { import {PythonFileWithVersion} from '../updaters/python/python-file-with-version'; import {FileNotFoundError} from '../errors'; import {filterCommits} from '../util/filter-commits'; +import {PythonReadme} from '../updaters/python/python-readme'; const CHANGELOG_SECTIONS = [ {type: 'feat', section: 'Features'}, @@ -79,6 +80,14 @@ export class Python extends BaseStrategy { }), }); + updates.push({ + path: this.addPath('README.md'), + createIfMissing: false, + updater: new PythonReadme({ + version, + }), + }); + const parsedPyProject = await this.getPyProject( this.addPath('pyproject.toml') ); diff --git a/src/updaters/python/python-readme.ts b/src/updaters/python/python-readme.ts new file mode 100644 index 000000000..7fa2331fe --- /dev/null +++ b/src/updaters/python/python-readme.ts @@ -0,0 +1,30 @@ +import {DefaultUpdater} from '../default'; + +/** + * Updates a README.md file + */ +export class PythonReadme extends DefaultUpdater { + /** + * Given initial file contents, return updated contents. + * @param {string} content The initial content + * @returns {string} The updated content + */ + updateContent(content: string): string { + // differs for windows vs. linux/ios + const newlineType = content.includes('\r\n') ? '\r\n' : '\n'; + + if (this.version.preRelease) { + // it's a pre-release, so add the pre-release flag if it's missing + return content.replace( + /^# install from PyPI\r?\n^pip install (\S+)$/gm, + `# install from PyPI${newlineType}pip install --pre $1` + ); + } else { + // it's not a pre-release, so remove the pre-release flag if it's present + return content.replace( + /^# install from PyPI\r?\n^pip install --pre (\S+)$/gm, + `# install from PyPI${newlineType}pip install $1` + ); + } + } +} diff --git a/test/strategies/python.ts b/test/strategies/python.ts index e31419295..e3d9a7222 100644 --- a/test/strategies/python.ts +++ b/test/strategies/python.ts @@ -28,6 +28,8 @@ import {SetupPy} from '../../src/updaters/python/setup-py'; import {Changelog} from '../../src/updaters/changelog'; import {ChangelogJson} from '../../src/updaters/changelog-json'; import snapshot = require('snap-shot-it'); +import {PullRequestBody} from '../../src/util/pull-request-body'; +import {PythonReadme} from '../../src/updaters/python/python-readme'; const sandbox = sinon.createSandbox(); const fixturesPath = './test/fixtures/strategies/python'; @@ -164,6 +166,39 @@ describe('Python', () => { assertHasUpdate(updates, 'pyproject.toml', PyProjectToml); }); + it('finds and updates a README.md', async () => { + const strategy = new Python({ + targetBranch: 'main', + github, + component: 'google-cloud-automl', + }); + sandbox + .stub(github, 'getFileContentsOnBranch') + .resolves( + buildGitHubFileContent( + './test/updaters/fixtures', + 'README-python-pre.md' + ) + ); + sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]); + const release = await strategy.buildReleasePullRequest({ + commits: COMMITS, + latestRelease: await strategy.buildRelease({ + title: 'chore(main): release v1.2.3', + headBranchName: 'release-please/branches/main', + baseBranchName: 'main', + number: 1234, + body: new PullRequestBody([]).toString(), + labels: [], + files: [], + sha: 'abc123', + }), + }); + const updates = release!.updates; + + assertHasUpdate(updates, 'README.md', PythonReadme); + }); + it('finds and updates a version.py file', async () => { const strategy = new Python({ targetBranch: 'main', diff --git a/test/updaters/fixtures/README-python-no-pre.md b/test/updaters/fixtures/README-python-no-pre.md new file mode 100644 index 000000000..d462d7fac --- /dev/null +++ b/test/updaters/fixtures/README-python-no-pre.md @@ -0,0 +1,6 @@ +## Installation + +```sh +# install from PyPI +pip install test-repo +``` \ No newline at end of file diff --git a/test/updaters/fixtures/README-python-pre.md b/test/updaters/fixtures/README-python-pre.md new file mode 100644 index 000000000..2d5b1255e --- /dev/null +++ b/test/updaters/fixtures/README-python-pre.md @@ -0,0 +1,6 @@ +## Installation + +```sh +# install from PyPI +pip install --pre test-repo +``` \ No newline at end of file diff --git a/test/updaters/python-readme.ts b/test/updaters/python-readme.ts new file mode 100644 index 000000000..3eb7f6640 --- /dev/null +++ b/test/updaters/python-readme.ts @@ -0,0 +1,50 @@ +import {readFileSync} from 'fs'; +import {resolve} from 'path'; +import {describe, it} from 'mocha'; +import {expect} from 'chai'; +import {Version} from '../../src/version'; +import {PythonReadme} from '../../src/updaters/python/python-readme'; + +const fixturesPath = './test/updaters/fixtures'; + +describe('PythonReadme', () => { + const withPreFlag = readFileSync( + resolve(fixturesPath, 'README-python-pre.md'), + 'utf8' + ); + + const withoutPreFlag = readFileSync( + resolve(fixturesPath, 'README-python-no-pre.md'), + 'utf8' + ); + + it('makes no changes if there is a --pre on the install instructions in a README for a prerelease version', async () => { + const readmeUpdater = new PythonReadme({ + version: Version.parse('0.6.0-alpha.1'), + }); + expect(readmeUpdater.updateContent(withPreFlag)).to.equal(withPreFlag); + }); + + it('makes no changes if there is no --pre on the install instructions in a README for a non-prerelease version', async () => { + const readmeUpdater = new PythonReadme({ + version: Version.parse('0.6.0'), + }); + expect(readmeUpdater.updateContent(withoutPreFlag)).to.equal( + withoutPreFlag + ); + }); + + it('adds --pre if there is no --pre on the install instructions in a README for a prerelease version', async () => { + const readmeUpdater = new PythonReadme({ + version: Version.parse('0.6.0-alpha.1'), + }); + expect(readmeUpdater.updateContent(withoutPreFlag)).to.equal(withPreFlag); + }); + + it('removes --pre if there is a --pre on the install instructions in a README for a non-prerelease version', async () => { + const readmeUpdater = new PythonReadme({ + version: Version.parse('0.6.0'), + }); + expect(readmeUpdater.updateContent(withPreFlag)).to.equal(withoutPreFlag); + }); +});