diff --git a/package.json b/package.json index aee0aef..1989686 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,10 @@ "@alicloud/fc2": "^2.6.6", "@alicloud/fc20230330": "4.6.7", "@alicloud/pop-core": "^1.8.0", + "@serverless-cd/srm-aliyun-oss": "^0.0.1-beta.8", "@serverless-cd/srm-aliyun-pop-core": "^0.0.8-beta.1", "@serverless-cd/srm-aliyun-ram20150501": "^0.0.2-beta.9", "@serverless-cd/srm-aliyun-sls20201230": "0.0.5-beta.3", - "@serverless-cd/srm-aliyun-oss": "^0.0.1-beta.8", "@serverless-devs/diff": "^0.0.3-beta.6", "@serverless-devs/downloads": "^0.0.7", "@serverless-devs/load-component": "^0.0.9", diff --git a/src/subCommands/deploy/impl/function.ts b/src/subCommands/deploy/impl/function.ts index c55048f..67ca76a 100644 --- a/src/subCommands/deploy/impl/function.ts +++ b/src/subCommands/deploy/impl/function.ts @@ -2,6 +2,7 @@ import _ from 'lodash'; import { diffConvertYaml } from '@serverless-devs/diff'; import inquirer from 'inquirer'; import fs from 'fs'; +import os from 'os'; import assert from 'assert'; import path from 'path'; import { yellow } from 'chalk'; @@ -21,6 +22,7 @@ import { ICredentials } from '@serverless-devs/component-interface'; import { calculateCRC64, getFileSize, parseAutoConfig, checkFcDir } from '../../../utils'; import OSS from '../../../resources/oss'; import { setNodeModulesBinPermissions } from '../../../resources/fc/impl/utils'; +import downloads from '@serverless-devs/downloads'; type IType = 'code' | 'config' | boolean; interface IOpts { @@ -277,12 +279,18 @@ export default class Service extends Base { return true; } - let zipPath: string = path.isAbsolute(codeUri) - ? codeUri - : path.join(this.inputs.baseDir, codeUri); + let zipPath: string; + let downloadedTempDir = ''; + // 处理不同类型的 codeUri + if (codeUri.startsWith('http://') || codeUri.startsWith('https://')) { + zipPath = await this._downloadFromUrl(codeUri); + downloadedTempDir = path.dirname(zipPath); + } else { + zipPath = path.isAbsolute(codeUri) ? codeUri : path.join(this.inputs.baseDir, codeUri); + } logger.debug(`Code path absolute path: ${zipPath}`); - const needZip = this._assertNeedZip(codeUri); + const needZip = this._assertNeedZip(zipPath); logger.debug(`Need zip file: ${needZip}`); let generateZipFilePath = ''; @@ -330,9 +338,58 @@ export default class Service extends Base { } } + if (downloadedTempDir) { + try { + logger.debug(`Removing temp download dir: ${downloadedTempDir}`); + fs.rmSync(downloadedTempDir, { recursive: true, force: true }); + } catch (ex) { + logger.debug(`Unable to remove temp download dir: ${downloadedTempDir}`); + } + } + return true; } + /** + * 从URL下载文件到本地临时目录 + */ + private async _downloadFromUrl(url: string): Promise { + logger.info(`Downloading code from URL: ${url}`); + + // 创建临时目录 + const tempDir = path.join(os.tmpdir(), 'fc_code_download'); + let downloadPath: string; + + try { + // 从URL获取文件名 + const urlPath = new URL(url).pathname; + const parsedPathName = path.parse(urlPath).name; + const filename = path.basename(urlPath) || `downloaded_code_${Date.now()}`; + downloadPath = path.join(tempDir, filename); + + await downloads(url, { + dest: tempDir, + filename: parsedPathName, + extract: false, + }); + + logger.debug(`Downloaded file to: ${downloadPath}`); + + // 返回下载文件路径,由主流程决定是否需要压缩 + return downloadPath; + } catch (error) { + // 如果下载失败,清理临时目录 + try { + fs.rmSync(tempDir, { recursive: true, force: true }); + logger.debug(`Cleaned up temporary directory after error: ${tempDir}`); + } catch (cleanupError) { + logger.debug(`Failed to clean up temporary directory: ${cleanupError.message}`); + } + + throw new Error(`Failed to download code from URL: ${error.message}`); + } + } + /** * 生成 auto 资源,非 FC 资源,主要指 vpc、nas、log、role(oss mount 挂载点才有) */