Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing a package definition file Tebafile or tebako.yaml? #156

Open
ronaldtse opened this issue Jun 30, 2024 · 5 comments
Open

Implementing a package definition file Tebafile or tebako.yaml? #156

ronaldtse opened this issue Jun 30, 2024 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@ronaldtse
Copy link
Contributor

The Tebafile is a configuration file used by Tebako to define how your Ruby application should be packaged. It typically includes information about the application's dependencies, metadata, and the entry point for the application. This file contains directives that Tebako uses to bundle your application and its dependencies into a single, self-contained executable.

Here's a detailed breakdown of the Tebafile components:

Tebafile Components

Source

The source directive specifies the RubyGems source from which to fetch the gems. This is similar to the source directive in a Gemfile.

source "https://rubygems.org"

Gem Dependencies

You list your application's dependencies just as you would in a Gemfile. These dependencies will be included in the packaged application.

gem "sinatra"
gem "puma"

Tebako Block

The tebako block contains metadata and configuration settings for your application. Here are the key attributes you can define:

  • name: The name of the application.
  • version: The version of the application.
  • main: The entry point script for your application.
tebako do
  name "MyApp"
  version "0.1.0"
  main "app.rb"
end

Complete Example

Putting it all together, here’s a complete example of a Tebafile for a simple Sinatra application:

source "https://rubygems.org"

gem "sinatra"
gem "puma"

tebako do
  name "SinatraApp"
  version "0.1.0"
  main "app.rb"
end

Creating and Using a Tebafile

Step-by-Step Guide

  1. Create a new directory for your project:

    mkdir my_sinatra_app
    cd my_sinatra_app
  2. Create the application files:

    • Gemfile:

      source "https://rubygems.org"
      
      gem "sinatra"
      gem "puma"
    • app.rb:

      require 'sinatra'
      
      get '/' do
        'Hello, Tebako on Windows with Sinatra!'
      end
  3. Install the dependencies:

    bundle install
  4. Create the Tebafile:
    Create a file named Tebafile with the following content:

    source "https://rubygems.org"
    
    gem "sinatra"
    gem "puma"
    
    tebako do
      name "SinatraApp"
      version "0.1.0"
      main "app.rb"
    end
  5. Run Tebako to package the application:

    tebako build
  6. Run the packaged application:

    • Navigate to the build directory:
      cd build
    • Execute the packaged application:
      sinatra_app.exe

    Open a web browser and go to http://localhost:4567 to see your Sinatra application running.

Benefits of Using a Tebafile

  • Simplifies Configuration: Centralizes all packaging configuration in one file.
  • Consistent Builds: Ensures that the same configuration is used every time you build your application.
  • Dependency Management: Automatically includes all specified dependencies in the package.

By properly configuring your Tebafile, you ensure that Tebako can correctly package and deploy your Ruby application with all necessary dependencies and configurations.

More complex app

This example will include multiple dependencies, a database connection, and some additional configuration settings to illustrate how to handle a more sophisticated setup.

Example Tebafile for a Complex Ruby Application

Application Overview

For this example, let's assume we have a Ruby application that uses Sinatra for the web framework, ActiveRecord for ORM, SQLite3 as the database, and Puma as the web server. The application will also include some additional gems for functionality like HTTP requests and JSON parsing.

Directory Structure

my_complex_app/
├── Gemfile
├── Gemfile.lock
├── app.rb
├── config/
│   └── database.yml
├── models/
│   └── user.rb
└── Tebafile

Gemfile

First, here is the Gemfile for our application:

source "https://rubygems.org"

gem "sinatra"
gem "puma"
gem "activerecord"
gem "sinatra-activerecord"
gem "sqlite3"
gem "httparty"
gem "json"

app.rb

The main application file, app.rb, might look like this:

require 'sinatra'
require 'sinatra/activerecord'
require 'json'
require 'httparty'

set :database_file, 'config/database.yml'

get '/' do
  'Hello, Complex Tebako App!'
end

get '/users' do
  content_type :json
  User.all.to_json
end

get '/external_api' do
  response = HTTParty.get('https://api.example.com/data')
  response.body
end

config/database.yml

The database configuration file, config/database.yml, will look like this:

development:
  adapter: sqlite3
  database: db/development.sqlite3

