Skip to content

ci: fix release build (native-arch per OS + node22) - #4

Open
dp9u0 wants to merge 11 commits into
mainfrom
dev
Open

ci: fix release build (native-arch per OS + node22)#4
dp9u0 wants to merge 11 commits into
mainfrom
dev

Conversation

@dp9u0

@dp9u0 dp9u0 commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Fix the first release run: pkg tried to build linux-arm64 from an x64 runner and cross-compiling failed in openssl. Now builds each OS natively (ubuntu/macos/windows), uploads artifacts, and a release job assembles them into one GitHub Release. Also bumps pkg targets to node22 and drops node20 from the ci matrix (runner deprecated). Validated with actionlint.

pkg compiles node from source for targets without a cached binary,
and cross-compiling arm64 from an x64 host fails in openssl's
arm_arch.h ("unsupported ARM architecture"). Build each OS on its own
runner (ubuntu/macos/windows), then assemble all artifacts in a
release job and publish. Also bump pkg/node20 targets to node22 and
drop node 20 from the ci matrix — Actions deprecated the runner.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 31, 2026 03:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The release workflow still risks cross-target builds and non-portable checksum generation, which can break the release pipeline on macOS/Windows and/or reintroduce the original cross-compilation failure.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the GitHub Actions workflows to build release artifacts per OS runner (instead of attempting cross-target builds from a single runner) and updates packaging/CI Node versions to newer baselines.

Changes:

  • Update pkg targets from Node 20 to Node 22.
  • Split release workflow into a per-OS build matrix that uploads artifacts, plus a final job that creates the GitHub Release from downloaded artifacts.
  • Drop Node 20 from the CI test matrix.
File summaries
File Description
package.json Bumps pkg build targets to Node 22.
.github/workflows/release.yml Adds OS-matrix build job, artifact upload/download, and release assembly step.
.github/workflows/ci.yml Removes Node 20 from the test matrix.
Review details

Suppressed comments (1)

.github/workflows/release.yml:40

  • pnpm exec pkg . --out-path dist will use the pkg.targets list from package.json, which can trigger cross-compilation and defeats the "native arch" intent of this job. Use the per-job target from the matrix (or otherwise constrain targets) so each runner only builds one native binary.
      - name: build standalone binaries (native arch)
        run: pnpm exec pkg . --out-path dist
  • Files reviewed: 3/3 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +15 to +18
include:
- os: ubuntu-latest
- os: macos-latest
- os: windows-latest
Comment on lines 42 to 47
- name: checksums
shell: bash
run: |
cd dist
for f in *; do sha256sum "$f" > "$f.sha256"; done

Comment thread package.json
Comment on lines 24 to +29
"targets": [
"node20-linux-x64",
"node20-linux-arm64",
"node20-macos-x64",
"node20-macos-arm64",
"node20-win-x64"
"node22-linux-x64",
"node22-linux-arm64",
"node22-macos-x64",
"node22-macos-arm64",
"node22-win-x64"
Comment thread .github/workflows/ci.yml
Comment on lines 11 to +14
strategy:
fail-fast: false
matrix:
node: [20, 22, 24]
node: [22, 24]
dp9u0 and others added 2 commits August 31, 2026 16:40
Previously the only way to bypass the 24h TTL was deleting
problems.json by hand. `leetcode cache -r` drops the cached list (and
its meta) and re-fetches immediately, printing how many questions
came back.

Co-Authored-By: Claude <noreply@anthropic.com>
`stat -c` previously rendered only this machine's lc-submit log
(stat.json). Fetch matchedUser.userCalendar.submissionCalendar from
graphql and fill the heatmap from the real per-day submission counts,
falling back to the local log with a warning when the fetch fails.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 31, 2026 09:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The release workflow and new CLI paths contain reliability issues (portable checksums, pkg target selection vs “native arch” intent, and unsafe calendar parsing/user access) that could break releases or crash the CLI.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (4)

test/commands/test_cache.js:91

  • This test currently only asserts process.exitCode on refresh failure; if the intent is to preserve the existing cached problems list when refresh fails, add an assertion that the old cache remains available.
  it('should fail loudly if refresh fails', function(done) {
    cache.set('problems', [{fid: 1}]);
    cmd.__set__('core', {getProblems: (t, cb) => cb('refresh error')});

    cmd.handler({refresh: true, dontTranslate: true});

    const text = out.join('\n');
    assert.include(text, 'refresh error');
    assert.equal(process.exitCode, 1);
    done();
  });

test/commands/test_stat.js:90

  • Same as above: the timeout isn't needed for this failure-path test when getCalendar is stubbed synchronously.
    cmd.handler({lock: true, cal: true});
    setTimeout(() => {
      const text = stripAnsi(out.join('\n'));
      assert.include(text, 'using local log');
      done();
    }, 10);
  });

