From cbcb1b556cc0be19ec81ffa4c53606684589aee9 Mon Sep 17 00:00:00 2001 From: Vladimir Dementyev Date: Fri, 13 Sep 2024 11:39:01 -0700 Subject: [PATCH] + anyt --- .github/workflows/ci.yml | 34 +++++++++++++++++++++++++++++----- Gemfile | 38 +++----------------------------------- Makefile | 10 ++++++++++ README.md | 27 ++++++++++++++++++++++++++- gemfiles/anycable.gemfile | 25 +++++++++++++++++++++++++ gemfiles/rails.gemfile | 14 ++++++++++++++ 6 files changed, 107 insertions(+), 41 deletions(-) create mode 100644 gemfiles/anycable.gemfile create mode 100644 gemfiles/rails.gemfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8025759..cb8d4bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: jobs: - wsdirector: + smoke: if: ${{ !contains(github.event.head_commit.message, '[ci skip]') }} runs-on: ubuntu-latest env: @@ -24,6 +24,7 @@ jobs: fail-fast: false matrix: server: ["puma", "anycable"] + scenario: ["echo", "broadcast"] steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 @@ -34,9 +35,32 @@ jobs: run: | bundle exec bento --${{ matrix.server }} & bin/wait_tcp 8080 - - name: Run echo scenario + - name: Run WS director scenario run: | - SCENARIO=echo make wsdirector - - name: Run broadcast scenario + SCENARIO=${{ matrix.scenario }} make wsdirector + + conformance: + if: ${{ !contains(github.event.head_commit.message, '[ci skip]') }} + runs-on: ubuntu-latest + env: + BUNDLE_JOBS: 4 + BUNDLE_RETRY: 3 + CI: true + services: + redis: + image: redis:7.0-alpine + ports: ["6379:6379"] + options: --health-cmd="redis-cli ping" --health-interval 1s --health-timeout 3s --health-retries 30 + strategy: + fail-fast: false + matrix: + server: ["puma", "anycable"] + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.3 + bundler-cache: true + - name: Run conformance tests via AnyT run: | - SCENARIO=broadcast make wsdirector + make anyt-${{ matrix.server }} diff --git a/Gemfile b/Gemfile index dbf10e0..42b620f 100644 --- a/Gemfile +++ b/Gemfile @@ -1,17 +1,6 @@ source "https://rubygems.org" -rails_path = File.file?(File.join(__dir__, ".rails-path")) ? File.read(File.join(__dir__, ".rails-path")).strip : File.join(__dir__, "../rails") - -# Use local Rails copy if available -if File.directory?(rails_path) - gem "rails", group: :preload, path: rails_path -# Use Rails from a git repo -elsif File.file?(File.join(__dir__, ".rails-revision")) - git, branch = *File.read(File.join(__dir__, ".rails-revision")).strip.split("#", 2) - gem "rails", group: :preload, git:, branch: -else - gem "rails", "~> 8.0" -end +eval_gemfile "gemfiles/rails.gemfile" # Baseline setup: Puma + Redis pub/sub gem "puma", "~> 6.4" @@ -20,31 +9,10 @@ gem "redis", "~> 5.0", group: :preload # Async setup # TODO -# AnyCable setup -gem "grpc_kit" if ENV["ANYCABLE_GRPC_IMPL"] == "grpc_kit" -gem "grpc" unless ENV["ANYCABLE_GRPC_IMPL"] == "grpc_kit" - -anycable_dir_path = File.file?(File.join(__dir__, ".anycable-path")) ? File.read(File.join(__dir__, ".anycable-path")).strip : File.join(__dir__, "..") - -if File.file?(File.join(anycable_dir_path, "anycable/anycable-core.gemspec")) - gem "anycable-core", group: :preload, path: File.join(anycable_dir_path, "anycable") -elsif File.file?(File.join(__dir__, ".anycable-revision")) - git, branch = *File.read(File.join(__dir__, ".anycable-revision")).strip.split("#", 2) - gem "anycable-core", require: false, group: :preload, git:, branch: -else - gem "anycable-core" -end - -if File.file?(File.join(anycable_dir_path, "anycable-rails/anycable-rails.gemspec")) - gem "anycable-rails", group: :preload, path: File.join(anycable_dir_path, "anycable-rails") -elsif File.file?(File.join(__dir__, ".anycable-rails-revision")) - git, branch = *File.read(File.join(__dir__, ".anycable-rails-revision")).strip.split("#", 2) - gem "anycable-rails", require: false, group: :preload, git:, branch: -else - gem "anycable-rails" -end +eval_gemfile "gemfiles/anycable.gemfile" # Tools gem "wsdirector-cli", require: false +gem "anyt", "~> 1.4", require: false gem "debug" unless ENV["CI"] diff --git a/Makefile b/Makefile index 0e3c0d2..63c8411 100644 --- a/Makefile +++ b/Makefile @@ -21,4 +21,14 @@ k6: build-k6 wsdirector: @bundle exec wsdirector -f scripts/wsdirector/$(SCENARIO).yml -u ws://localhost:8080/cable -s $(SCALE) +bin/dist/anycable-go: + @bin/anycable-go -v + +anyt-puma: + @bundle exec anyt --self-check + +anyt-anycable: bin/dist/anycable-go + ANYCABLE_HEADERS=cookie,x-api-token \ + bundle exec anyt -c "bin/dist/anycable-go" --target-url="ws://localhost:8080/cable" + .PHONY: websocket-bench diff --git a/README.md b/README.md index afc9e3b..a5446cb 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Install the dependencies: bundle install ``` -NOTE: You can use local dependencies (Rails, AnyCable) either by following path conventions or by providing `.xxx-path` files (see the Gemfile). +NOTE: You can use local dependencies (Rails, AnyCable) either by following path conventions or by providing `.xxx-path` files (see the Gemfile/gemfiles). Now you should be able to run a minimal Action Cable application via one of the supported web servers. By default, Puma is used: @@ -42,6 +42,8 @@ $ bundle exec bento --anycable ## Tests +### Smoke tests + You can run basic smoke tests via [wsdirector][] as follows (NOTE: the server must be running): ```sh @@ -64,5 +66,28 @@ Group listener: 40 clients, 0 failures ``` +### Conformance tests + +We use [AnyT][] to run Action Cable conformance tests. We use make files to encapsulate difference between different server configurations, for example: + +```sh +$ make anyt-puma + +Starting AnyT v1.4.0 (pid: 21243) + +Subscription aknowledgement + Client receives subscription confirmation PASS (0.52s) + +Subscription aknowledgement + Client receives subscription rejection PASS (0.51s) + +... + +32 tests, 80 assertions, 0 failures, 0 errors, 1 skips +``` + +You can run specific tests by name via the `ANYT_FILTER_TESTS=` env var. To see all scenarios, run `bundle exec anyt -l`. + [the-pr]: https://github.com/rails/rails/pull/50979 [wsdirector]: https://github.com/palkan/wsdirector +[AnyT]: https://github.com/anycable/anyt diff --git a/gemfiles/anycable.gemfile b/gemfiles/anycable.gemfile new file mode 100644 index 0000000..a8e43c9 --- /dev/null +++ b/gemfiles/anycable.gemfile @@ -0,0 +1,25 @@ +# AnyCable setup +gem "grpc_kit" if ENV["ANYCABLE_GRPC_IMPL"] == "grpc_kit" +gem "grpc" unless ENV["ANYCABLE_GRPC_IMPL"] == "grpc_kit" + +root_dir = File.join(__dir__, "..") + +anycable_dir_path = File.file?(File.join(root_dir, ".anycable-path")) ? File.read(File.join(root_dir, ".anycable-path")).strip : File.join(root_dir, "..") + +if File.file?(File.join(anycable_dir_path, "anycable/anycable-core.gemspec")) + gem "anycable-core", group: :preload, path: File.join(anycable_dir_path, "anycable") +elsif File.file?(File.join(root_dir, ".anycable-revision")) + git, branch = *File.read(File.join(root_dir, ".anycable-revision")).strip.split("#", 2) + gem "anycable-core", require: false, group: :preload, git:, branch: +else + gem "anycable-core" +end + +if File.file?(File.join(anycable_dir_path, "anycable-rails/anycable-rails.gemspec")) + gem "anycable-rails", group: :preload, path: File.join(anycable_dir_path, "anycable-rails") +elsif File.file?(File.join(root_dir, ".anycable-rails-revision")) + git, branch = *File.read(File.join(root_dir, ".anycable-rails-revision")).strip.split("#", 2) + gem "anycable-rails", require: false, group: :preload, git:, branch: +else + gem "anycable-rails" +end diff --git a/gemfiles/rails.gemfile b/gemfiles/rails.gemfile new file mode 100644 index 0000000..8df00d4 --- /dev/null +++ b/gemfiles/rails.gemfile @@ -0,0 +1,14 @@ +root_dir = File.join(__dir__, "../..") + +rails_path = File.file?(File.join(root_dir, ".rails-path")) ? File.read(File.join(root_dir, ".rails-path")).strip : File.join(root_dir, "../rails") + +# Use local Rails copy if available +if File.directory?(rails_path) + gem "rails", group: :preload, path: rails_path +# Use Rails from a git repo +elsif File.file?(File.join(root_dir, ".rails-revision")) + git, branch = *File.read(File.join(root_dir, ".rails-revision")).strip.split("#", 2) + gem "rails", group: :preload, git:, branch: +else + gem "rails", "~> 8.0" +end