From 7c8bad58f221f302fef134beb21e7cfec2b2c4bb Mon Sep 17 00:00:00 2001 From: SongJun Date: Wed, 22 Jul 2026 08:35:38 -0400 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=86=85=E9=83=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9C=8D=E5=8A=A1=E7=9A=84=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- download/dist/index.js | 16 ++++++++++++++-- upload/dist/index.js | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/download/dist/index.js b/download/dist/index.js index 0b08c35..09d8f17 100644 --- a/download/dist/index.js +++ b/download/dist/index.js @@ -2694,9 +2694,21 @@ function getResultsServiceUrl() { if (!resultsUrl) { throw new Error('Unable to get the ACTIONS_RESULTS_URL env variable'); } - return new URL(resultsUrl).origin; + const serviceUrl = new URL(resultsUrl); + if (serviceUrl.protocol === 'https:' && isDockerBridgeIPv4(serviceUrl.hostname)) { + serviceUrl.protocol = 'http:'; + } + return serviceUrl.origin; } exports.getResultsServiceUrl = getResultsServiceUrl; +function isDockerBridgeIPv4(hostname) { + const octets = hostname.split('.').map(Number); + return (octets.length === 4 && + octets.every(octet => Number.isInteger(octet) && octet >= 0 && octet <= 255) && + octets[0] === 172 && + octets[1] >= 16 && + octets[1] <= 31); +} function isGhes() { return false; } @@ -124958,4 +124970,4 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ module.exports = __webpack_exports__; /******/ /******/ })() -; \ No newline at end of file +; diff --git a/upload/dist/index.js b/upload/dist/index.js index 1acca9b..30783f1 100644 --- a/upload/dist/index.js +++ b/upload/dist/index.js @@ -3019,9 +3019,21 @@ function getResultsServiceUrl() { if (!resultsUrl) { throw new Error('Unable to get the ACTIONS_RESULTS_URL env variable'); } - return new URL(resultsUrl).origin; + const serviceUrl = new URL(resultsUrl); + if (serviceUrl.protocol === 'https:' && isDockerBridgeIPv4(serviceUrl.hostname)) { + serviceUrl.protocol = 'http:'; + } + return serviceUrl.origin; } exports.getResultsServiceUrl = getResultsServiceUrl; +function isDockerBridgeIPv4(hostname) { + const octets = hostname.split('.').map(Number); + return (octets.length === 4 && + octets.every(octet => Number.isInteger(octet) && octet >= 0 && octet <= 255) && + octets[0] === 172 && + octets[1] >= 16 && + octets[1] <= 31); +} function isGhes() { return false; } @@ -129412,4 +129424,4 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ module.exports = __webpack_exports__; /******/ /******/ })() -; \ No newline at end of file +; From b84b9d8e3f94c99728bc1250146e4dec7aa60f31 Mon Sep 17 00:00:00 2001 From: SongJun Date: Wed, 22 Jul 2026 08:43:48 -0400 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=86=85=E9=83=A8?= =?UTF-8?q?=E7=AD=BE=E5=90=8D=E6=96=87=E4=BB=B6=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- download/dist/index.js | 21 +++++++++-------- tests/internal-results-url.test.js | 36 ++++++++++++++++++++++++++++++ upload/dist/index.js | 21 +++++++++-------- 3 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 tests/internal-results-url.test.js diff --git a/download/dist/index.js b/download/dist/index.js index 09d8f17..331beef 100644 --- a/download/dist/index.js +++ b/download/dist/index.js @@ -2150,7 +2150,7 @@ function downloadArtifactInternal(artifactId, options) { core.info(`Redirecting to blob download url: ${scrubQueryParameters(signedUrl)}`); try { core.info(`Starting download of artifact to: ${downloadPath}`); - yield streamExtract(signedUrl, downloadPath); + yield streamExtract((0, config_1.normalizeDockerBridgeUrl)(signedUrl), downloadPath); core.info(`Artifact download completed successfully.`); } catch (error) { @@ -2673,7 +2673,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getConcurrency = exports.getGitHubWorkspaceDir = exports.isGhes = exports.getResultsServiceUrl = exports.getRuntimeToken = exports.getUploadChunkSize = void 0; +exports.getConcurrency = exports.getGitHubWorkspaceDir = exports.isGhes = exports.normalizeDockerBridgeUrl = exports.getResultsServiceUrl = exports.getRuntimeToken = exports.getUploadChunkSize = void 0; const os_1 = __importDefault(__nccwpck_require__(22037)); // Used for controlling the highWaterMark value of the zip that is being streamed // The same value is used as the chunk size that is use during upload to blob storage @@ -2694,20 +2694,23 @@ function getResultsServiceUrl() { if (!resultsUrl) { throw new Error('Unable to get the ACTIONS_RESULTS_URL env variable'); } - const serviceUrl = new URL(resultsUrl); - if (serviceUrl.protocol === 'https:' && isDockerBridgeIPv4(serviceUrl.hostname)) { - serviceUrl.protocol = 'http:'; - } - return serviceUrl.origin; + return new URL(normalizeDockerBridgeUrl(resultsUrl)).origin; } exports.getResultsServiceUrl = getResultsServiceUrl; +function normalizeDockerBridgeUrl(rawUrl) { + const serviceUrl = new URL(rawUrl); + if (serviceUrl.protocol === 'https:' && isDockerBridgeIPv4(serviceUrl.hostname)) { + return `http:${rawUrl.slice('https:'.length)}`; + } + return rawUrl; +} +exports.normalizeDockerBridgeUrl = normalizeDockerBridgeUrl; function isDockerBridgeIPv4(hostname) { const octets = hostname.split('.').map(Number); return (octets.length === 4 && octets.every(octet => Number.isInteger(octet) && octet >= 0 && octet <= 255) && octets[0] === 172 && - octets[1] >= 16 && - octets[1] <= 31); + octets[1] === 19); } function isGhes() { return false; diff --git a/tests/internal-results-url.test.js b/tests/internal-results-url.test.js new file mode 100644 index 0000000..0f2d0c2 --- /dev/null +++ b/tests/internal-results-url.test.js @@ -0,0 +1,36 @@ +const assert = require('assert/strict'); +const fs = require('fs'); +const vm = require('vm'); + +const cases = [ + [ + 'https://172.19.153.70:62066/twirp/path?sig=a%2Bb%3D&expires=2026-07-22+21%253A28', + 'http://172.19.153.70:62066/twirp/path?sig=a%2Bb%3D&expires=2026-07-22+21%253A28' + ], + ['http://172.19.153.70:62066/twirp/path?sig=a%2Bb%3D', 'http://172.19.153.70:62066/twirp/path?sig=a%2Bb%3D'], + ['https://172.18.4.8:62066/twirp/path', 'https://172.18.4.8:62066/twirp/path'], + ['https://172.20.4.8:62066/twirp/path', 'https://172.20.4.8:62066/twirp/path'], + ['https://172.31.4.8:62066/twirp/path', 'https://172.31.4.8:62066/twirp/path'], + ['https://git.data-it.tech/api/v1', 'https://git.data-it.tech/api/v1'] +]; + +for (const file of ['upload/dist/index.js', 'download/dist/index.js']) { + const source = fs.readFileSync(file, 'utf8'); + const begin = source.indexOf('function getResultsServiceUrl()'); + const end = source.indexOf('function isGhes()', begin); + assert.ok(begin >= 0 && end >= 0, `${file}: helper segment not found`); + const context = {process: {env: {}}, URL, exports: {}}; + vm.runInNewContext(source.slice(begin, end), context); + for (const [input, expected] of cases) { + assert.equal(context.exports.normalizeDockerBridgeUrl(input), expected, `${file}: ${input}`); + } + context.process.env.ACTIONS_RESULTS_URL = cases[0][0]; + assert.equal(context.exports.getResultsServiceUrl(), 'http://172.19.153.70:62066', `${file}: results service origin`); +} + +const upload = fs.readFileSync('upload/dist/index.js', 'utf8'); +const download = fs.readFileSync('download/dist/index.js', 'utf8'); +assert.ok(upload.includes('new storage_blob_1.BlobClient((0, config_1.normalizeDockerBridgeUrl)(authenticatedUploadURL))')); +assert.ok(download.includes('yield streamExtract((0, config_1.normalizeDockerBridgeUrl)(signedUrl), downloadPath);')); + +console.log('internal results service address checks passed'); diff --git a/upload/dist/index.js b/upload/dist/index.js index 30783f1..3872468 100644 --- a/upload/dist/index.js +++ b/upload/dist/index.js @@ -2998,7 +2998,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getConcurrency = exports.getGitHubWorkspaceDir = exports.isGhes = exports.getResultsServiceUrl = exports.getRuntimeToken = exports.getUploadChunkSize = void 0; +exports.getConcurrency = exports.getGitHubWorkspaceDir = exports.isGhes = exports.normalizeDockerBridgeUrl = exports.getResultsServiceUrl = exports.getRuntimeToken = exports.getUploadChunkSize = void 0; const os_1 = __importDefault(__nccwpck_require__(22037)); // Used for controlling the highWaterMark value of the zip that is being streamed // The same value is used as the chunk size that is use during upload to blob storage @@ -3019,20 +3019,23 @@ function getResultsServiceUrl() { if (!resultsUrl) { throw new Error('Unable to get the ACTIONS_RESULTS_URL env variable'); } - const serviceUrl = new URL(resultsUrl); - if (serviceUrl.protocol === 'https:' && isDockerBridgeIPv4(serviceUrl.hostname)) { - serviceUrl.protocol = 'http:'; - } - return serviceUrl.origin; + return new URL(normalizeDockerBridgeUrl(resultsUrl)).origin; } exports.getResultsServiceUrl = getResultsServiceUrl; +function normalizeDockerBridgeUrl(rawUrl) { + const serviceUrl = new URL(rawUrl); + if (serviceUrl.protocol === 'https:' && isDockerBridgeIPv4(serviceUrl.hostname)) { + return `http:${rawUrl.slice('https:'.length)}`; + } + return rawUrl; +} +exports.normalizeDockerBridgeUrl = normalizeDockerBridgeUrl; function isDockerBridgeIPv4(hostname) { const octets = hostname.split('.').map(Number); return (octets.length === 4 && octets.every(octet => Number.isInteger(octet) && octet >= 0 && octet <= 255) && octets[0] === 172 && - octets[1] >= 16 && - octets[1] <= 31); + octets[1] === 19); } function isGhes() { return false; @@ -3307,7 +3310,7 @@ function uploadZipToBlobStorage(authenticatedUploadURL, zipUploadStream) { let uploadByteCount = 0; const maxConcurrency = (0, config_1.getConcurrency)(); const bufferSize = (0, config_1.getUploadChunkSize)(); - const blobClient = new storage_blob_1.BlobClient(authenticatedUploadURL); + const blobClient = new storage_blob_1.BlobClient((0, config_1.normalizeDockerBridgeUrl)(authenticatedUploadURL)); const blockBlobClient = blobClient.getBlockBlobClient(); core.debug(`Uploading artifact zip to blob storage with maxConcurrency: ${maxConcurrency}, bufferSize: ${bufferSize}`); const uploadCallback = (progress) => {