.github/workflows/release.yml:47

  • The checksum step uses sha256sum, which is not available by default on macOS runners (and can vary on Windows even under bash). Using Node's crypto makes this portable across all runners already in the matrix.
      - name: checksums
        shell: bash
        run: |
          cd dist
          for f in *; do sha256sum "$f" > "$f.sha256"; done

.github/workflows/release.yml:40

  • pnpm exec pkg . --out-path dist will build all targets listed in package.json's pkg.targets. That includes cross-arch targets (e.g. linux-arm64 from ubuntu x64, macos-x64 from an arm64 macOS runner), which contradicts the 'native arch only' comment and can reintroduce the OpenSSL cross-compile failure you’re trying to avoid. Consider explicitly setting --targets per matrix entry (and/or adding native arm64/x64 runners) so each job builds only what its runner can build reliably.
      # pkg compiles node from source for any target without a cached
      # binary, which cannot be cross-compiled (arm64 from an x64 host
      # fails in openssl's arm_arch.h). Building the native arch only
      # avoids that: the host arch is inferred from the runner and pkg
      # picks the matching node* target from the config.
      - name: build standalone binaries (native arch)
        run: pnpm exec pkg . --out-path dist
  • Files reviewed: 11/11 changed files
  • Comments generated: 8
  • Review effort level: Lite

Comment thread lib/plugins/leetcode.js
Comment on lines +483 to +486
opts.body = {
query: 'query cal($username: String!) { matchedUser(username: $username) { userCalendar { submissionCalendar } } }',
variables: {username: session.getUser().name}
};
Comment thread lib/plugins/leetcode.js
Comment on lines +494 to +496
const cal = body.data.matchedUser.userCalendar;
if (!cal) return cb('failed to load submission calendar!');
try {
Comment thread lib/plugins/leetcode.js
Comment on lines +476 to +478
// server-side submission calendar: {unixDay: submissionCount}
plugin.getCalendar = function(cb) {
log.debug('running leetcode.getCalendar');
Comment thread lib/commands/cache.js
Comment on lines +46 to +55
if (argv.refresh) {
// drop the problems cache so the next fetch is a fresh one
cache.del(h.KEYS.problems);
cache.del(h.KEYS.problemsMeta);
core.getProblems(!argv.dontTranslate, function(e, problems) {
if (e) return log.fail(e);
log.info('Problems list refreshed (' + problems.length + ' questions).');
});
return;
}
Comment on lines +68 to +79
const NEW = [{fid: 1, name: 'new'}, {fid: 2, name: 'two'}];
cmd.__set__('core', {getProblems: (t, cb) => cb(null, NEW)});

cmd.handler({refresh: true, dontTranslate: true});

const text = out.join('\n');
assert.include(text, 'refreshed (2 questions)');
// the problems cache was dropped so the next fetch re-pulls
assert.equal(cache.get('problems'), null);
assert.equal(cache.get('problemsMeta'), null);
done();
});
Comment thread lib/commands/stat.js
Comment on lines +148 to 150
// graph[i] = submission count i days ago; prefers the server calendar
// and falls back to the local lc-submit log
const graph = [];
Comment on lines +67 to +76
cmd.handler({lock: true, cal: true});
// async getCalendar -> handler prints inside callback
setTimeout(() => {
const text = stripAnsi(out.join('\n'));
assert.include(text, 'Sun');
assert.include(text, 'Mon');
assert.match(text, /▣/, 'submission cells rendered');
done();
}, 10);
});
Comment on lines +63 to +67
uses: actions/download-artifact@v4
with:
path: dist-all
merge-multiple: true

dp9u0 added 2 commits August 31, 2026 17:25
Drop .travis.yml and Dockerfile (CI moved to GitHub Actions), the
old bin/pkg* packaging scripts and bin/install (replaced by pkg +
release workflow), a stray 1.js debug file, and the stale npm
package-lock.json (project uses pnpm). Update .npmignore for the
renamed eslint config and fix the issue template to reference
pnpm and the main branch.
Delete the company plugin (outdated 2017 hardcoded company/tag
mappings) and solution.discuss (its --solution command was removed,
leaving getSolution without callers). Drop the win7/ascii icon
themes and make icon fallback to 'default' on all platforms.
Update plugin/list examples and the affected tests.
Copilot AI review requested due to automatic review settings August 31, 2026 09:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

