diff --git a/.changeset/two-cougars-breathe.md b/.changeset/two-cougars-breathe.md new file mode 100644 index 0000000000..0b61078e85 --- /dev/null +++ b/.changeset/two-cougars-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fixed bug where the mode of an executable file was ignored diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index ea29866485..643ab6e30c 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -64,7 +64,7 @@ "luxon": "^2.0.2", "morgan": "^1.10.0", "nunjucks": "^3.2.3", - "octokit-plugin-create-pull-request": "^3.9.3", + "octokit-plugin-create-pull-request": "^3.10.0", "uuid": "^8.2.0", "winston": "^3.2.1", "yaml": "^1.10.0" diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts index ed72b14a65..dbb5f3caff 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts @@ -98,7 +98,11 @@ describe('createPublishGithubPullRequestAction', () => { { commit: 'Create my new app', files: { - 'file.txt': 'Hello there!', + 'file.txt': { + encoding: 'utf-8', + content: 'Hello there!', + mode: '100644', + }, }, }, ], @@ -167,7 +171,11 @@ describe('createPublishGithubPullRequestAction', () => { { commit: 'Create my new app', files: { - 'foo.txt': 'Hello there!', + 'foo.txt': { + content: 'Hello there!', + encoding: 'utf-8', + mode: '100644', + }, }, }, ], @@ -221,7 +229,79 @@ describe('createPublishGithubPullRequestAction', () => { { commit: 'Create my new app', files: { - 'file.txt': 'Hello there!', + 'file.txt': { + content: 'Hello there!', + encoding: 'utf-8', + mode: '100644', + }, + }, + }, + ], + }); + }); + + it('creates outputs for the url', async () => { + await instance.handler(ctx); + + expect(ctx.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + }); + afterEach(() => { + mockFs.restore(); + jest.resetAllMocks(); + }); + }); + + describe('with executable file', () => { + let input: GithubPullRequestActionInput; + let ctx: ActionContext; + + beforeEach(() => { + input = { + repoUrl: 'github.com?owner=myorg&repo=myrepo', + title: 'Create my new app', + branchName: 'new-app', + description: 'This PR is really good', + }; + + mockFs({ + [workspacePath]: { + 'file.txt': mockFs.file({ + content: 'Hello there!', + mode: 33277, // File mode: 100755 + }), + }, + }); + + ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + }); + it('creates a pull request', async () => { + await instance.handler(ctx); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'myorg', + repo: 'myrepo', + title: 'Create my new app', + head: 'new-app', + body: 'This PR is really good', + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': { + content: 'Hello there!', + encoding: 'utf-8', + mode: '100755', + }, }, }, ], diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts index 253fd72b38..733fd673ff 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { readFile } from 'fs-extra'; +import fs from 'fs-extra'; import path from 'path'; import { parseRepoUrl } from './util'; @@ -194,7 +194,20 @@ export const createPublishGithubPullRequestAction = ({ }); const fileContents = await Promise.all( - localFilePaths.map(p => readFile(path.resolve(fileRoot, p))), + localFilePaths.map(filePath => { + const absPath = path.resolve(fileRoot, filePath); + const content = fs.readFileSync(absPath).toString(); + const fileStat = fs.statSync(absPath); + const isExecutable = fileStat.mode === 33277 // aka. 100755; + // See the properties of tree items + // in https://docs.github.com/en/rest/reference/git#trees + const githubTreeItemMode = isExecutable ? '100755' : '100644'; + return { + encoding: 'utf-8', + content: content, + mode: githubTreeItemMode, + }; + }), ); const repoFilePaths = localFilePaths.map(repoFilePath => { @@ -205,7 +218,7 @@ export const createPublishGithubPullRequestAction = ({ { files: zipObject( repoFilePaths, - fileContents.map(buf => buf.toString()), + fileContents, ), commit: title, },