0

Writing github workflow files is for me a tedious, error prone, exhausting and time consuming task. For that reason, I have a lot of github workflow files that are monstruosities born from random copy paste, or that were modified from some random templated that I used to scaffold whatever project they're in.

The workflow below is from an ocaml project that I didn't checked in two years, and 99% of the workflow file seems to be coming from the tool that initiated the project given that most of the lines were added in the very first commit. That means that I don't have full understanding of what is happening, and I'm constantly in doubt about removing sections, even if they seem to be redundant to me.

As you can see below, it has two jobs, one that builds the project for each supported platform, and generates assets containing the compilation result. The second job is supposed to be used to publish the built assets into a github release, but for some reason it also contains build steps, which are quite slow. Knowing that the upload step downloads the generated assets, is there any reason to have such build duplication of steps?

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 }}
Danielo515
  • 5,996
  • 4
  • 32
  • 66
  • Depending on what the `release-make-skeleton.js` script dependencies and premisses are, you could remove a good part of the second job setup, as you are already downloading the binaries generated on the first job using the same step by step. – GuiFalourd Sep 12 '22 at 12:23
  • Yes, that is exactly what I thought. The release-make-skeleton.js just generates a bunch of folders and a package.json containing some metadata, it does not require any existing file – Danielo515 Sep 13 '22 at 07:31
  • In that case, you could probably just keep the `actions/checkout` and the `actions/setup-node` steps before the script in that second job. – GuiFalourd Sep 13 '22 at 09:23

0 Answers0