langToCommentStyle('all') crashed with 'Cannot read properties of
undefined (reading style)' when submission ran without -l (default
'all' is not a real lang). Return an empty style so the export
degrades gracefully instead of throwing.
leetcode.com's getProblemOfToday queries activeDailyCodingChallengeQuestion
which returns http 400 on leetcode.cn. Override it in the cn plugin with
the todayRecord query and add a dedicated test file.
Drop the github/linkedin login options from user command, the
githubLogin/linkedinLogin implementations, their config URLs, and
the cache plugin wrappers. The HTML-scraping flows are long broken
against current github/linkedin pages and unused; cookie login
remains the supported path.
getUser looked up a list literally named 'Favorite', which leetcode.cn
never provides (users name lists freely), so user.hash stayed undefined
and starProblem sent favoriteIdHash: undefined -> graphql 400. Fall back
to the first private favorite when 'Favorite' is absent; leetcode.com
behavior is unchanged.
Remove the githubLogin/linkedinLogin methods and the now-orphaned
requestLeetcodeAndSave helper. HTML form scraping of github/linkedin
login pages is long broken; cookie login is the supported path.
file.meta split the @lc comment line on spaces, so 'id=LCR 064'
yielded id='LCR' and dropped the numeric part, breaking test/push
for all LCP/LCR/LCS problems. Append following bare tokens (until
the next key=value) to a value, keeping 'LCR 064' intact while
plain numeric ids and tab-separated pairs still parse.
Copilot AI review requested due to automatic review settings September 1, 2026 05:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The updated release workflow has concrete correctness/portability issues (pkg target selection vs multi-target config, and non-portable checksum tooling) that can break releases/CI.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (4)

.github/workflows/release.yml:40

  • The build job runs pnpm exec pkg . without --targets, but package.json defines a multi-target pkg.targets list (linux x64+arm64, macOS x64+arm64, win x64). pkg will attempt to build every configured target on each runner, reintroducing cross-arch builds (e.g. linux-arm64 on ubuntu-latest x64) despite the “native arch only” comment, and can fail when a target requires a from-source Node build.
      # pkg compiles node from source for any target without a cached
      # binary, which cannot be cross-compiled (arm64 from an x64 host
      # fails in openssl's arm_arch.h). Building the native arch only
      # avoids that: the host arch is inferred from the runner and pkg
      # picks the matching node* target from the config.
      - name: build standalone binaries (native arch)
        run: pnpm exec pkg . --out-path dist

.github/workflows/release.yml:47

  • The checksum step uses sha256sum, which is available on Ubuntu but typically not present on macOS runners (and can vary on Windows even under bash). This can cause the build matrix to fail before artifacts are uploaded.
      - name: checksums
        shell: bash
        run: |
          cd dist
          for f in *; do sha256sum "$f" > "$f.sha256"; done

lib/plugins/leetcode.js:496

  • getCalendar assumes session.getUser().name is always present and that body.data.matchedUser.userCalendar exists. If the username wasn't persisted (e.g. getUserInfo failed) or GraphQL returns {errors: ...} / an unexpected body shape, this will throw a TypeError instead of returning a helpful error to the caller.
  const opts = plugin.makeOpts(config.sys.urls.graphql);
  opts.headers.Origin = config.sys.urls.base;
  opts.headers.Referer = config.sys.urls.base;
  opts.json = true;
  opts.body = {
    query:     'query cal($username: String!) { matchedUser(username: $username) { userCalendar { submissionCalendar } } }',
    variables: {username: session.getUser().name}
  };

  const spin = h.spin('Retrieving submission calendar');
  request.post(opts, function(e, resp, body) {
    spin.stop();
    e = plugin.checkError(e, resp, 200);
    if (e) return cb(e);

    const cal = body.data.matchedUser.userCalendar;
    if (!cal) return cb('failed to load submission calendar!');
    try {

test/commands/test_stat.js:90

  • These tests wait on a fixed setTimeout(..., 10) even though the stubbed getCalendar callback is invoked synchronously; this adds unnecessary delay and can introduce flakiness on slow CI. Prefer asserting immediately after cmd.handler(...) (or use setImmediate/process.nextTick if you want to model async).
  • Files reviewed: 35/41 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines 31 to +39

- run: pnpm install --frozen-lockfile

- name: build standalone binaries
# pkg compiles node from source for any target without a cached
# binary, which cannot be cross-compiled (arm64 from an x64 host
# fails in openssl's arm_arch.h). Building the native arch only
# avoids that: the host arch is inferred from the runner and pkg
# picks the matching node* target from the config.
- name: build standalone binaries (native arch)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants