diff --git a/.github/workflows/build-gems.yml b/.github/workflows/build-gems.yml index e743e2c7a..7556cced2 100644 --- a/.github/workflows/build-gems.yml +++ b/.github/workflows/build-gems.yml @@ -18,7 +18,7 @@ jobs: id: fetch with: supported-ruby-platforms: | - exclude: [arm-linux, x64-mingw32] + exclude: [arm-linux, x64-mingw32, aarch64-mingw-ucrt] stable-ruby-versions: | exclude: [head] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a569f4ab8..84cdb22c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,13 +17,10 @@ on: type: string description: "Pre-release name to be released" required: true - secrets: - NODE_AUTH_TOKEN: - required: true jobs: lint: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: ${{ github.event_name == 'pull_request' }} steps: - uses: actions/checkout@v4 @@ -47,7 +44,7 @@ jobs: entry: - { target: wasm32-unknown-wasip1 } - { target: wasm32-unknown-emscripten } - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 @@ -66,11 +63,9 @@ jobs: push: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/tags/*' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max build-rake-task-matrix: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 outputs: entries: ${{ steps.set-matrix.outputs.entries }} steps: @@ -99,7 +94,7 @@ jobs: matrix: entry: ${{ fromJson(needs.build-rake-task-matrix.outputs.entries) }} needs: [build-rake-task-matrix] - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -107,7 +102,7 @@ jobs: - uses: actions/download-artifact@v4 with: name: build-manifest - - uses: actions/cache@v4.1.2 + - uses: actions/cache@v4.2.3 if: ${{ matrix.entry.rubies_cache_key != null }} with: path: ./rubies @@ -120,8 +115,6 @@ jobs: with: context: builders/${{ matrix.entry.builder }} load: true - cache-from: type=gha - cache-to: type=gha,mode=max - name: Setup builder container run: | docker run -dit -v "$GITHUB_WORKSPACE:/home/me/build" -w /home/me/build \ @@ -152,6 +145,10 @@ jobs: with: ruby-version: "3.4.1" bundler-cache: false + - uses: actions/setup-node@v4 + if: ${{ matrix.entry.test != '' }} + with: + node-version: "22.20.0" - name: rake ${{ matrix.entry.test }} run: | bundle install --with=check --without=development @@ -160,8 +157,11 @@ jobs: release-artifacts: needs: [rake-tasks] - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: ${{ startsWith(github.ref, 'refs/tags/') || inputs.publish }} + permissions: + id-token: write # Required for OIDC + contents: write steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 @@ -172,7 +172,7 @@ jobs: path: release - uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 24 registry-url: https://registry.npmjs.org/ - uses: ruby/setup-ruby@v1 with: @@ -183,4 +183,3 @@ jobs: - run: bundle exec rake "ci:publish[${PREREL_NAME:-$GITHUB_REF_NAME}]" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml index 3a4ba7954..f63de4520 100644 --- a/.github/workflows/nightly-release.yml +++ b/.github/workflows/nightly-release.yml @@ -11,7 +11,7 @@ on: jobs: create-nightly-tag: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 outputs: tag-name: ${{ steps.generate-tag.outputs.TAG_NAME }} steps: @@ -32,5 +32,3 @@ jobs: with: publish: true prerel_name: ${{ needs.create-nightly-tag.outputs.tag-name }} - secrets: - NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} diff --git a/.github/workflows/prune-caches.yml b/.github/workflows/prune-caches.yml new file mode 100644 index 000000000..e2c039e99 --- /dev/null +++ b/.github/workflows/prune-caches.yml @@ -0,0 +1,21 @@ +name: Prune Actions caches + +on: + schedule: + - cron: '0 21 * * *' + workflow_dispatch: + +permissions: + contents: read + actions: write + +jobs: + prune: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - run: rake ci:prune_caches + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01ef08511..f33349920 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -112,7 +112,7 @@ $ git push origin 0.6.0 # After GitHub Actions "Build gems" is done # https://github.com/ruby/ruby.wasm/actions/workflows/build-gems.yml $ gh run download -$ for pkg in cross-gem/pkg/ruby_wasm-*; do gem push $pkg; done +$ for pkg in cross-gem-*/ruby_wasm-*; do gem push $pkg; done $ gem build && gem push ruby_wasm-*.gem && rm ruby_wasm-*.gem $ (cd packages/gems/js/ && gem build && gem push js-*.gem && rm js-*.gem) $ rake bump_dev_version @@ -129,7 +129,7 @@ $ npm install --save @ruby/wasm-wasi@latest # or if you want the nightly snapshot $ npm install --save @ruby/wasm-wasi@next # or you can specify the exact snapshot version -$ npm install --save @ruby/wasm-wasi@2.7.1-2025-01-23-a +$ npm install --save @ruby/wasm-wasi@2.7.2-2025-10-03-a ``` diff --git a/Cargo.lock b/Cargo.lock index 7afd429c2..e90b01f85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1361,7 +1361,7 @@ dependencies = [ "wasi-virt", "wasm-compose 0.219.1", "wit-component 0.216.0", - "wizer", + "wizer 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1835,13 +1835,13 @@ dependencies = [ [[package]] name = "wasi-vfs-cli" version = "0.5.3" -source = "git+https://github.com/kateinoigakukun/wasi-vfs/?tag=v0.5.3#39d83db2b2518d1f991276960d22d3948d62f7df" +source = "git+https://github.com/kateinoigakukun/wasi-vfs/?tag=v0.5.3-p1#32437aed43b117fe6905f547924196c15bf7b966" dependencies = [ "anyhow", "structopt", "wasm-encoder 0.212.0", "wasmparser 0.212.0", - "wizer", + "wizer 6.0.0 (git+https://github.com/kateinoigakukun/wizer.git?branch=katei/add-env-option-6.0.0)", ] [[package]] @@ -2750,6 +2750,21 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "wizer" +version = "6.0.0" +source = "git+https://github.com/kateinoigakukun/wizer.git?branch=katei/add-env-option-6.0.0#8e7158013eb3d1059504229eff834eb1f3e33949" +dependencies = [ + "anyhow", + "cap-std", + "log", + "rayon", + "wasi-common", + "wasm-encoder 0.202.0", + "wasmparser 0.202.0", + "wasmtime", +] + [[package]] name = "zerocopy" version = "0.7.34" diff --git a/Gemfile b/Gemfile index adfecca75..84a10c84c 100644 --- a/Gemfile +++ b/Gemfile @@ -14,5 +14,5 @@ group :check do # Use the latest version of webrick for URI change in Ruby 3.4 gem "webrick", "~> 1.8.2" gem "syntax_tree", "~> 3.5" - gem "steep", "~> 1.9" if RUBY_VERSION >= "3.1.0" + gem "steep", "1.10.0" if RUBY_VERSION >= "3.1.0" end diff --git a/README.md b/README.md index e3916a9f5..1b4e18637 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Create and save `index.html` page with the following contents: ```html - + + + + + diff --git a/packages/npm-packages/ruby-wasm-wasi/example/lucky.html b/packages/npm-packages/ruby-wasm-wasi/example/lucky.html index 1042d8c00..625a04a2c 100644 --- a/packages/npm-packages/ruby-wasm-wasi/example/lucky.html +++ b/packages/npm-packages/ruby-wasm-wasi/example/lucky.html @@ -1,5 +1,5 @@ - +
+ diff --git a/packages/npm-packages/ruby-wasm-wasi/package.json b/packages/npm-packages/ruby-wasm-wasi/package.json index f7eef4e85..8910a8c4e 100644 --- a/packages/npm-packages/ruby-wasm-wasi/package.json +++ b/packages/npm-packages/ruby-wasm-wasi/package.json @@ -1,6 +1,6 @@ { "name": "@ruby/wasm-wasi", - "version": "2.7.1", + "version": "2.7.2", "description": "WebAssembly port of CRuby with WASI", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", @@ -54,11 +54,11 @@ }, "devDependencies": { "@bytecodealliance/jco": "1.8.1", - "@rollup/plugin-typescript": "^12.1.1", - "@types/node": "22.10.1", - "prettier": "^3.4.1", - "typescript": "^5.7.2", - "vitest": "^2.1.6" + "@rollup/plugin-typescript": "^12.1.4", + "@types/node": "24.1.0", + "prettier": "^3.6.2", + "typescript": "^5.9.2", + "vitest": "^3.2.4" }, "dependencies": { "@bjorn3/browser_wasi_shim": "^0.3.0", diff --git a/packages/npm-packages/ruby-wasm-wasi/src/vm.ts b/packages/npm-packages/ruby-wasm-wasi/src/vm.ts index 01f9530e4..ef4ba9802 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/vm.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/vm.ts @@ -132,7 +132,12 @@ export class RubyVM { vm.addToImports(imports); options.addToImports?.(imports); const instance = await WebAssembly.instantiate(module, imports); - await vm.setInstance(instance); + try { + await vm.setInstance(instance); + } catch (e) { + console.error("Failed to instantiate Ruby VM. Please make sure that you have added `gem \"js\"` to your Gemfile."); + throw e; + } options.setMemory?.(instance.exports.memory as WebAssembly.Memory); wasip1.initialize(instance); vm.initialize(options.args); diff --git a/rakelib/ci.rake b/rakelib/ci.rake index 3f4889be6..6099ec609 100644 --- a/rakelib/ci.rake +++ b/rakelib/ci.rake @@ -132,6 +132,40 @@ namespace :ci do end end + desc "Prune old caches in GitHub Actions" + task :prune_caches, [:days] do |_, args| + RubyWasm::Toolchain.check_executable("gh") + + days = (args[:days] || 1).to_i + repo = ENV["GITHUB_REPOSITORY"] || "ruby/ruby.wasm" + cutoff = (Time.now.utc - days * 86_400).iso8601 + + puts "Deleting caches last accessed before #{cutoff}…" + + page = 1 + deleted = 0 + + loop do + resp = `gh api -H 'Accept: application/vnd.github+json' "/repos/#{repo}/actions/caches?per_page=100&page=#{page}"` + raise "gh api failed" unless $?.success? + + data = JSON.parse(resp) + caches = data["actions_caches"] + + old = caches.select { |c| c["last_accessed_at"] < cutoff } + old.each do |c| + id = c["id"] + system("gh api -X DELETE /repos/#{repo}/actions/caches/#{id}") + deleted += 1 + end + + break if caches.size < 100 + page += 1 + end + + puts "Deleted #{deleted} caches older than #{days} days." + end + desc "Publish artifacts as a GitHub Release" task :publish, [:tag] do |t, args| RubyWasm::Toolchain.check_executable("gh") diff --git a/ruby_wasm.gemspec b/ruby_wasm.gemspec index 80471f9bf..355ea8aaf 100644 --- a/ruby_wasm.gemspec +++ b/ruby_wasm.gemspec @@ -29,4 +29,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.extensions = ["ext/ruby_wasm/Cargo.toml"] + + spec.add_dependency "logger" end diff --git a/sig/ruby_wasm/cli.rbs b/sig/ruby_wasm/cli.rbs index f4f43e705..65ee28e74 100644 --- a/sig/ruby_wasm/cli.rbs +++ b/sig/ruby_wasm/cli.rbs @@ -29,7 +29,10 @@ module RubyWasm def initialize: (stdout: IO, stderr: IO) -> void + def run: (Array[String] args) -> void + def build: (Array[String] args) -> void + def do_build_with_force_ruby_platform: (cli_options options) -> void def pack: (Array[String] args) -> void private @@ -49,5 +52,6 @@ module RubyWasm self.@logger: Logger? def self.logger: () -> Logger + def self.logger=: (Logger) -> void attr_accessor self.log_level: Symbol end diff --git a/sig/ruby_wasm/packager.rbs b/sig/ruby_wasm/packager.rbs index a91fd7823..c3cee357d 100644 --- a/sig/ruby_wasm/packager.rbs +++ b/sig/ruby_wasm/packager.rbs @@ -70,8 +70,12 @@ class RubyWasm::Packager def build_strategy: () -> BuildStrategy class BuildStrategy + include RubyWasm::_Cacheable + @packager: RubyWasm::Packager def initialize: (RubyWasm::Packager) -> void + def target: () -> RubyWasm::Target + def artifact: () -> string def build: (RubyWasm::BuildExecutor, untyped options) -> String def specs_with_extensions: () -> Array[[untyped, Array[string]]] def build_gem_exts: (RubyWasm::BuildExecutor, string gem_home) -> void