该OCaml项目的GitHub Action发布工作流是否存在冗余步骤?
问题:发布阶段的重复构建步骤是否必要?
我编写GitHub Workflow时经常靠复制粘贴或修改模板,手上有个两年没维护的OCaml项目,Workflow文件99%来自初始化工具,细节不太敢改。这个Workflow分两个Job:第一个Job在各平台构建并上传产物;第二个Job本应只负责发布到GitHub Release,但却包含了和第一个Job几乎一样的耗时构建步骤,而且发布阶段已经会下载第一个Job生成的产物。想问这些重复构建步骤有没有存在的必要?
以下是原Workflow文件:
name: Release on: workflow_dispatch: release: types: [ published ] jobs: build: name: Build and test runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v2 - name: Fetch git tags run: git fetch --tags --force - name: Use Node.js 12.x uses: actions/setup-node@v1 with: node-version: 12.x registry-url: "https://registry.npmjs.org" - name: Set macOS deployment target if: matrix.os == 'macos-latest' run: | echo "::set-env name=MACOSX_DEPLOYMENT_TARGET=10.9" - name: Cache esy dependencies uses: actions/cache@v1 id: cache with: path: _export key: ${{ runner.OS }}-build-${{ hashFiles('esy.lock/index.json') }} restore-keys: | ${{ runner.OS }}-build-${{ env.cache-name }}- ${{ runner.OS }}-build- ${{ runner.OS }}- - name: Install esy run: npm install -g esy@latest - name: Import dependencies if: steps.cache.outputs.cache-hit == 'true' run: esy import-build _export/* - name: Install dependencies run: esy install - name: Build run: esy build --release - name: Substitute watermarks run: esy dune subst - name: Build subst changes run: esy dune build - name: Export dependencies run: esy export-dependencies - name: Get binary path id: get_binary_path shell: bash run: | # from https://stackoverflow.com/a/24848739/617787 s=$(pwd); d=$(dirname $(esy x which reason-ls)); while [ "${d#$s/}" == "${d}" ] do s=$(dirname $s);b="../${b}"; done; BINARY_PATH=${b}${d#$s/}/reason-ls echo "BINARY_PATH: $BINARY_PATH" echo "##[set-output name=path;]$BINARY_PATH" - name: Upload artifacts for ${{ matrix.os }} uses: actions/upload-artifact@master with: name: ${{ matrix.os }} path: ${{ steps.get_binary_path.outputs.path }} publish: needs: build name: Publish runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Fetch git tags run: git fetch --tags --force - name: Use Node.js 12.x uses: actions/setup-node@v1 with: node-version: 12.x - name: Cache esy dependencies uses: actions/cache@v1 id: cache with: path: _export key: ${{ runner.OS }}-build-${{ hashFiles('esy.lock/index.json') }} restore-keys: | ${{ runner.OS }}-build-${{ env.cache-name }}- ${{ runner.OS }}-build- ${{ runner.OS }}- - name: Install esy run: npm install -g esy@latest - name: Import dependencies if: steps.cache.outputs.cache-hit == 'true' run: esy import-build _export/* - name: Install dependencies run: esy install - name: Build run: esy build --release - name: Substitute watermarks run: esy dune subst - name: Make NPM release skeleton run: node script/release-make-skeleton.js - name: Download linux artifacts uses: actions/download-artifact@master with: name: ubuntu-latest path: _release/platform-linux-x64 - name: Download macOS artifacts uses: actions/download-artifact@master with: name: macos-latest path: _release/platform-darwin-x64 - name: Create archives for Github release run: | cd _release/platform-darwin-x64 zip -r ../../reason-ls-darwin-x64.zip . cd ../.. cd _release/platform-linux-x64 zip -r ../../reason-ls-linux-x64.zip . cd ../.. - name: Upload reason-ls-darwin-x64.zip to Github release uses: actions/upload-release-asset@v1.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: reason-ls-darwin-x64.zip asset_name: reason-ls-darwin-x64.zip asset_content_type: application/gzip - name: Upload reason-ls-linux-x64.zip to Github release uses: actions/upload-release-asset@v1.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: reason-ls-linux-x64.zip asset_name: reason-ls-linux-x64.zip asset_content_type: application/gzip - name: Publish NPM package run: | npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN npm config set scope "@{{ npm_username }}" npm config list npm publish --access public working-directory: ./_release env: NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
回答
这些重复构建步骤完全没有必要,可以安全删除,能大幅减少发布阶段的运行时间。具体分析如下:
冗余性明确
build job已经在Ubuntu和macOS平台完成了完整的依赖安装、项目构建、产物上传流程,publish job通过actions/download-artifact已经拿到了最终的二进制产物,后续打包、发布只需要这些产物,不需要再次执行构建流程。publish job里的esy install、esy build --release、esy dune subst等步骤都是完全重复的操作,纯粹浪费资源。需要保留的核心步骤
只需要保留支撑node script/release-make-skeleton.js和后续发布流程的基础步骤:actions/checkout@v2:需要获取项目中的script/release-make-skeleton.js脚本文件Use Node.js 12.x:运行Node脚本需要对应的Node环境Fetch git tags:如果release-make-skeleton.js需要读取git标签信息来生成版本号,这个步骤需要保留;如果不需要也可以删除
其余所有esy相关的缓存、安装、构建步骤都可以直接删除。
优化后的publish job示例
简化后的publish job步骤如下:
publish: needs: build name: Publish runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Fetch git tags run: git fetch --tags --force - name: Use Node.js 12.x uses: actions/setup-node@v1 with: node-version: 12.x - name: Make NPM release skeleton run: node script/release-make-skeleton.js - name: Download linux artifacts uses: actions/download-artifact@master with: name: ubuntu-latest path: _release/platform-linux-x64 - name: Download macOS artifacts uses: actions/download-artifact@master with: name: macos-latest path: _release/platform-darwin-x64 - name: Create archives for Github release run: | cd _release/platform-darwin-x64 zip -r ../../reason-ls-darwin-x64.zip . cd ../.. cd _release/platform-linux-x64 zip -r ../../reason-ls-linux-x64.zip . cd ../.. - name: Upload reason-ls-darwin-x64.zip to Github release uses: actions/upload-release-asset@v1.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: reason-ls-darwin-x64.zip asset_name: reason-ls-darwin-x64.zip asset_content_type: application/gzip - name: Upload reason-ls-linux-x64.zip to Github release uses: actions/upload-release-asset@v1.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: reason-ls-linux-x64.zip asset_name: reason-ls-linux-x64.zip asset_content_type: application/gzip - name: Publish NPM package run: | npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN npm config set scope "@{{ npm_username }}" npm config list npm publish --access public working-directory: ./_release env: NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
内容的提问来源于stack exchange,提问作者Danielo515
相关产品推荐
相关产品推荐

