使用 GitHub Action 实现自动化的力量 - 如何创建您的操作
在过去的两到四个月里,我开始管理一个新项目,幸运的是,我能够应用我从课程和阅读材料中学到的很多东西,同时牢记我所在团队成员的经验一起工作让事情变得简单,但同时也有点挑战性,所以我可以鼓励他们学习新事物或加强他们目前拥有的知识。 在项目的前两周,我们必须交付一个 MVP,因此我们决定将其托管在Heroku中,在那里我为多环境创建了一个管道,现在我认为这是一个矫枉过正 😅 因为它是只是一个MVP。
在过去的两到四个月里,我开始管理一个新项目,幸运的是,我能够应用我从课程和阅读材料中学到的很多东西,同时牢记我所在团队成员的经验一起工作让事情变得简单,但同时也有点挑战性,所以我可以鼓励他们学习新事物或加强他们目前拥有的知识。
在项目的前两周,我们必须交付一个 MVP,因此我们决定将其托管在Heroku中,在那里我为多环境创建了一个管道,现在我认为这是一个矫枉过正 😅 因为它是只是一个MVP。
继续前进,我希望能够将我的 Docker 镜像推送到 Heroku 注册表,所以合并的每一小段代码我都手动构建了镜像并将其推送到 Heroku。
到目前为止一切顺利,但我厌倦了一遍又一遍地做同样的事情,所以我记得我可以使用 GitHub Actions 来自动化这个过程💡。我在 GitHub Marketplace 上搜索允许我构建 docker 图像并将其推送到 Heroku 的东西,我找到了一些东西,但这不是我想要的。所以我做了工程师会做的任何事情,创造它的行动😎。
阅读文档!
由于我从未使用过 Action,我不得不去阅读文档,我发现它是一个有据可查的功能。
引起我注意的是,人们可以为一些常见的编程语言(如 JavaScript、Python 和 Java)编写动作。您可以在此处阅读有关支持的语言和框架的更多信息。
现在我知道我可以为我的项目编写一个动作,然后我继续前进并登陆创建动作页面,在这里我注意到您可以使用 JavaScript 或 Bash 编写动作,这对我来说很酷😉。
建设行动
我决定像往常一样使用 JavaScript 来编写我的操作,为您的项目创建一个文件夹:
mkdir my-action && cd my-action
进入全屏模式 退出全屏模式
添加action.yml
使用您最喜欢的 IDE 或代码编辑器打开您的项目目录并创建一个名为action.yml
的新文件。该文件是您要定义操作元数据的位置,并且应该具有以下结构:
name: # Name of your action
description: # Some Fancy description explaining what this does
inputs: # User input for you action
id_of_your_input:
description: # What is this input about
required: # Set this to true if the input is required or set it to fall if otherwise
default: # Some default value
outputs:
time: # id of output
description: 'The time we greeted you'
runs:
using: 'node12'
main: 'index.js'
进入全屏模式 退出全屏模式
所以我创建了我的action.yml
,它看起来像这样:
name: 'Deploy Docker Image to Heroku App'
author: 'Jean Carlos Taveras'
description: 'A simple action to build, push and Deploy a Docker Image to your Heroku app.'
inputs:
email:
description: 'Email Linked to your Heroku Account'
required: true
api_key:
description: 'Your Heroku API Key'
required: true
app_name:
description: 'Your Heroku App Name'
required: true
dockerfile_path:
description: 'Dokerfile path'
required: true
options:
description: 'Optional build parameters'
required: false
runs:
using: 'node12'
main: 'dist/index.js'
进入全屏模式 退出全屏模式
安装依赖
在开始编码之前,您需要安装两个依赖项
-
@actions/core
-
@actions/github
您需要@actions/core
才能从action.yml
中提取声明的输入和输出变量等。另一方面,@actions/github
用于获取有关操作上下文等的信息。
npm install -s @actions/core @actions/github
进入全屏模式 退出全屏模式
写动作的核心
创建一个index.js
文件,让我们导入依赖项:
const core = require('@actions/core');
const github = require('@actions/github'); // In case you need it
进入全屏模式 退出全屏模式
由于我需要执行 docker 和 Heroku 命令,我需要添加child_process
和util
模块,并从后者获取promisify
函数。
...
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
进入全屏模式 退出全屏模式
好的!现在我必须创建一个函数来允许对 Heroku Registry 进行身份验证。
...
async function loginHeroku() {
const login = core.getInput('email');
const password = core.getInput('api_key');
try {
await exec(`echo ${password} | docker login --username=${login} registry.heroku.com --password-stdin`);
console.log('Logged in succefully ✅');
} catch (error) {
core.setFailed(`Authentication process faild. Error: ${error.message}`);
}
}
进入全屏模式 退出全屏模式
好的!现在我需要构建 Docker 镜像,将其推送到 Heroku Registry 并将其部署到 Heroku App
...
async function buildPushAndDeploy() {
const appName = core.getInput('app_name');
const dockerFilePath = core.getInput('dockerfile_path');
const buildOptions = core.getInput('options') || '';
const herokuAction = herokuActionSetUp(appName);
try {
await exec(`cd ${dockerFilePath}`);
await exec(`docker build . --file Dockerfile ${buildOptions} --tag registry.heroku.com/${appName}/web`);
console.log('Image built 🛠');
await exec(herokuAction('push'));
console.log('Container pushed to Heroku Container Registry ⏫');
await exec(herokuAction('release'));
console.log('App Deployed successfully 🚀');
} catch (error) {
core.setFailed(`Something went wrong building your image. Error: ${error.message}`);
}
}
进入全屏模式 退出全屏模式
现在我看到了这个,我需要重构这个函数😅。当我说让我们写下我们行动的核心时,我想我太认真了。
您可能会注意到有一个名为herokuActionSetUp
的函数,它只是一个返回 Heroku 操作(推送或释放)的辅助函数。
...
/**
*
* @param {string} appName - Heroku App Name
* @returns {function}
*/
function herokuActionSetUp(appName) {
/**
* @typedef {'push' | 'release'} Actions
* @param {Actions} action - Action to be performed
* @returns {string}
*/
return function herokuAction(action) {
const HEROKU_API_KEY = core.getInput('api_key');
const exportKey = `HEROKU_API_KEY=${HEROKU_API_KEY}`;
return `${exportKey} heroku container:${action} web --app ${appName}`
}
}
进入全屏模式 退出全屏模式
我们快完成了。我们只需要调用我们的函数,因为这些函数是异步的,所以我们可以将它们链接在一起,如下所示:
...
loginHeroku()
.then(() => buildPushAndDeploy())
.catch((error) => {
console.log({ message: error.message });
core.setFailed(error.message);
})
进入全屏模式 退出全屏模式
捆绑您的代码
为了防止提交您的node_modules/
文件夹,您可以运行:
npx zeit/ncc build index.js
进入全屏模式 退出全屏模式
这将创建一个dist
文件夹,其中包含一个包index.js
文件,请记住,您必须更改action.yml
文件中的runs
部分以指向捆绑的 JavaScript 文件:
runs:
using: 'node12'
main: 'dist/index.js'
进入全屏模式 退出全屏模式
添加自述文件
您应该添加一个README.md
文件以让用户了解如何使用您的操作。
测试您的操作
您可以按照 GitHub 文档在工作流中测试您的操作中的说明进行操作。但是,我发现这种测试方法非常痛苦,因为每次进行更改时都必须推送代码。然后您可以做的是使用nektos/act在本地运行您的操作(https://github.com/nektos/act)是一个文档齐全且易于使用的工具。
就是这样,这就是使用 JavaScript 创建动作所需的全部知识。这篇文章比我想象的要长一点,因为这是我的第一篇文章。
感谢并在 GitHub MarketplaceDeploy Docker Image to Heroku App以及jctaveras/heroku-deploy的 repo 中检查此操作。
更多推荐
所有评论(0)