3 2 2025-03-04 (C) Questetra, Inc. (MIT License) This item gets a specified file from a repository on GitHub. この工程は、GitHub のリポジトリから指定したファイルを取得します。 https://support.questetra.com/bpmn-icons/service-task-github-file-get/ https://support.questetra.com/ja/bpmn-icons/service-task-github-file-get/ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAABM9JREFUWEfF V2tQlFUYfs4ugiKgePkTiE3gCIssGWRhg1EwaE2OUZNjVDIFEwyJM12MSZKgokkNUdZNMhwCCg0p Bi8UxGVRblkgLHFJ12ZipImBLiAOg7h7mvfT/dz99lt2sR+8v3bPe3vOez0fw/+gqKgoF1LX6XQ3 79YMc1bxvuBgP2ZSRjHGH4SJqcCwGsCi2/pj4PgVCt7HOfuJK4y633p7B52x7RBAgCo0GCYeD4bn AKxyxiiAy+A4CQUrM/R1986kYxdAWFjYvH8nb6YoOE/igNpJx1ZiDNCbGCtcvMCloKOjY1rOhiyA ALXal93gb3PG0u7GsVSHca7hrmyfQa+/asOTHpBzTCMLQKIj5wqFAiaTyZGYmX8M85AlBWEVAQr7 +PUbufZu7uvrg+SkV3B/aAj8VqyAu7u7AGB09C8MXLqEH+oacKK8wi4gioTXQtc3LdNhBcBfFZrG OM+Xs7AjNRlpqSmgW89Evw8OIiExGUNDf8iKccZ2Xunr1piZIgCqdsZ5mbTgvL0Xo7ysFPeu9HM2 1EJU9uXm4VhRiY0OFSZnLN7cHXcABKpzwLBbqlH1zddQBQU67dxScGv8dlzs6rbV5fjIMKDPIIYA gIaMwqSsk/b5i/Hb8N677wgGJicnsSfrA6S9loKVfn7CLaempqBUKuHq6gqj0Sjkf8H8+Xgmboug MzY2hnWPRMkV6mWTwhhDw0oA4B+k3s6AYkuoi7y80N7cCBcXYdqCchuzabPwe/nyZRgZGRXFyanS RYmJieuIeGgdSoo+F3nfVlYhPSPTJgocSLjSry8RAASoQjTgbIelVPy2rcjOFKIk0MjoKNZviHaY Crr93pz3Rbmx8XGEPxxpq8f4YUNfT9otAIHqejA8bil1+GAuNsbGiEd0C7qNI6IuudDaBIqgmQJD 1sJolMwLjgbDgD76FoAgNU0oH0vjjbXVoL4nonyvXrPWkW+Rn5+3H09sjBX/U1u2trVL9YcM/Xpf Riv16vDf/wDwsJT45eIFuLm5CUdUYIEhDzgN4OOcbDwb97Qor9EWIF97RKo/YejXe9oF0Ha+AcuW LhWV1j8abVV4M6GpPHkca4JVoshb6btRdfqsPAB7Kag48SVC1SGiErUYtaEjWrLEGy26OrF7SD7y sVj8OTwsnwJ7RUgdQJ1gSY4KkSJGwH187hHV7KbPqghl2pBGcPv5RmH2U89T7xNRO3Z2diEjMxvU YkQ0sOK2bBbCLt0V39XUYufru2wDZ9mGcoOINPI+2YunntyE6elpYcq99MLzgiGacOERG0SjSS8n IH3XGzZOqHvCIyJx7dqEDc9qENkbxR4eC9FUXwMvT090detxvLwCqwL8cfpMNfr6B0SjFJ3Wpnob J3n5WnxacFSubKxH8e06kF1GVFS11aeEwUKjVt/TA925ZhQVl4qG6V3Q/XOblSPtkaM4qNHK16x0 GQkA7Kxj4lE9fFH4mbgVzzW3IPHVVNG4p6cHOn9sEf7Tgtp/4BCKS7+SdW53HZP0TA8S4lNbfpi9 B1WnzqKw6M7uooX1/ZlK1NTW4cAhje3YtYBi90FCMo6eZPLxdP7U4ZNMSMUsHqXOuxYkHT9KzQbn 9FluBjGnHyaWoZ2zTzNpfufs43SWhTZr8f8AaTovPzYDLOEAAAAASUVORK5CYII= { const auth = httpClient.createAuthSettingToken('Personal Access Token', 'github-token-12345'); configs.putObject('conf_Auth', auth); // 文字型データ項目を準備して、config に指定 const repositoryUrlDef = engine.createDataDefinition('リポジトリURL', 2, 'q_RepositoryUrl', 'STRING_TEXTFIELD'); configs.putObject('conf_RepositoryUrl', repositoryUrlDef); // 文字型データ項目の値(リポジトリURL)を指定 engine.setData(repositoryUrlDef, repositoryUrl); configs.put('conf_Path', path); // 文字型データ項目を準備して、config に指定 const branchDef = engine.createDataDefinition('ブランチ', 3, 'q_Branch', 'STRING_TEXTFIELD'); configs.putObject('conf_Branch', branchDef); // 文字型データ項目の値(ブランチ)を指定 engine.setData(branchDef, branch); // 文字型データ項目を準備して、config に指定 const fileShaDef = engine.createDataDefinition('ファイルSHA', 4, 'q_SHA', 'STRING_TEXTFIELD'); configs.putObject('conf_Hash', fileShaDef); // 文字型データ項目の値(S)を指定 engine.setData(fileShaDef, '事前文字列'); // ファイル型データ項目を準備して、config に指定 const filesDef = engine.createDataDefinition('ファイル', 5, 'q_files', 'FILE'); configs.putObject('conf_File', filesDef); engine.setData(filesDef, files); return { fileShaDef, filesDef }; }; /** * 異常系のテスト * @param errorMsg */ const assertError = (errorMsg) => { let failed = false; try { main(); } catch (e) { failed = true; expect(e.message).toEqual(errorMsg); } if (!failed) { fail('No error was thrown.'); } }; /** * conf_RepositoryUrl にデータ項目を設定しているが、そのデータ項目の値が空でエラーになる場合 */ test("Repository's URL is blank - Repository's URL specified by String Data", () => { prepareConfigs(null, 'path1/test.txt', 'branchQ', null); assertError("Repository's URL is blank."); }); /** * リポジトリURLが不正 */ test("Invalid repository URL - handle specified by String Data", () => { prepareConfigs("https://invalid.com/user1Org/user1Org123", 'folder0', '', null); assertError("Invalid repository URL."); }); /** * ファイルパスが空 */ test('File Path is blank', () => { prepareConfigs("https://github.com/user1Org/user1Org123", '', 'branch2', null); assertError('File Path is blank.'); }); /** * conf_Hash conf_File が未設定でエラーになる場合 */ test('Neither of Data Items to save result are set - neither C5 nor C6 are set ', () => { prepareConfigs("https://github.com/user1Org/user1Org456", 'path', 'branch', null); //conf_Hash と conf_File を空で上書き configs.put('conf_Hash', ''); configs.put('conf_File', ''); assertError('No data item to save the result is set.'); }); /** * リクエストのテスト(ファイルの情報を取得する) * @param {Object} request * @param request.url * @param request.method * @param ownerAndRepo * @param path * @param branch */ const assertGetFileInfomationRequest = ({ url, method }, ownerAndRepo, path, branch) => { expect(url).toEqual(`https://api.github.com/repos/${ownerAndRepo}/contents/${path}?ref=${branch}`); expect(method).toEqual('GET'); }; /** * ファイルの情報を取得する API リクエストでエラー */ test('GET file infomation Failed', () => { prepareConfigs("https://github.com/user1Org/user1Org123", 'folder1/file1.txt', 'branch1'); httpClient.setRequestHandler((request) => { assertGetFileInfomationRequest(request, 'user1Org/user1Org123', 'folder1/file1.txt', 'branch1'); return httpClient.createHttpResponse(404, 'application/json', '{}'); }); assertError('Failed to get file info. status: 404'); }); /** * ファイル情報取得 API のレスポンスボディを作成 * @param {String} type * @param {String} path * @returns {String} response */ const createResponse = (type, path, string) => { const name = path.split("/").pop(); const responseObj = { type, encoding: "base64", size: 5362, name, path, content: `content1234567890${string}`, sha: `sha123456789012345678901234567890${string}` } return JSON.stringify(responseObj); }; /** * ファイル情報取得 API のレスポンスボディを作成(1 MB を超えるサイズ) * @param {String} type * @param {String} path * @returns {String} response */ const createOver1MBResponse = (type, path, string) => { const name = path.split("/").pop(); const responseObj = { type, size: 1048577, name, path, content: '', sha: `sha123456789012345678901234567890${string}` } return JSON.stringify(responseObj); }; /** * ファイルパスがフォルダタイプでエラー */ test('failed - path is folder', () => { prepareConfigs("https://github.com/user1Org/user1Org456", 'folder2', 'branch2'); httpClient.setRequestHandler((request) => { assertGetFileInfomationRequest(request, 'user1Org/user1Org456', 'folder2', 'branch2'); return httpClient.createHttpResponse(200, 'application/json', createResponse('dir', 'folder2')); }); assertError('Resource is not a file.'); }); /** * SHA 取得成功 * ブランチ無 * ダウンロードファイルを保存するファイル型データ項目を設定していない */ test('Succeed - SHA get', () => { const { fileShaDef, filesDef } = prepareConfigs("https://github.com/user1Org/user1Org100", 'fileQ.txt', '', null); //conf_File を空で上書き configs.put('conf_File', ''); httpClient.setRequestHandler((request) => { assertGetFileInfomationRequest(request, 'user1Org/user1Org100', 'fileQ.txt', ''); return httpClient.createHttpResponse(200, 'application/json', createResponse('file', 'fileQ.txt', 'string0')); }); main(); expect(engine.findData(fileShaDef)).toEqual('sha123456789012345678901234567890string0'); }); /** * リクエストのテスト(ファイルの blob を取得する) * @param {Object} request * @param request.url * @param request.method * @param ownerAndRepo * @param sha */ const assertGetFileBlobRequest = ({ url, method }, ownerAndRepo, sha) => { expect(url).toEqual(`https://api.github.com/repos/${ownerAndRepo}/git/blobs/${sha}`); expect(method).toEqual('GET'); }; /** * ファイルの blob を取得する API リクエストでエラー */ test('GETBlob Failed', () => { prepareConfigs("https://github.com/user1/user1repo", 'folder111/file333.txt', 'branch2'); const filesDef = engine.createDataDefinition('ファイル', 5, 'q_files', 'FILE'); configs.putObject('conf_File', filesDef); engine.setData(filesDef, null); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetFileInfomationRequest(request, 'user1/user1repo', 'folder111/file333.txt', 'branch2'); reqCount++; return httpClient.createHttpResponse(200, 'application/json', createResponse('file', 'folder111/file333.txt', 'string0')); } assertGetFileBlobRequest(request, 'user1/user1repo', 'sha123456789012345678901234567890string0'); return httpClient.createHttpResponse(404, 'application/vnd.github.raw+json', '{}'); }); assertError('Failed to download. status: 404'); }); /** * ファイルのテスト * @param file * @param name * @param body * @param contentType */ const assertFile = (file, name, body, contentType) => { expect(file.getName()).toEqual(name); expect(file.getContentType()).toEqual(contentType); const text = fileRepository.readFile(file, 'UTF-8'); expect(text).toEqual(body); }; /** * SHA 取得成功 * ファイルダウンロード 成功 * 事前にファイルが添付されている */ test('Succeed - both sha and file saved ', () => { const attachedFiles = new java.util.ArrayList(); attachedFiles.add(engine.createQfile('test.html', 'text/html', '')); attachedFiles.add(engine.createQfile('test.xml', 'text/xml', 'test')); const { fileShaDef, filesDef } = prepareConfigs("https://github.com/user1/user1repo", 'folder2/file3.txt', 'branch2', attachedFiles); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetFileInfomationRequest(request, 'user1/user1repo', 'folder2/file3.txt', 'branch2'); reqCount++; return httpClient.createHttpResponse(200, 'application/json', createResponse('file', 'folder2/file3.txt', 'string1')); } assertGetFileBlobRequest(request, 'user1/user1repo', 'sha123456789012345678901234567890string1'); return httpClient.createHttpResponse(200, 'text/plain; charset=UTF-8', 'test'); }); main(); expect(engine.findData(fileShaDef)).toEqual('sha123456789012345678901234567890string1'); const files = engine.findData(filesDef); expect(files.size()).toEqual(3); assertFile(files.get(2), 'file3.txt', 'test', 'text/plain'); }); /** * SHA 取得成功 * ファイルダウンロード 成功 * ファイルのサイズが 1MB を超える * ファイル名 が QBPMS の制限長を超える * SHA を保存するデータ項目を設定していない */ test('Succeed - file saved - file size is over 1 MB', () => { const fileName = 'a'.repeat(FILE_NAME_MAX_LENGTH) + '.txt'; const { fileShaDef, filesDef } = prepareConfigs("https://github.com/user1/user1repo", fileName, 'branchC', null); //conf_Hash を空で上書き configs.put('conf_Hash', ''); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetFileInfomationRequest(request, 'user1/user1repo', fileName, 'branchC'); reqCount++; return httpClient.createHttpResponse(200, 'application/json', createOver1MBResponse('file', fileName, 'string2')); } assertGetFileBlobRequest(request, 'user1/user1repo', 'sha123456789012345678901234567890string2'); return httpClient.createHttpResponse(200, 'text/html; charset=UTF-8', 'テスト'); }); main(); const files = engine.findData(filesDef); expect(files.size()).toEqual(1); assertFile(files.get(0), 'a'.repeat(FILE_NAME_MAX_LENGTH - 3) + '...', 'テスト', 'text/html'); }); /** * SHA 取得成功 * ファイルダウンロード 成功 * URL と ブランチを固定値で指定 */ test('Succeed - url and branch are fixed value ', () => { const { fileShaDef, filesDef } = prepareConfigs('', 'folder2/file3.xml', '', null); //URL と ブランチを固定値で指定 configs.put('conf_RepositoryUrl', 'https://github.com/user1/user1repo'); configs.put('conf_Branch', 'branchQ'); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetFileInfomationRequest(request, 'user1/user1repo', 'folder2/file3.xml', 'branchQ'); reqCount++; return httpClient.createHttpResponse(200, 'application/json', createResponse('file', 'folder2/file3.xml', 'stringQ')); } assertGetFileBlobRequest(request, 'user1/user1repo', 'sha123456789012345678901234567890stringQ'); return httpClient.createHttpResponse(200, 'text/xml; charset=UTF-8', 'test'); }); main(); expect(engine.findData(fileShaDef)).toEqual('sha123456789012345678901234567890stringQ'); const files = engine.findData(filesDef); expect(files.size()).toEqual(1); assertFile(files.get(0), 'file3.xml', 'test', 'text/xml'); }); ]]>