[{"data":1,"prerenderedAt":305},["ShallowReactive",2],{"article-2":3},{"id":4,"title":5,"body":6,"create":293,"description":24,"extension":294,"labels":295,"locked":297,"meta":298,"navigation":299,"path":300,"seo":301,"stem":302,"update":303,"__hash__":304},"articles/article/2.md","用 JavaScript 创建 GitHub Action",{"type":7,"value":8,"toc":282},"minimark",[9,13,17,28,31,37,67,73,76,82,90,102,106,117,121,129,132,151,155,165,171,174,182,191,197,206,212,215,218,227,231,254,257,279],[10,11,12],"h2",{"id":12},"初始化",[14,15,16],"p",{},"首先创建一个仓库",[18,19,25],"pre",{"className":20,"code":22,"language":23,"meta":24},[21],"language-shell","git init\n","shell","",[26,27,22],"code",{"__ignoreMap":24},[14,29,30],{},"然后，初始化项目",[18,32,35],{"className":33,"code":34,"language":23,"meta":24},[21],"npm init\n",[26,36,34],{"__ignoreMap":24},[14,38,39,40,47,52,55,56,61,63,64,66],{},"接着安装相关依赖 ",[41,42,46],"a",{"href":43,"rel":44},"https://github.com/actions/toolkit/tree/main/packages/core",[45],"nofollow","@actions/core",[41,48,51],{"href":49,"rel":50},"https://github.com/actions/toolkit/tree/main/packages/github",[45],"@actions/github",[53,54],"br",{},"\n其他的工具包在这里 ",[41,57,60],{"href":58,"rel":59},"https://github.com/actions/toolkit",[45],"toolkit",[53,62],{},"\n但是想用 GitHub API 的话就不用安装 octokit 了，因为 ",[26,65,51],{}," 已经封装好了这个包。",[18,68,71],{"className":69,"code":70,"language":23,"meta":24},[21],"npm install -D @actions/core @actions/github\n",[26,72,70],{"__ignoreMap":24},[10,74,75],{"id":75},"配置文件",[14,77,78,79],{},"新建 ",[26,80,81],{},"action.yml",[18,83,88],{"className":84,"code":86,"language":87,"meta":24},[85],"language-yaml","name: 'say hello'\ndescription: 'test for GitHub Actions!'\n# 需要输入的字段\ninputs:\n  # 输入字段名称\n  name:\n    # 字段描述\n    description: 'name'\n    # 默认值 \n    default: 'ttdly'\n    # 是否必须\n    required: true\n# 需要输出的字段\noutputs:\n  hello:\n    description: 'say hello'\n\nruns:\n  using: 'node16'\n  main: 'index.js'\n","yaml",[26,89,86],{"__ignoreMap":24},[14,91,92,93,95,96,101],{},"关于 ",[26,94,81],{},"\n的语法，可以参考 ",[41,97,100],{"href":98,"rel":99},"https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-docker-container-and-javascript-actions",[45],"官方文档","\n，但是上面俩字段基本够用了。",[10,103,105],{"id":104},"编写-本地测试","编写 & 本地测试",[14,107,108,109,112,113,116],{},"新建 js 入口文件 ",[26,110,111],{},"index.js","，可以是任何名称，但是 ",[26,114,115],{},"runs.mian.\u003Cname>"," 字段一定要和入口文件名字一致",[118,119,120],"h3",{"id":120},"输入输出",[18,122,127],{"className":123,"code":125,"language":126,"meta":24},[124],"language-javascript","const core = require('@actions/core');\nconst github = require('@actions/github');\n\nconst core = require('@actions/core')\n\nasync function run() {\n    try {\n        const name = core.getInput('name')\n        core.setOutput('hello', `Hello ${name}`)\n    } catch (err) {\n        core.setFailed(err.message)\n    }\n}\n\nrun()\n","javascript",[26,128,125],{"__ignoreMap":24},[14,130,131],{},"可以看的出来，平时 Javascript 怎么写，这里就能怎么写，只是输入输出方式不一样，这里列举一下输出的类型：",[133,134,135,139,142,145,148],"ul",{},[136,137,138],"li",{},"core.info ()",[136,140,141],{},"core.debug ()",[136,143,144],{},"core.warning ()",[136,146,147],{},"core.notice ()",[136,149,150],{},"core.error ()",[118,152,154],{"id":153},"结合-github-api","结合 GitHub API",[14,156,157,158,161,162,164],{},"虽然在执行工作流的时候，",[26,159,160],{},"github context"," 提供了许多信息，但是也并不包含有关事件的所有信息，这时就要用到 GitHub API\n来获取一些额外的数据。",[53,163],{},"\n通过以下步骤获取到可以直接执行 graphql 查询的工具：",[18,166,169],{"className":167,"code":168,"language":126,"meta":24},[124],"const github = require('@actions/github')\nconst octokit = github.getOctokit(token)\nconst graphqlWithAuth = octokit.graphql\n",[26,170,168],{"__ignoreMap":24},[14,172,173],{},"然后编写查询语句，这里简单一些，获取当前登录用户的名称：",[18,175,180],{"className":176,"code":178,"language":179,"meta":24},[177],"language-graphql","query {\n  viewer {\n    login \n  }\n}\n","graphql",[26,181,178],{"__ignoreMap":24},[14,183,184,185,190],{},"较为复杂的语句建议在 ",[41,186,189],{"href":187,"rel":188},"https://docs.github.com/en/graphql/overview/explorer",[45],"官方工具"," 中编写。\n执行查询语句，获取数据：",[18,192,195],{"className":193,"code":194,"language":126,"meta":24},[124],"const data = await graphqlWithAuth(`\nquery {\n  viewer {\n    login \n  }\n}\n`)\nconsole.log('login:', data.data.viewer.login)\n",[26,196,194],{"__ignoreMap":24},[14,198,199,200,205],{},"注意，在执行 graphql\n查询时，如果需要在查询语句中传递参数，官方建议是这么写的。（代码摘自 ",[41,201,204],{"href":202,"rel":203},"https://github.com/octokit/graphql.js",[45],"octokit/graphql.js","）",[18,207,210],{"className":208,"code":209,"language":126,"meta":24},[124],"const { graphql } = require (\"@octokit/graphql\");\nconst { lastIssues } = await graphql ({\n  query: `query lastIssues ($owner: String!, $repo: String!, $num: Int = 3) {\n    repository (owner:$owner, name:$repo) {\n      issues (last:$num) {\n        edges {\n          node {\n            title\n          }\n        }\n      }\n    }\n  }`,\n  owner: \"octokit\",\n  repo: \"graphql.js\",\n  headers: {\n    authorization: `token secret123`,\n  },\n});\n",[26,211,209],{"__ignoreMap":24},[14,213,214],{},"也就是你需要传递的参数也得放在请求里面，而不是用模板字符拼接，因为用模板字符拼接可能会遭受注入攻击。而且也更方便进行一些递归查询。",[118,216,217],{"id":217},"本地测试",[14,219,220,221,226],{},"目前我知道的，比较专业的 action 测试是 ",[41,222,225],{"href":223,"rel":224},"https://github.com/nektos/act",[45],"act","，不过也没了解过，我是通过修改环境变量的方式来进行本地测试的。",[228,229,230],"h4",{"id":230},"input",[14,232,233,234,236,237,240,241,244,245,248,249,253],{},"对于利用 Javascript 来创建的 GitHub Actions，",[26,235,81],{}," 中的 input 字段，会在运行时转换成 INPUT_XXX 并且空格会转换成 ",[26,238,239],{},"_","\n。例如你的 input 字段是 ",[26,242,243],{},"time","，那存储在环境变量里面的就会是 ",[26,246,247],{},"INPUT_TIME"," 字段，可以设置 process.env ",[250,251,252],"span",{},"'INPUT_TIME'","=10\n来模拟输入。",[228,255,256],{"id":256},"context",[14,258,259,260,262,263,266,267,269,270,273,274,278],{},"context 中的字段在 process.env 中的字段，基本就是 GITHUB_XXX（该字段的 upperCase），驼峰命名使用 ",[26,261,239],{}," 连接，如 eventName 就是\n",[26,264,265],{},"process.env.GITHUB_EVENT_NAME","。",[53,268],{},"\n但是 payload 比较特殊，需要给 ",[26,271,272],{},"process.env.GITHUB_EVENT_PATH"," 设置一个 json 文件的文件路径，内容就是 Action\n执行的上下文，也就是 ",[41,275,160],{"href":276,"rel":277},"https://docs.github.com/en/actions/learn-github-actions/contexts#github-context",[45],"\n中的内容。",[14,280,281],{},"基本上这些数据就能够进行一些简单的流程测试。",{"title":24,"searchDepth":283,"depth":283,"links":284},2,[285,286,287],{"id":12,"depth":283,"text":12},{"id":75,"depth":283,"text":75},{"id":104,"depth":283,"text":105,"children":288},[289,291,292],{"id":120,"depth":290,"text":120},3,{"id":153,"depth":290,"text":154},{"id":217,"depth":290,"text":217},"2023-03-31T02:36:53.000Z","md",[296],"github",false,{},true,"/article/2",{"title":5,"description":24},"article/2","2023-04-09T13:03:24.000Z","Q13pLWESx3_LgiAXZjQPp82uqptA0MhkmQN6ZmpGxiM",1755235549205]