production:
  adapter: sqlite3
  database: db/production.sqlite3

models/user.rb

The User model, models/user.rb, might look like this:

class User < ActiveRecord::Base
end

Tebafile

Finally, here is the Tebafile for this complex Ruby application:

source "https://rubygems.org"

gem "sinatra"
gem "puma"
gem "activerecord"
gem "sinatra-activerecord"
gem "sqlite3"
gem "httparty"
gem "json"

tebako do
  name "ComplexApp"
  version "1.0.0"
  main "app.rb"
  include "config"
  include "models"
  include "db"
end

Explanation of the Tebafile

  • source: Specifies the RubyGems source.
  • gem: Lists all the dependencies required by the application. These are the same as in the Gemfile.
  • tebako block:
    • name: The name of the application.
    • version: The version of the application.
    • main: The entry point script for the application (app.rb).
    • include: Specifies additional directories to include in the package. In this case, we include config, models, and db to ensure the database configuration, models, and database files are packaged.

Steps to Package and Run the Application

  1. Install Dependencies:

    bundle install
  2. Run Tebako to Package the Application:

    tebako build
  3. Run the Packaged Application:

    Navigate to the build directory and execute the packaged application:

    cd build
    complex_app.exe
  4. Access the Application:

    Open a web browser and navigate to http://localhost:4567 to see your application running. You can also access the /users endpoint to see JSON data from the database and the /external_api endpoint to fetch data from an external API.

This example demonstrates how to configure a Tebafile for a more complex Ruby application, ensuring that all necessary components and configurations are included in the package.

@ronaldtse
Copy link
Contributor Author

We also need to specify these paths in the Tebafile:

  • the ENTRYPOINT to run the default executable
  • the $PWD set when the entry point is run
  • the directory where Tebako is to package into memFS

@ronaldtse
Copy link
Contributor Author

Perhaps we should call this the tebako.yaml file:

---
# Gem source
source: "https://rubygems.org"

# Application metadata
name: "MyApp"
version: "1.0.0"

# Dependencies
dependencies:
  - sinatra
  - puma
  - activerecord
  - sinatra-activerecord
  - sqlite3
  - httparty
  - json

# Main entry point
main: "app.rb"

# Working directory
working_directory: "/app"

# Execution command
run_command: "ruby -I. app.rb"

# Directories to include
include:
  - config
  - models
  - db

# Environment variables
environment:
  RACK_ENV: production
  DATABASE_URL: "sqlite3:///app/db/production.sqlite3"
  LOG_LEVEL: info
  API_KEY: "your_api_key_here"

# Additional configuration
database:
  development:
    adapter: sqlite3
    database: db/development.sqlite3
  production:
    adapter: sqlite3
    database: db/production.sqlite3

# Any other Tebako-specific configurations
tebako_options:
  output_dir: "build"
  compress: true

The environment variables would be set when the application is loaded and run by Tebako.

This approach allows you to:

  • Easily view and modify environment variables in one place.
  • Set different environment variables for different deployment scenarios.
  • Keep sensitive information (like API keys) separate from your code.

Remember that for security reasons, you should not commit sensitive information like actual API keys to version control. Instead, you might use placeholder values in the committed file and replace them with real values during the deployment process.

If you need to handle more complex environment variable scenarios, you could potentially extend this to support:

  1. Different sets of environment variables for different environments (dev, test, prod).
  2. Referencing other environment variables or using simple templating.
  3. Loading some environment variables from external sources.

The exact implementation would depend on Tebako's capabilities and your specific requirements.

@ronaldtse ronaldtse changed the title Implementing a package definition file Tebafile Implementing a package definition file Tebafile or tebako.yaml? Jul 29, 2024
@ronaldtse ronaldtse added the enhancement New feature or request label Jul 29, 2024
@ronaldtse ronaldtse added this to Tebako Jul 29, 2024
@ronaldtse
Copy link
Contributor Author

Here are the sample tebako.yaml files for each of the five valid scenarios.

  1. Scenario 1: Simple ruby script
ruby:
  version: 3.2.4
  entry_point: my_script.rb
output:
  name: simple_script_package
  1. Scenario 2: Packaged gem
ruby:
  version: 3.2.4
  entry_point: my_gem_executable
