diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..11c8ac8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,48 @@ +name: Release + +on: + push: + branches: [master] + +jobs: + release: + name: Release + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Install Node.js and npm + uses: actions/setup-node@v1 + with: + node-version: 14.x + registry-url: https://registry.npmjs.org + + - name: Retrieve dependencies from cache + id: cacheNpm + uses: actions/cache@v2 + with: + path: | + ~/.npm + node_modules + key: npm-v14-${{ runner.os }}-refs/heads/master-${{ hashFiles('package.json') }} + restore-keys: npm-v14-${{ runner.os }}-refs/heads/master- + + - name: Install dependencies + if: steps.cacheNpm.outputs.cache-hit != 'true' + run: | + npm update --no-save + npm update --save-dev --no-save + - name: Releasing + run: | + npm run release + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + GIT_AUTHOR_NAME: slsplus + GIT_AUTHOR_EMAIL: slsplus.sz@gmail.com + GIT_COMMITTER_NAME: slsplus + GIT_COMMITTER_EMAIL: slsplus.sz@gmail.com diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..21b004e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,45 @@ +name: Test + +on: + pull_request: + branches: [master] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # Ensure connection with 'master' branch + fetch-depth: 2 + + - name: Install Node.js and npm + uses: actions/setup-node@v1 + with: + node-version: 14.x + registry-url: https://registry.npmjs.org + + - name: Retrieve dependencies from cache + id: cacheNpm + uses: actions/cache@v2 + with: + path: | + ~/.npm + node_modules + key: npm-v14-${{ runner.os }}-${{ github.ref }}-${{ hashFiles('package.json') }} + restore-keys: | + npm-v14-${{ runner.os }}-${{ github.ref }}- + npm-v14-${{ runner.os }}-refs/heads/master- + + - name: Install dependencies + if: steps.cacheNpm.outputs.cache-hit != 'true' + run: | + npm update --no-save + npm update --save-dev --no-save + - name: Running tests + run: npm run test + env: + TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} + TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..3840792 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,45 @@ +name: Validate + +on: + pull_request: + branches: [master] + +jobs: + lintAndFormatting: + name: Lint & Formatting + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # Ensure connection with 'master' branch + fetch-depth: 2 + + - name: Install Node.js and npm + uses: actions/setup-node@v1 + with: + node-version: 14.x + registry-url: https://registry.npmjs.org + + - name: Retrieve dependencies from cache + id: cacheNpm + uses: actions/cache@v2 + with: + path: | + ~/.npm + node_modules + key: npm-v14-${{ runner.os }}-${{ github.ref }}-${{ hashFiles('package.json') }} + restore-keys: | + npm-v14-${{ runner.os }}-${{ github.ref }}- + npm-v14-${{ runner.os }}-refs/heads/master- + + - name: Install dependencies + if: steps.cacheNpm.outputs.cache-hit != 'true' + run: | + npm update --no-save + npm update --save-dev --no-save + + - name: Validate Formatting + run: npm run prettier:fix + - name: Validate Lint rules + run: npm run lint:fix diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d78fad9..0000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: node_js - -node_js: - - 10 - -install: - - npm install - -# should change to serverless registry publish -jobs: - include: - # Define the release stage that runs semantic-release - - stage: release - node_js: 10.18 - # Advanced: optionally overwrite your default `script` step to skip the tests - # script: skip - deploy: - provider: script - skip_cleanup: true - on: - branch: master - script: - - npm run release diff --git a/CHANGELOG.md b/CHANGELOG.md index 825596d..5a5f73e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [0.1.0](https://github.com/serverless-components/tencent-laravel/compare/v0.0.8...v0.1.0) (2020-12-04) + + +### Bug Fixes + +* update deps ([82d8696](https://github.com/serverless-components/tencent-laravel/commit/82d8696e0b4446414f81cd398646b4f9410d602c)) + + +### Features + +* support no migration deploy ([9670f55](https://github.com/serverless-components/tencent-laravel/commit/9670f55e521b15886297b99d8d89d5fe10a90cac)) + ## [0.0.8](https://github.com/serverless-components/tencent-laravel/compare/v0.0.7...v0.0.8) (2020-09-07) diff --git a/README.md b/README.md index dd5e0a6..7a21b62 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,73 @@ [![Serverless PHP Laravel Tencent Cloud](https://img.serverlesscloud.cn/20191226/1577347087676-website_%E9%95%BF.png)](http://serverless.com) -# 腾讯云 Laravel Serverless Component +[![Build Status](https://github.com/serverless-components/tencent-laravel/workflows/Test/badge.svg?branch=master)](https://github.com/serverless-components/tencent-laravel/actions?query=workflow:Test) -## 简介 +
腾讯云 [Laravel](https://github.com/laravel/laravel) Serverless Component, 支持 `Laravel >= 6.0`。 -## 目录 +
-0. [准备](#0-准备) -1. [安装](#1-安装) -1. [配置](#2-配置) -1. [部署](#3-部署) -1. [移除](#4-移除) +特性介绍: -### 0. 准备 +- [x] **按需付费** - 按照请求的使用量进行收费,没有请求时无需付费 +- [x] **"0"配置** - 只需要关心项目代码,之后部署即可,Serverless Framework 会搞定所有配置。 +- [x] **极速部署** - 仅需几秒,部署你的整个 laravel 应用。 +- [x] **便捷协作** - 通过云端的状态信息和部署日志,方便的进行多人协作开发。 +- [x] **自定义域名** - 支持配置自定义域名及 HTTPS 访问 -#### 初始化 Laravel 项目 +
-在使用此组件之前,你需要先自己初始化一个 `laravel` 项目 +快速开始: -```bash -composer create-project --prefer-dist laravel/laravel serverless-laravel -``` +1. [**安装**](#1-安装) +2. [**创建**](#2-创建) +3. [**部署**](#3-部署) +4. [**配置**](#4-配置) +5. [**查看状态**](#5-查看状态) +6. [**移除**](#6-移除) -> 注意:Laravel 使用 Coposer 管理依赖的,所以你需要先自行安装 Composer,请参考 [官方安装文档](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos) +更多资源: -#### 修改 Laravel 项目 +- [**架构说明**](#架构说明) +- [**账号配置**](#账号配置) -由于云函数在执行时,只有 `/tmp` 可读写的,所以我们需要将 `laravel` 框架运行时的 `storage` 目录写到该目录下,为此需要修改 `bootstrap/app.php` 文件,在 `$app = new Illuminate\Foundation\Application` 后添加: +  -```php -$app->useStoragePath(env('APP_STORAGE', '/tmp')); -``` +### 1. 安装 -然后在根目录下的 `.env` 文件中新增如下配置: +通过 npm 安装最新版本的 Serverless Framework -```dotenv -# 视图文件编译路径 -VIEW_COMPILED_PATH=/tmp/storage/framework/views +```bash +$ npm install -g serverless +``` -# 由于是无服务函数,所以没法存储 session 在硬盘上,如果不需要 sessions,可以使用 array -# 如果需要你可以将 session 存储到 cookie 或者数据库中 -SESSION_DRIVER=array +### 2. 创建 -# 建议将错误日志输出到控制台,方便云端去查看 -LOG_CHANNEL=stderr +通过如下命令和模板链接,快速创建一个 laravel 应用: -# 应用的 storage 目录必须为 /tmp -APP_STORAGE=/tmp +```bash +$ serverless init laravel-starter --name serverless-laravel +$ cd example ``` -### 1. 安装 +### 3. 部署 -通过 npm 全局安装 [serverless cli](https://github.com/serverless/serverless) +在 `serverless.yml` 文件所在的项目根目录,运行以下指令进行部署: ```bash -$ npm install -g serverless +$ serverless deploy ``` -### 2. 配置 +部署时需要进行身份验证,如您的账号未 [登陆](https://cloud.tencent.com/login) 或 [注册](https://cloud.tencent.com/register) 腾讯云,您可以直接通过 `微信` 扫描命令行中的二维码进行授权登陆和注册。 -在项目根目录,创建 `serverless.yml` 文件,在其中进行如下配置 +> 注意: 如果希望查看更多部署过程的信息,可以通过`serverless deploy --debug` 命令查看部署过程中的实时日志信息。 -```bash -$ touch serverless.yml -``` +### 4. 配置 + +laravel 组件支持 0 配置部署,也就是可以直接通过配置文件中的默认值进行部署。但你依然可以修改更多可选配置来进一步开发该 laravel 项目。 + +以下是 laravel 组件的 `serverless.yml`配置示例: ```yml # serverless.yml @@ -77,7 +79,9 @@ app: appDemo stage: dev inputs: - src: ./ + src: + src: ./ + functionName: laravelDemo region: ap-guangzhou runtime: Php7 apigatewayConf: @@ -87,50 +91,58 @@ inputs: environment: release ``` -- [更多配置](https://github.com/serverless-components/tencent-laravel/tree/master/docs/configure.md) +点此查看[全量配置及配置说明](https://github.com/serverless-components/tencent-laravel/tree/master/docs/configure.md) -### 3. 部署 +当你根据该配置文件更新配置字段后,再次运行 `serverless deploy` 或者 `serverless` 就可以更新配置到云端。 -> 注意:**在部署前,你需要先清理本地运行的配置缓存,执行 `php artisan config:clear` 即可。** +### 5. 查看状态 -如您的账号未 [登陆](https://cloud.tencent.com/login) 或 [注册](https://cloud.tencent.com/register) 腾讯云,您可以直接通过 `微信` 扫描命令行中的二维码进行授权登陆和注册。 +在`serverless.yml`文件所在的目录下,通过如下命令查看部署状态: -通过 `sls` 命令进行部署,并可以添加 `--debug` 参数查看部署过程中的信息 +``` +$ serverless info +``` -```bash -$ sls deploy +### 6. 移除 + +在`serverless.yml`文件所在的目录下,通过以下命令移除部署的 laravel 服务。移除后该组件会对应删除云上部署时所创建的所有相关资源。 + +``` +$ serverless remove ``` -> 注意: `sls` 是 `serverless` 命令的简写。 +和部署类似,支持通过 `serverless remove --debug` 命令查看移除过程中的实时日志信息。 -### 4. 移除 +## 架构说明 -通过以下命令移除部署的 Laravel 服务。 +laravel 组件将在腾讯云账户中使用到如下 Serverless 服务: -```bash -$ sls remove -``` +- [x] **API 网关** - API 网关将会接收外部请求并且转发到 SCF 云函数中。 +- [x] **SCF 云函数** - 云函数将承载 laravel.js 应用。 +- [x] **CAM 访问控制** - 该组件会创建默认 CAM 角色用于授权访问关联资源。 +- [x] **COS 对象存储** - 为确保上传速度和质量,云函数压缩并上传代码时,会默认将代码包存储在特定命名的 COS 桶中。 +- [x] **SSL 证书服务** - 如果你在 yaml 文件中配置了 `apigatewayConf.customDomains` 字段,需要做自定义域名绑定并开启 HTTPS 时,也会用到证书管理服务和域名服务。Serverless Framework 会根据已经备案的域名自动申请并配置 SSL 证书。 -### 账号配置(可选) +## 账号配置 当前默认支持 CLI 扫描二维码登录,如您希望配置持久的环境变量/秘钥信息,也可以本地创建 `.env` 文件 +```console +$ touch .env # 腾讯云的配置信息 +``` + 在 `.env` 文件中配置腾讯云的 SecretId 和 SecretKey 信息并保存 -如果没有腾讯云账号,可以在此 [注册新账号](https://cloud.tencent.com/register)。 +如果没有腾讯云账号,可以在此[注册新账号](https://cloud.tencent.com/register)。 -如果已有腾讯云账号,可以在 [API 密钥管理](https://console.cloud.tencent.com/cam/capi) 中获取 `SecretId` 和`SecretKey`. +如果已有腾讯云账号,可以在[API 密钥管理](https://console.cloud.tencent.com/cam/capi)中获取 `SecretId` 和`SecretKey`. -```text +``` # .env TENCENT_SECRET_ID=123 TENCENT_SECRET_KEY=123 ``` -### 更多组件 - -可以在 [Serverless Components](https://github.com/serverless/components/blob/master/README.cn.md) repo 中查询更多组件的信息。 - ## License MIT License diff --git a/tests/integration.test.js b/__tests__/index.test.js similarity index 66% rename from tests/integration.test.js rename to __tests__/index.test.js index 8bef758..107d93b 100644 --- a/tests/integration.test.js +++ b/__tests__/index.test.js @@ -1,16 +1,10 @@ -const { generateId, getServerlessSdk } = require('./utils') -const execSync = require('child_process').execSync -const path = require('path') +const { generateId, getServerlessSdk } = require('./lib/utils') const axios = require('axios') -// set enough timeout for deployment to finish -jest.setTimeout(600000) - -// the yaml file we're testing against const instanceYaml = { org: 'orgDemo', app: 'appDemo', - component: 'laravel', + component: 'laravel@dev', name: `laravel-integration-tests-${generateId()}`, stage: 'dev', inputs: { @@ -20,16 +14,17 @@ const instanceYaml = { } } -// get credentials from process.env but need to init empty credentials object const credentials = { - tencent: {} + tencent: { + SecretId: process.env.TENCENT_SECRET_ID, + SecretKey: process.env.TENCENT_SECRET_KEY + } } -// get serverless construct sdk const sdk = getServerlessSdk(instanceYaml.org) -it('should successfully deploy laravel app', async () => { - const instance = await sdk.deploy(instanceYaml, { tencent: {} }) +it('should deploy success', async () => { + const instance = await sdk.deploy(instanceYaml, credentials) expect(instance).toBeDefined() expect(instance.instanceName).toEqual(instanceYaml.name) @@ -44,7 +39,7 @@ it('should successfully deploy laravel app', async () => { expect(response.data.includes('Laravel')).toBeTruthy() }) -it('should successfully remove laravel app', async () => { +it('should remove success', async () => { await sdk.remove(instanceYaml, credentials) result = await sdk.getInstance( instanceYaml.org, diff --git a/tests/utils.js b/__tests__/lib/utils.js similarity index 100% rename from tests/utils.js rename to __tests__/lib/utils.js diff --git a/docs/configure.md b/docs/configure.md index e178849..0495922 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -16,17 +16,12 @@ inputs: functionName: laravelDemo # 云函数名称 serviceName: mytest # api网关服务名称 runtime: Php7 # 运行环境 - serviceId: service-np1uloxw # api网关服务ID - src: ./src # 第一种为string时,会打包src对应目录下的代码上传到默认cos上。 - # src: # 第二种,部署src下的文件代码,并打包成zip上传到bucket上 - # src: ./src # 本地需要打包的文件目录 - # bucket: bucket01 # bucket name,当前会默认在bucket name后增加 appid 后缀, 本例中为 bucket01-appid - # exclude: # 被排除的文件或目录 - # - .env - # - node_modules - # src: # 第三种,在指定存储桶bucket中已经存在了object代码,直接部署 - # bucket: bucket01 # bucket name,当前会默认在bucket name后增加 appid 后缀, 本例中为 bucket01-appid - # object: cos.zip # bucket key 指定存储桶内的文件 + src: # 第二种,部署src下的文件代码,并打包成zip上传到bucket上 + src: ./src # 本地需要打包的文件目录 + # bucket: bucket01 # bucket name,存储桶名称 + # object: cos.zip # bucket key 指定存储桶内的文件 + exclude: # 被排除的文件或目录 + - .env layers: - name: layerName # layer名称 version: 1 # 版本 diff --git a/example/.env.example b/example/.env.example index eefba19..da50526 100644 --- a/example/.env.example +++ b/example/.env.example @@ -45,21 +45,6 @@ PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" - -# views compiled path -VIEW_COMPILED_PATH=/tmp/storage/framework/views - -# We cannot store sessions to disk: if you don't need sessions (e.g. API) -# then use `array`, else store sessions in database or cookies -SESSION_DRIVER=array - -# Logging to stderr allows the logs to end up in Cloudwatch -LOG_CHANNEL=stderr - -# app storage dir must be /tmp -APP_STORAGE=/tmp - - # tencent crendential TENCENT_SECRET_ID=xxx TENCENT_SECRET_KEY=xxx diff --git a/example/bootstrap/app.php b/example/bootstrap/app.php index 990ecf6..037e17d 100644 --- a/example/bootstrap/app.php +++ b/example/bootstrap/app.php @@ -15,8 +15,6 @@ $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__) ); -$app->useStoragePath(env('APP_STORAGE', '/tmp')); - /* |-------------------------------------------------------------------------- | Bind Important Interfaces diff --git a/example/public/favicon.ico b/example/public/favicon.ico index e69de29..dbb20ed 100644 Binary files a/example/public/favicon.ico and b/example/public/favicon.ico differ diff --git a/example/serverless.yml b/example/serverless.yml index e291274..ddbbf41 100644 --- a/example/serverless.yml +++ b/example/serverless.yml @@ -1,11 +1,12 @@ -component: laravel -name: laravelDemo org: orgDemo app: appDemo stage: dev +component: laravel +name: laravelDemo inputs: - src: ./ # (optional) path to the source folder. default is a hello world app. + src: + src: ./ region: ap-guangzhou runtime: Php7 apigatewayConf: diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..08fa42d --- /dev/null +++ b/jest.config.js @@ -0,0 +1,14 @@ +const { join } = require('path') +require('dotenv').config({ path: join(__dirname, '.env.test') }) + +const config = { + verbose: true, + silent: false, + testTimeout: 60000, + testEnvironment: 'node', + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$', + testPathIgnorePatterns: ['/node_modules/', '/__tests__/lib/'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'] +} + +module.exports = config diff --git a/package.json b/package.json index 14e3725..131b5c4 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,7 @@ "access": "public" }, "scripts": { - "int-test": "jest ./tests/integration.test.js --testEnvironment node", - "test": "npm run lint && npm run prettier && npm run int-test", + "test": "jest", "commitlint": "commitlint -f HEAD@{15}", "lint": "eslint --ext .js,.ts,.tsx .", "lint:fix": "eslint --fix --ext .js,.ts,.tsx .", diff --git a/serverless.component.yml b/serverless.component.yml index 5d733f2..2536442 100644 --- a/serverless.component.yml +++ b/serverless.component.yml @@ -1,5 +1,5 @@ name: laravel -version: 0.0.9 +version: 0.1.1 author: 'Tencent Cloud, Inc' org: 'Tencent Cloud, Inc' description: Deploy a serverless Laravel application on Tencent SCF and API Gateway. diff --git a/src/config.js b/src/config.js index 0a18f3d..3cb06cc 100644 --- a/src/config.js +++ b/src/config.js @@ -9,7 +9,13 @@ const CONFIGS = { timeout: 3, memorySize: 128, namespace: 'default', - description: 'Created by Serverless Component' + description: 'Created by Serverless Component', + envs: { + VIEW_COMPILED_PATH: '/tmp/storage/framework/views', + SESSION_DRIVER: 'array', + LOG_CHANNEL: 'stderr', + APP_STORAGE: '/tmp' + } } module.exports = CONFIGS diff --git a/src/package.json b/src/package.json index 4e09522..c7e061e 100644 --- a/src/package.json +++ b/src/package.json @@ -1,7 +1,7 @@ { "dependencies": { "download": "^8.0.0", - "tencent-component-toolkit": "^1.16.4", + "tencent-component-toolkit": "^1.19.4", "type": "^2.1.0" } } diff --git a/src/utils.js b/src/utils.js index ef8aa9f..d843638 100644 --- a/src/utils.js +++ b/src/utils.js @@ -246,8 +246,25 @@ const prepareInputs = async (instance, credentials, inputs = {}) => { functionConf.needSetTraffic = inputs.traffic !== undefined && functionConf.lastVersion if (tempFunctionConf.environment) { - functionConf.environment = inputs.functionConf.environment + functionConf.environment = tempFunctionConf.environment + functionConf.environment.variables = functionConf.environment.variables || {} + functionConf.environment.variables.SERVERLESS = '1' + functionConf.environment.variables.VIEW_COMPILED_PATH = CONFIGS.envs.VIEW_COMPILED_PATH + functionConf.environment.variables.SESSION_DRIVER = CONFIGS.envs.SESSION_DRIVER + functionConf.environment.variables.LOG_CHANNEL = CONFIGS.envs.LOG_CHANNEL + functionConf.environment.variables.APP_STORAGE = CONFIGS.envs.APP_STORAGE + } else { + functionConf.environment = { + variables: { + SERVERLESS: '1', + VIEW_COMPILED_PATH: CONFIGS.envs.VIEW_COMPILED_PATH, + SESSION_DRIVER: CONFIGS.envs.SESSION_DRIVER, + LOG_CHANNEL: CONFIGS.envs.LOG_CHANNEL, + APP_STORAGE: CONFIGS.envs.APP_STORAGE + } + } } + if (tempFunctionConf.vpcConfig) { functionConf.vpcConfig = inputs.functionConf.vpcConfig }