Skip to content

Commit

Permalink
feat: Lesson 2 [1]
Browse files Browse the repository at this point in the history
  • Loading branch information
maxirmx committed Jan 11, 2025
1 parent 4221f34 commit 3838e00
Show file tree
Hide file tree
Showing 10 changed files with 287 additions and 30 deletions.
22 changes: 16 additions & 6 deletions .github/workflows/tutorial.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ concurrency:
cancel-in-progress: true

jobs:
lesson-1:
lessons-1-2:
runs-on: macos-latest
steps:

Expand All @@ -26,22 +26,32 @@ jobs:
- name: Install gem
run: gem install tebako

- name: Checkout sample
- name: Checkout
uses: actions/checkout@v4

- name: Package
- name: Package 1_hello_world
run: |
tebako press --root=tutorial/1_hello_world/sample --entry=hello_world.rb
- name: Run packaged application
- name: Run packaged 1_hello_world application
run: |
./hello_world
otool -L hello_world
- name: Package with a difefrent name
- name: Package 1_hello_world with a difefrent name
run: |
tebako press --root=tutorial/1_hello_world/sample --entry=hello_world.rb --output=lesson-1
- name: Run packaged application with a diffeernt name
- name: Run packaged 1_hello_world application with a different name
run: |
./lesson-1
- name: Package 2_scenarios gemfile sample
run: |
tebako press -r tutorial/2_scenarios/gemfile.sample -e ticker.rb -o ticker.tebako.
# Cannot run this sample since GH Actions does not allow such websocket connection to the outside world

- name: Package 2_scenarios gemspec sample
run: |
tebako press -r tutorial/2_scenarios/gemspec.sample -e tebako-table-cli -o table.tebako
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ log
# Tutorila
hello_world
source_filesystem/
*.tebako
24 changes: 0 additions & 24 deletions tutorial/1_hello_world/sample/hello_world.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1,5 @@
# frozen_string_literal: true

# Copyright (c) 2025 [Ribose Inc](https://www.ribose.com).
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# Tebako tutorial: Lesson 1

puts "Hello, World!"
176 changes: 176 additions & 0 deletions tutorial/2_scenarios/Lesson-2.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
= Tebako tutorial - Lesson 2. "Packaging scenarios"

In the Lesson 1 we have packaged simple script without dependencies. Now we will talk about more complex scenarios.

== Packaging a bundle

Let's package a script that has external dependencies.

