CI and the deploy no longer fail when the npm registry drops a connection mid-install. Every job on g1t's cloud runners keeps npm's downloads between runs (actions/cache on ~/.npm, keyed on the lockfile) and installs with --prefer-offline, so it asks the registry only for what changed; and the repository's .npmrc retries a dropped fetch five times, waiting up to a minute, instead of npm's two quick retries.
6 files+96−90/6 viewed
| 72 | 72 | timeout-minutes: 30 | |
| 73 | 73 | steps: | |
| 74 | 74 | - uses: actions/checkout@v5 | |
| 75 | + | # npm's downloads, kept between runs: an install reads them first | |
| 76 | + | # and asks the registry only for what changed, so a dropped | |
| 77 | + | # connection to it rarely stops the job. | |
| 78 | + | - name: Cache npm's downloads | |
| 79 | + | uses: actions/cache@v4 | |
| 80 | + | with: | |
| 81 | + | path: ~/.npm | |
| 82 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 83 | + | restore-keys: npm-${{ runner.os }}- | |
| 75 | 84 | - name: Install | |
| 76 | − | run: npm ci --no-audit --no-fund | |
| 85 | + | run: npm ci --prefer-offline --no-audit --no-fund | |
| 77 | 86 | - name: Type checks | |
| 78 | 87 | run: npm run typecheck | |
| 79 | 88 | - name: Tests | |
| ⋯ | |||
| 92 | 101 | timeout-minutes: 30 | |
| 93 | 102 | steps: | |
| 94 | 103 | - uses: actions/checkout@v5 | |
| 104 | + | # npm's downloads, kept between runs: an install reads them first | |
| 105 | + | # and asks the registry only for what changed, so a dropped | |
| 106 | + | # connection to it rarely stops the job. | |
| 107 | + | - name: Cache npm's downloads | |
| 108 | + | uses: actions/cache@v4 | |
| 109 | + | with: | |
| 110 | + | path: ~/.npm | |
| 111 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 112 | + | restore-keys: npm-${{ runner.os }}- | |
| 95 | 113 | - name: Install | |
| 96 | − | run: npm ci --no-audit --no-fund | |
| 114 | + | run: npm ci --prefer-offline --no-audit --no-fund | |
| 97 | 115 | - name: The site, sudo and the docs | |
| 98 | 116 | run: node scripts/deploy.mjs build --only web,sudo,docs | |
| 99 | 117 | ||
| 70 | 70 | timeout-minutes: 20 | |
| 71 | 71 | steps: | |
| 72 | 72 | - uses: actions/checkout@v5 | |
| 73 | + | # npm's downloads, kept between runs: an install reads them first | |
| 74 | + | # and asks the registry only for what changed, so a dropped | |
| 75 | + | # connection to it rarely stops the job. | |
| 76 | + | - name: Cache npm's downloads | |
| 77 | + | uses: actions/cache@v4 | |
| 78 | + | with: | |
| 79 | + | path: ~/.npm | |
| 80 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 81 | + | restore-keys: npm-${{ runner.os }}- | |
| 73 | 82 | - name: Install Wrangler | |
| 74 | − | run: npm ci --workspaces=false --no-audit --no-fund | |
| 83 | + | run: npm ci --prefer-offline --workspaces=false --no-audit --no-fund | |
| 75 | 84 | - name: The manifest matches every wrangler.jsonc | |
| 76 | 85 | run: node scripts/deploy.mjs manifest --check | |
| 77 | 86 | - name: The deploy tool's tests | |
| ⋯ | |||
| 125 | 134 | timeout-minutes: 20 | |
| 126 | 135 | steps: | |
| 127 | 136 | - uses: actions/checkout@v5 | |
| 137 | + | # npm's downloads, kept between runs: an install reads them first | |
| 138 | + | # and asks the registry only for what changed, so a dropped | |
| 139 | + | # connection to it rarely stops the job. | |
| 140 | + | - name: Cache npm's downloads | |
| 141 | + | uses: actions/cache@v4 | |
| 142 | + | with: | |
| 143 | + | path: ~/.npm | |
| 144 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 145 | + | restore-keys: npm-${{ runner.os }}- | |
| 128 | 146 | - name: Install Wrangler | |
| 129 | − | run: npm ci --workspaces=false --no-audit --no-fund | |
| 147 | + | run: npm ci --prefer-offline --workspaces=false --no-audit --no-fund | |
| 130 | 148 | - name: Apply pending migrations | |
| 131 | 149 | env: | |
| 132 | 150 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| 86 | 86 | ~/.cargo/registry | |
| 87 | 87 | apps/desktop/src-tauri/target | |
| 88 | 88 | key: desktop-release-linux-${{ hashFiles('apps/desktop/src-tauri/Cargo.lock') }} | |
| 89 | + | # npm's downloads, kept between runs: an install reads them first | |
| 90 | + | # and asks the registry only for what changed, so a dropped | |
| 91 | + | # connection to it rarely stops the job. | |
| 92 | + | - name: Cache npm's downloads | |
| 93 | + | uses: actions/cache@v4 | |
| 94 | + | with: | |
| 95 | + | path: ~/.npm | |
| 96 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 97 | + | restore-keys: npm-${{ runner.os }}- | |
| 89 | 98 | - name: Install | |
| 90 | − | run: npm ci --no-audit --no-fund | |
| 99 | + | run: npm ci --prefer-offline --no-audit --no-fund | |
| 91 | 100 | - name: Build and sign | |
| 92 | 101 | env: | |
| 93 | 102 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.DESKTOP_SIGNING_KEY }} | |
| ⋯ | |||
| 157 | 166 | ~/.cargo/registry | |
| 158 | 167 | apps/desktop/src-tauri/target | |
| 159 | 168 | key: desktop-release-windows-${{ hashFiles('apps/desktop/src-tauri/Cargo.lock') }} | |
| 169 | + | # npm's downloads, kept between runs: an install reads them first | |
| 170 | + | # and asks the registry only for what changed, so a dropped | |
| 171 | + | # connection to it rarely stops the job. | |
| 172 | + | - name: Cache npm's downloads | |
| 173 | + | uses: actions/cache@v4 | |
| 174 | + | with: | |
| 175 | + | path: ~/.npm | |
| 176 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 177 | + | restore-keys: npm-${{ runner.os }}- | |
| 160 | 178 | - name: Install | |
| 161 | − | run: npm ci --no-audit --no-fund | |
| 179 | + | run: npm ci --prefer-offline --no-audit --no-fund | |
| 162 | 180 | - name: Build and sign | |
| 163 | 181 | env: | |
| 164 | 182 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.DESKTOP_SIGNING_KEY }} | |
| ⋯ | |||
| 217 | 235 | pattern: desktop-* | |
| 218 | 236 | merge-multiple: true | |
| 219 | 237 | path: target/desktop-release/${{ needs.version.outputs.version }}/ | |
| 238 | + | # npm's downloads, kept between runs: an install reads them first | |
| 239 | + | # and asks the registry only for what changed, so a dropped | |
| 240 | + | # connection to it rarely stops the job. | |
| 241 | + | - name: Cache npm's downloads | |
| 242 | + | uses: actions/cache@v4 | |
| 243 | + | with: | |
| 244 | + | path: ~/.npm | |
| 245 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 246 | + | restore-keys: npm-${{ runner.os }}- | |
| 220 | 247 | - name: Install Wrangler | |
| 221 | − | run: npm ci --workspaces=false --no-audit --no-fund | |
| 248 | + | run: npm ci --prefer-offline --workspaces=false --no-audit --no-fund | |
| 222 | 249 | - name: The manifest | |
| 223 | 250 | run: node scripts/desktop-release.mjs manifest --notes "${{ inputs.notes }}" | |
| 224 | 251 | - name: Publish | |
| 55 | 55 | if [ "${GITHUB_REF_TYPE}" = tag ] && [ "mobile-v$version" != "${GITHUB_REF_NAME}" ]; then | |
| 56 | 56 | echo "::error::The tag is ${GITHUB_REF_NAME}, but apps/mobile is $version"; exit 1 | |
| 57 | 57 | fi | |
| 58 | + | # npm's downloads, kept between runs: an install reads them first | |
| 59 | + | # and asks the registry only for what changed, so a dropped | |
| 60 | + | # connection to it rarely stops the job. | |
| 61 | + | - name: Cache npm's downloads | |
| 62 | + | uses: actions/cache@v4 | |
| 63 | + | with: | |
| 64 | + | path: ~/.npm | |
| 65 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 66 | + | restore-keys: npm-${{ runner.os }}- | |
| 58 | 67 | - name: Install Wrangler | |
| 59 | − | run: npm ci --workspaces=false --no-audit --no-fund | |
| 68 | + | run: npm ci --prefer-offline --workspaces=false --no-audit --no-fund | |
| 60 | 69 | - name: Build on EAS | |
| 61 | 70 | if: ${{ !inputs.build }} | |
| 62 | 71 | env: |
| 67 | 67 | run: | | |
| 68 | 68 | node scripts/runner-release.mjs sign | |
| 69 | 69 | node scripts/runner-release.mjs verify | |
| 70 | + | # npm's downloads, kept between runs: an install reads them first | |
| 71 | + | # and asks the registry only for what changed, so a dropped | |
| 72 | + | # connection to it rarely stops the job. | |
| 73 | + | - name: Cache npm's downloads | |
| 74 | + | uses: actions/cache@v4 | |
| 75 | + | with: | |
| 76 | + | path: ~/.npm | |
| 77 | + | key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| 78 | + | restore-keys: npm-${{ runner.os }}- | |
| 70 | 79 | - name: Install Wrangler | |
| 71 | − | run: npm ci --workspaces=false --no-audit --no-fund | |
| 80 | + | run: npm ci --prefer-offline --workspaces=false --no-audit --no-fund | |
| 72 | 81 | - name: Publish to g1t.sh/downloads/runner | |
| 73 | 82 | env: | |
| 74 | 83 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} |
| 1 | + | # Installs on g1t's runners (and anywhere else) retry a dropped connection | |
| 2 | + | # to the registry more patiently than npm's default of two quick retries: | |
| 3 | + | # an ECONNRESET partway through a 1,300-package install used to fail CI. | |
| 4 | + | fetch-retries=5 | |
| 5 | + | fetch-retry-mintimeout=5000 | |
| 6 | + | fetch-retry-maxtimeout=60000 |