gems:
  - name: my_packaged_gem.gem
    path: ./
output:
  name: packaged_gem_package
  1. Scenario 3: Gem source, no bundler
ruby:
  version: 3.2.4
  entry_point: my_gem_executable
build:
  gem:
    name: my_gem
output:
  name: gem_source_package
  1. Scenario 4: Gem source, bundler
ruby:
  version: 3.2.4
  entry_point: my_gem_executable
build:
  gem:
    name: my_gem
  bundler: true
output:
  name: gem_source_bundler_package
  1. Scenario 5: Rails project
ruby:
  version: 3.2.4
  entry_point: rails_app.rb
build:
  bundler: true
include:
  directories:
    - app
    - config
    - db
    - lib
    - public
    - vendor
output:
  name: rails_project_package

These tebako.yaml files are basic examples for each scenario. You may need to adjust them based on your specific project requirements, such as adding additional gems, specifying native extensions, or including specific files and directories.

@ronaldtse
Copy link
Contributor Author

Adding a "test" section to the tebako.yaml files is a great idea for ensuring the packaged executable undergoes some basic sanity checks. Here are the updated tebako.yaml files with a "test" section added for each scenario:

  1. Scenario 1: Simple ruby script
ruby:
  version: 3.2.4
  entry_point: my_script.rb
output:
  name: simple_script_package
test:
  commands:
    - ./simple_script_package --version
    - ./simple_script_package --help
  expected_output:
    - "Version 1.0.0"
    - "Usage: simple_script_package [options]"
  1. Scenario 2: Packaged gem
ruby:
  version: 3.2.4
  entry_point: my_gem_executable
gems:
  - name: my_packaged_gem.gem
    path: ./
output:
  name: packaged_gem_package
test:
  commands:
    - ./packaged_gem_package --version
    - echo "Hello, World!" | ./packaged_gem_package
  expected_output:
    - "my_packaged_gem version 1.0.0"
    - "Processed input: Hello, World!"
  1. Scenario 3: Gem source, no bundler
ruby:
  version: 3.2.4
  entry_point: my_gem_executable
build:
  gem:
    name: my_gem
output:
  name: gem_source_package
test:
  commands:
    - ./gem_source_package -h
    - ./gem_source_package perform_action
  expected_output:
    - "Usage: gem_source_package [options]"
    - "Action performed successfully"
  1. Scenario 4: Gem source, bundler
ruby:
  version: 3.2.4
  entry_point: my_gem_executable
build:
  gem:
    name: my_gem
  bundler: true
output:
  name: gem_source_bundler_package
test:
  commands:
    - ./gem_source_bundler_package --version
    - ./gem_source_bundler_package list_dependencies
  expected_output:
    - "my_gem version 1.0.0"
    - "Dependencies: nokogiri, httparty"
  1. Scenario 5: Rails project
ruby:
  version: 3.2.4
  entry_point: rails_app.rb
build:
  bundler: true
include:
  directories:
    - app
    - config
    - db
    - lib
    - public
    - vendor
output:
  name: rails_project_package
test:
  commands:
    - ./rails_project_package --version
    - ./rails_project_package about
  expected_output:
    - "Rails 7.0.4"
    - "Ruby version: 3.2.4"
    - "RubyGems version:"
    - "Rack version:"
    - "JavaScript Runtime: Node.js"

In these examples, the test section includes:

  1. commands: A list of commands to run on the packaged executable.
  2. expected_output: A list of expected outputs or patterns to match against the command outputs.

These test sections provide a way for users to quickly verify that the packaged executable is working as expected. The specific commands and expected outputs should be adjusted based on your application's functionality and requirements.

You could also add more sophisticated tests, such as:

  • Checking for specific exit codes
  • Testing with various input data
  • Verifying file operations
  • Checking database connections (for database-driven apps)

Remember to update these tests as your application evolves to ensure they remain relevant and useful for sanity checking the packaged executable.

@maxirmx
Copy link
Member

maxirmx commented Aug 4, 2024

Minimal tebafile is implemented at #179
It allows to specify options that are available on the command line

Improvements specified above cover not only tebafile but also require additional functionality that is not provided by tebako at this time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: 🔖 Ready
Development

No branches or pull requests

2 participants