[source,Ruby]
----
require "async"
require "async/http"
require "async/websocket"
URL = "wss://stream.binance.com:9443/ws/btcusdt@bookTicker"
Signal.trap("INT") do
puts "\n\nStopping..."
exit(0)
end
Async do |task|
endpoint = Async::HTTP::Endpoint.parse(URL, alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
Async::WebSocket::Client.connect(endpoint) do |connection|
while message = connection.read
puts message.parse
end
end
end
----

This script recieves the BTC/USDT ticker from the Binance exchange and outputs it to the console.
It uses the `async`, `async-http`, and `async-websocket` gems, so I will add a Gemfile to manage dependencies:

[source,Ruby]
----
source "https://rubygems.org"
gem "async"
gem "async-http"
gem "async-websocket"
----

We put the script into the `gemfile.sample/ticker.rb` file and the Gemfile into the `gemfile.sample/Gemfile` file and package it with tebako.
I will use short aliases for the parameters:

[source,sh]
----
tebako press -r gemfile.sample -e ticker.rb -o ticker.tebako
----

Note, that we do not run `bundle install` before packaging. Tebako creates its own environment that is isolated from the system where we package.
It works similar to rbenv. When packaging starts the environment is initialized with tebako-patched Ruby and `bundle install` is executed by tebako
against this environment.

You can see this sequence in tebako console log:

[source]
----
-- Running init script
... creating packaging environment at /Users/runner/.tebako/o/s
-- Running deploy script
... installing tebako-runtime gem
... @ /Users/runner/.tebako/o/s/bin/gem install tebako-runtime --no-document --install-dir /Users/runner/.tebako/o/s/lib/ruby/gems/3.2.0
... deploying Gemfile
... @ /Users/runner/.tebako/o/s/bin/bundle config set --local build.ffi --disable-system-libffi
... @ /Users/runner/.tebako/o/s/bin/bundle config set --local build.nokogiri --no-use-system-libraries
... @ /Users/runner/.tebako/o/s/bin/bundle config set --local force_ruby_platform false
*** It may take a long time for a big project. It takes REALLY long time on Windows ***
... @ /Users/runner/.tebako/o/s/bin/bundle install --jobs=3
... target entry point will be at /__tebako_memfs__/local/ticker.rb
... stripping the output
-- Running mkdwarfs script
... @ /Users/runner/.tebako/deps/bin/mkdwarfs -o /Users/runner/.tebako/o/p/fs.bin -i /Users/runner/.tebako/o/s --no-progress
----

== Packaging a gem

The most common ytem for packaging is previously developed gem. Note that tebako is an executable packager. That implies that we can package
a gem as an application but not as a library. Practicaly it means that tebako package runs of the gem executables which serves as the package
entry point.

We will use the folloing gem specification (`gemfile.sample/tebako-table.gemspec`)

[source,Ruby]
----
# frozen_string_literal: true
require_relative "lib/version"
Gem::Specification.new do |s|
s.name = "tebako-test"
s.version = Test::VERSION
s.summary = "A simple gem for tebako testing"
s.authors = ["Ribose"]
s.email = ["open.source@ribose.com"]
s.files = Dir.glob("lib/**/*") + Dir.glob("exe/**/*")
s.homepage = "https://github.com/tamitebako"
s.license = "Unlicense"
s.bindir = "exe"
s.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
s.add_dependency "text-table", "~> 1.2.4"
s.executables << "tebako-table-cli"
end
----

and three source files

* `gemfile.sample/exe/tebako-table-cli`

[source,Ruby]
----
# frozen_string_literal: true
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "tebako-table"
instance = Test::TebakoTable.new
instance.run
----

* `gemfile.sample/lib/tebako-table.rb`

[source,Ruby]
----
# frozen_string_literal: true
require "text-table"
require_relative "version"
module Test
class TebakoTable
def msg
table = Text::Table.new
table.head = %w[A B]
table.rows = [%w[a1 b1]]
table.rows << %w[a2 b2]
table
end
def run
puts <<~MSG
Running packaged tebako-table gem version #{VERSION}.
You shall see a nice text table below.
#{msg}
MSG
end
end
end
----

* `gemfile.sample/lib/version.rb`

[source,Ruby]
----
# frozen_string_literal: true
module Test
VERSION = "0.0.2"
end
----

Press command is the same:

[source,sh]
----
tebako press -r gemspec.sample -e tebako-table-cli -o table.tebako
----



== Live example

You can find the complete code of this lesson in the `tutorial/2_dependencies` directory of the tebako-samples repository.
The code is running on GHA via the `tutorial.yml` workflow.
9 changes: 9 additions & 0 deletions tutorial/2_scenarios/gemfile.sample/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

# Tebako tutorial: Lesson 2

source "https://rubygems.org"

gem "async"
gem "async-http"
gem "async-websocket"
24 changes: 24 additions & 0 deletions tutorial/2_scenarios/gemfile.sample/ticker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

# Tebako tutorial: Lesson 2

require "async"
require "async/http"
require "async/websocket"

URL = "wss://stream.binance.com:9443/ws/btcusdt@bookTicker"

Signal.trap("INT") do
puts "\n\nStopping..."
exit(0)
end

Async do |task|
endpoint = Async::HTTP::Endpoint.parse(URL, alpn_protocols: Async::HTTP::Protocol::HTTP11.names)

Async::WebSocket::Client.connect(endpoint) do |connection|
while message = connection.read
puts message.parse
end
end
end
9 changes: 9 additions & 0 deletions tutorial/2_scenarios/gemspec.sample/exe/tebako-table-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

# Tebako tutorial: Lesson 2

$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "tebako-table"

instance = Test::TebakoTable.new
instance.run
27 changes: 27 additions & 0 deletions tutorial/2_scenarios/gemspec.sample/lib/tebako-table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

# Tebako tutorial: Lesson 2

require "text-table"
require_relative "version"

module Test
class TebakoTable
def msg
table = Text::Table.new
table.head = %w[A B]
table.rows = [%w[a1 b1]]
table.rows << %w[a2 b2]
table
end

def run
puts <<~MSG
Running packaged tebako-table gem version #{VERSION}.
You shall see a nice text table below.
#{msg}
MSG
end
end
end
7 changes: 7 additions & 0 deletions tutorial/2_scenarios/gemspec.sample/lib/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

# Tebako tutorial: Lesson 2

module Test
VERSION = "0.0.2"
end
18 changes: 18 additions & 0 deletions tutorial/2_scenarios/gemspec.sample/tebako-table.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require_relative "lib/version"

Gem::Specification.new do |s|
s.name = "tebako-test"
s.version = Test::VERSION
s.summary = "A simple gem for tebako testing"
s.authors = ["Ribose"]
s.email = ["open.source@ribose.com"]
s.files = Dir.glob("lib/**/*") + Dir.glob("exe/**/*")
s.homepage = "https://github.com/tamitebako"
s.license = "Unlicense"
s.bindir = "exe"
s.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
s.add_dependency "text-table", "~> 1.2.4"
s.executables << "tebako-table-cli"
end

0 comments on commit 3838e00

Please sign in to comment.