diff --git a/.github/actions/pnpm-install/action.yml b/.github/actions/pnpm-install/action.yml new file mode 100644 index 00000000..b4225457 --- /dev/null +++ b/.github/actions/pnpm-install/action.yml @@ -0,0 +1,53 @@ +name: Install dependencies +description: Set up pnpm and Node.js, restore caches and run pnpm install + +inputs: + node-version: + description: Node.js version passed to actions/setup-node + required: true + ignore-scripts: + description: Skip the prepare scripts that build the workspace packages + default: "false" + +runs: + using: composite + steps: + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v7 + with: + node-version: ${{ inputs.node-version }} + + # The lockfile is not committed, so the usual lockfile hash key does not + # apply. Instead a new store snapshot is saved whenever a package.json + # changes or a week passes, and every run restores the most recent one. + - id: store + shell: bash + run: | + echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" + echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT" + - uses: actions/cache@v6 + with: + path: ${{ steps.store.outputs.path }} + key: pnpm-store-${{ runner.os }}-${{ steps.store.outputs.week }}-${{ hashFiles('**/package.json', 'pnpm-workspace.yaml') }} + restore-keys: pnpm-store-${{ runner.os }}- + + # The prepare scripts run tsc --build and webpack, both incremental when + # their previous output is present. Every run saves its output and the + # next run starts from the most recent one. + - if: inputs.ignore-scripts != 'true' + uses: actions/cache@v6 + with: + path: | + packages/*/dist + plugins/*/dist + packages/*/node_modules/.cache + plugins/*/node_modules/.cache + key: build-${{ runner.os }}-${{ github.sha }} + restore-keys: build-${{ runner.os }}- + + - shell: bash + run: pnpm i --no-frozen-lockfile ${{ inputs.ignore-scripts == 'true' && '--ignore-scripts' || '' }} + # Drop packages the restored store had but this install did not use, so + # the snapshot does not grow with every version bump. + - shell: bash + run: pnpm store prune diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index f465f8f7..8b321f19 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -31,13 +31,10 @@ jobs: steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@v6 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v7 + - name: Prepare and install + uses: ./.github/actions/pnpm-install with: node-version: ${{ matrix.node-version }} - - name: Prepare and install - run: pnpm i --no-frozen-lockfile - name: Use Factorio ${{ matrix.factorio-version }} run: wget -q -O factorio.tar.gz https://www.factorio.com/get-download/${{ matrix.factorio-version }}/headless/linux64 && tar -xf factorio.tar.gz && rm factorio.tar.gz - name: Run tests @@ -78,12 +75,10 @@ jobs: steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@v6 - - uses: actions/setup-node@v7 + - name: Prepare and install + uses: ./.github/actions/pnpm-install with: node-version: ${{ env.NODE_VERSION }} - - name: Prepare and install - run: pnpm i --no-frozen-lockfile - name: Build run: pnpm run build - name: Test ${{ matrix.controller }} controller with ${{ matrix.host }} host @@ -98,11 +93,10 @@ jobs: timeout-minutes: 5 steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@v6 - - uses: actions/setup-node@v7 + - uses: ./.github/actions/pnpm-install with: node-version: ${{ env.NODE_VERSION }} - - run: pnpm i --no-frozen-lockfile + ignore-scripts: true - run: pnpm run lint build: @@ -110,11 +104,10 @@ jobs: timeout-minutes: 5 steps: - uses: actions/checkout@v7 - - uses: pnpm/action-setup@v6 - - uses: actions/setup-node@v7 + - uses: ./.github/actions/pnpm-install with: node-version: ${{ env.NODE_VERSION }} - - run: pnpm i --no-frozen-lockfile + ignore-scripts: true - run: pnpm run build-mod # Upload build to artifacts - name: Upload build to artifacts