hamster-web 0.1.0.pre.2 → 0.1.0.pre.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da9a6aefcced6e728e844a09b04ebaab4d6970b0742b9e527be34c36bcc52de1
4
- data.tar.gz: f063de9bfdd15a06f17992ed6efd23cb6e3ad50fbe99195ec2e82718e11b2aef
3
+ metadata.gz: ad523636ae12bea5f7c62d7ba64c1f9f343340c3c73952d086cb88ad003ebb33
4
+ data.tar.gz: 8b09067b4f17a7a5031f20b543e9ac8564b63319252c1cfb991da4bf4de0b321
5
5
  SHA512:
6
- metadata.gz: 1a06018d216e769b046d6ec6614ff110ab61fce962de8f35d38ee96a8cccbbf67fe73c5d1c6885e225e8f76b5757ef56b5a4b8f18f6f208fc7c2570a1e3b2a3c
7
- data.tar.gz: 47d17563010f3acb9f3b678dd9c2027e2ebedb38cc31b7d28c4abecab57fa994f696a8d72f8551006dc7c5d374ebb36f37431ac466e910e1b0b0cc28b66b8ae9
6
+ metadata.gz: a714e1f4112d612d6123ee30b7febcb5f5b7eac0138d7c8a01e6b969656654c32dac6e2995aa54bd692131d9e323da62480b3904082cd11512784d04409688ca
7
+ data.tar.gz: 7df33a2df961b34d348399c1d6a3e2051457811f3de7543c76eaa6c5c73099ed3bd6c37234d1bcd38ac4efafdcf28d3b65eb911116e59c43bbeae4b7f4db98f8
data/README.md CHANGED
@@ -9,11 +9,11 @@ actions, compiled views, and SQL migrations. Database creation and migration
9
9
  commands, the console, and schema-aware records/queries are available.
10
10
  Telemetry extraction and asset delivery remain under development.
11
11
 
12
- Build and install the local framework preview:
12
+ Install the public framework preview from RubyGems:
13
13
 
14
14
  ```sh
15
- gem build hamster-web.gemspec
16
- gem install --local hamster-web-0.1.0.pre.2.gem
15
+ gem install bundler --version 2.5.23
16
+ gem install hamster-web --version 0.1.0.pre.3
17
17
  hamster new MyApp
18
18
  cd my_app
19
19
  bin/hamster setup
@@ -28,7 +28,7 @@ bin/hamster build
28
28
  bin/hamster serve
29
29
  ```
30
30
 
31
- Run framework tests with `ruby -Ilib -e 'Dir["test/*_test.rb"].sort.each { |file| require_relative file }'`.
31
+ Run framework tests with `ruby -Ilib -e 'Dir["test/*_test.rb"].sort.each { |file| require File.expand_path(file) }'`.
32
32
 
33
33
  ## Records and queries
34
34
 
@@ -59,3 +59,103 @@ configured PostgreSQL database. It reports missing tables/columns, incompatible
59
59
  types, and unexpected nullability with a nonzero exit status. It never migrates
60
60
  or modifies the schema. Configuration is loaded through config/commands.rb,
61
61
  a CRuby-only adapter generated with new applications.
62
+
63
+ ## Installation contract and Linux verification
64
+
65
+ The clean-install gate targets Ruby 3.3.6, Bundler 2.5.23, Hamster
66
+ 0.1.0.pre.3, Spinner 0.1.0.pre.1, PostgreSQL 16.6, and unmodified Spinel/Spin
67
+ revision `10f112c51666e7ffd308e0ab90a69c2184870c06`. The exact CI inputs live
68
+ in `script/ci/versions.env`; Linux compatibility is verified by the native
69
+ smoke workflow. This pin does not include the experimental benchmark runtime.
70
+
71
+ The server gem is named `spinel-spinner`; Ruby application code uses
72
+ `require "spinner"` and the `Spinner` namespace. Hamster installs it as a
73
+ separate, exact-version dependency. The RubyGems package named `spinner` is
74
+ unrelated. Neither framework gem bundles a compiler or a precompiled server.
75
+
76
+ Spinel and its `spin` project tool must be installed before app setup. On
77
+ Debian Bookworm, install `build-essential`, `ca-certificates`, `curl`, `git`,
78
+ `pkg-config`, `libffi-dev`, and `libssl-dev`. PostgreSQL must be available;
79
+ `postgresql-client` provides the smoke test's `psql` checks. Build the pinned
80
+ upstream toolchain into a dedicated installation prefix:
81
+
82
+ ```sh
83
+ git clone https://github.com/matz/spinel.git
84
+ cd spinel
85
+ git checkout --detach 10f112c51666e7ffd308e0ab90a69c2184870c06
86
+ make deps
87
+ make -j2
88
+ make install PREFIX="$HOME/.local"
89
+ export PATH="$HOME/.local/bin:$PATH"
90
+ spinel --version
91
+ spin --version
92
+ ```
93
+
94
+ Then run the app generation commands above from an empty directory. Setup
95
+ fetches the PostgreSQL driver revision in the generated `spin.lock` from
96
+ `https://github.com/rubys/spinel-pg`. RubyGems and GitHub network access are
97
+ required. Configure `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`,
98
+ `DATABASE_USERNAME`, and `DATABASE_PASSWORD` for your PostgreSQL server.
99
+ `DATABASE_ADMIN_NAME` defaults to `postgres`; administrative credentials default
100
+ to the application credentials and need permission to create the database.
101
+ The generated README describes the defaults and build/serve commands.
102
+
103
+ To build a local framework preview instead of installing the public package:
104
+
105
+ ```sh
106
+ gem build hamster-web.gemspec
107
+ gem install --local hamster-web-0.1.0.pre.3.gem
108
+ ```
109
+
110
+ Run the clean Linux gate locally with Docker running (no local PostgreSQL or
111
+ Spinel installation needed):
112
+
113
+ ```sh
114
+ # Public packages, installed directly from RubyGems:
115
+ bash script/ci/run_native_smoke.sh published
116
+
117
+ # Candidate gem built from this checkout, plus published Spinner:
118
+ mkdir -p tmp
119
+ gem build hamster-web.gemspec --output tmp/hamster-web.gem
120
+ bash script/ci/run_native_smoke.sh candidate tmp/hamster-web.gem
121
+ ```
122
+
123
+ Each invocation builds an image without caches, installs the compiler from its
124
+ pinned upstream source, and tests in a separate consumer image containing no
125
+ Hamster/Spinner checkout. Only the CI harness and optional candidate gem enter
126
+ that environment. Gems, Bundler settings, and the generated app use fresh
127
+ isolated directories. Package resolution must stay within that gem installation.
128
+ The test creates a disposable database, applies a real migration twice, checks
129
+ its effects and tracking, compiles the app, and asserts HTTP 200 and welcome
130
+ content from the native executable. Containers, their processes, networks, and
131
+ the tagged test image are removed on exit. Docker retains image build layers;
132
+ no restored layers are used by the gate.
133
+
134
+ Logs, lockfiles, resolved package paths, and HTTP output are retained under
135
+ `tmp/native-smoke-<mode>/` (override with `SMOKE_ARTIFACTS_DIR`). GitHub Actions
136
+ uploads those diagnostics even on failure. Pull requests and main test the
137
+ candidate package; weekly and manually triggered runs also test published
138
+ packages. Public pins are advanced deliberately when releases are available.
139
+
140
+ ## Generated deployment images
141
+
142
+ New applications include a multi-stage `Dockerfile`, `.dockerignore`, and a
143
+ `GET /up` liveness endpoint. Build with `docker build -t my_app .`; no host Ruby,
144
+ Spinel, or database is needed. The default image runs the native executable as
145
+ UID 10001 on port 4000, with shared libraries, migrations and public assets only.
146
+ Ruby and the compiler are confined to build/operational stages.
147
+
148
+ Build `--target migrations` separately and run that image's `db:migrate`
149
+ command with database settings supplied at runtime before deploying the native
150
+ image. Migrations never run during image build or server startup. `/up` bypasses
151
+ database checkout after the application's initial database/migration verification,
152
+ so it reports process liveness rather than database readiness. The generated
153
+ README includes deployment commands, environment settings and shutdown semantics.
154
+
155
+ Run `bash script/ci/run_app_docker_smoke.sh` to verify the generated image using
156
+ Docker alone. It packages and installs the current framework inside a temporary
157
+ container, generates an app, builds before creating any database, checks secret
158
+ exclusions and runtime linkage, applies a real migration, verifies HTTP and Docker
159
+ health checks as a non-root user without Ruby/Spinel, stops PostgreSQL to test
160
+ liveness, and verifies clean SIGTERM shutdown. Diagnostics are retained in
161
+ `tmp/app-docker-smoke/`. This runs as a separate job in the native smoke workflow.
data/lib/hamster/cli.rb CHANGED
@@ -44,6 +44,13 @@ module Hamster
44
44
  end
45
45
  end
46
46
 
47
+ def self.require_tool!(executable, instruction)
48
+ paths = executable.include?(File::SEPARATOR) ? [executable] : ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).map { |directory| File.join(directory, executable) }
49
+ return if paths.any? { |path| File.file?(path) && File.executable?(path) }
50
+
51
+ raise "Required executable #{executable.inspect} was not found; #{instruction}"
52
+ end
53
+
47
54
  def self.dispatch(command)
48
55
  app_root = root
49
56
  metadata = JSON.parse(File.read(File.join(app_root, "config/hamster.json")))
@@ -63,10 +70,13 @@ module Hamster
63
70
  Console.run(ApplicationCommands.build)
64
71
  end
65
72
  when "setup"
73
+ require_tool!("bundle", "install Bundler with gem install bundler")
74
+ require_tool!("spin", "install the supported Spinel toolchain (including spin); see the Hamster README") if File.file?(File.join(app_root, "spin.toml"))
66
75
  Dir.chdir(app_root) { raise "Dependency installation failed" unless system("bundle", "install") }
67
76
  Dir.chdir(app_root) { raise "Spin dependency vendoring failed" unless system("spin", "vendor") } if File.file?(File.join(app_root, "spin.toml"))
68
77
  Build::PostgresCompatibility.apply(app_root) if File.file?(File.join(app_root, "spin.toml"))
69
78
  when "db:create", "db:migrate"
79
+ require_tool!("spin", "install the supported Spinel toolchain and run bin/hamster setup")
70
80
  output, status = Open3.capture2e("spin", "list", "--json", chdir: app_root)
71
81
  raise "Cannot resolve PostgreSQL dependency: #{output}" unless status.success?
72
82
  pg = JSON.parse(output).find { |package| package["name"] == "pg" }
@@ -95,6 +105,9 @@ module Hamster
95
105
  raise issues.join("\n") unless issues.empty?
96
106
  puts "Manifest check passed"
97
107
  when "build"
108
+ compiler = ENV.fetch("SPINEL", "spinel")
109
+ require_tool!(compiler, "install the supported Spinel toolchain or set SPINEL to its compiler path; see the Hamster README")
110
+ require_tool!("spin", "install the supported Spinel toolchain (including spin)") if File.file?(File.join(app_root, "spin.toml"))
98
111
  Build::PostgresCompatibility.apply(app_root) if File.file?(File.join(app_root, "spin.toml"))
99
112
  Build::Manifest.generate(app_root)
100
113
  issues = Build::Manifest.check(app_root)
@@ -109,7 +122,7 @@ module Hamster
109
122
  raise "Spin dependency resolution failed: #{diagnostic}" unless status.success?
110
123
  flags.concat(Shellwords.split(output))
111
124
  end
112
- raise "Spinel compilation failed" unless system(ENV.fetch("SPINEL", "spinel"), "bin/server", *flags, "-o", temporary)
125
+ raise "Spinel compilation failed" unless system(compiler, "bin/server", *flags, "-o", temporary)
113
126
  end
114
127
  File.rename(temporary, binary)
115
128
  ensure
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Hamster
4
4
  module Web
5
- VERSION = "0.1.0.pre.2"
5
+ VERSION = "0.1.0.pre.3"
6
6
  end
7
7
  end
@@ -0,0 +1,18 @@
1
+ .git
2
+ .bundle
3
+ vendor
4
+ node_modules
5
+ tmp
6
+ log
7
+ coverage
8
+ *.gem
9
+ bin/*-server
10
+ bin/*.tmp
11
+ **/.env
12
+ **/.env.*
13
+ **/*.key
14
+ **/*.pem
15
+ **/credentials.yml.enc
16
+ README.md
17
+ AGENTS.md
18
+ test
@@ -1,6 +1,6 @@
1
1
  # Application conventions
2
2
 
3
- - Keep one action per endpoint directory with a sibling view.html.erb.
3
+ - Keep one action per endpoint directory; HTML responses can use a sibling view.html.erb.
4
4
  - Declare routes in app/routes/mappings.rb.
5
5
  - App Ruby files load through config/manifest.rb; do not add local requires.
6
6
  - Run bin/hamster manifest after editing application Ruby files or templates.
@@ -0,0 +1,53 @@
1
+ # Build with Docker only; Spinel and Ruby are installed inside the builder.
2
+ ARG RUBY_IMAGE=ruby:3.3.6-bookworm@sha256:347edd0c70ee08d87de9f01b99de2f14a64cedb5d1bfb38457dfe8cd0bf113c5
3
+ ARG RUNTIME_IMAGE=debian:bookworm-slim@sha256:99c0b25c46d0214d5a2091092e7908907dcaecd6a962cde0ac700acee222b6f3
4
+ FROM ${RUBY_IMAGE} AS toolchain
5
+ ARG SPINEL_REVISION=10f112c51666e7ffd308e0ab90a69c2184870c06
6
+ RUN apt-get update && apt-get install -y --no-install-recommends \
7
+ build-essential ca-certificates curl git libffi-dev libssl-dev pkg-config \
8
+ && rm -rf /var/lib/apt/lists/*
9
+ RUN mkdir /src && cd /src && git init \
10
+ && git remote add origin https://github.com/matz/spinel.git \
11
+ && git fetch --depth 1 origin "$SPINEL_REVISION" && git checkout --detach FETCH_HEAD \
12
+ && test "$(git rev-parse HEAD)" = "$SPINEL_REVISION" \
13
+ && make deps && make -j2 && make install PREFIX=/opt/spinel \
14
+ && rm -rf /src
15
+ ENV PATH="/opt/spinel/bin:${PATH}"
16
+ RUN gem install bundler --version 2.5.23 --no-document \
17
+ && gem install hamster-web --version __HAMSTER_VERSION__ --no-document
18
+
19
+ FROM toolchain AS builder
20
+ WORKDIR /app
21
+ COPY . .
22
+ # Setup and compilation require no database connection or credentials.
23
+ RUN bin/hamster setup && bin/hamster manifest && bin/hamster manifest:check && bin/hamster build
24
+ RUN mkdir -p /runtime/app/bin /runtime/app/db/migrations /runtime/app/public \
25
+ && cp bin/__APP_NAME__-server /runtime/app/bin/ \
26
+ && cp -a db/migrations/. /runtime/app/db/migrations/ \
27
+ && cp -a public/. /runtime/app/public/ \
28
+ && ldd bin/__APP_NAME__-server > /runtime/ldd.txt \
29
+ && cat /runtime/ldd.txt && ! grep -F 'not found' /runtime/ldd.txt
30
+
31
+ # Optional operational image. Migrations run explicitly, never during build/boot.
32
+ FROM builder AS migrations
33
+ ENV HAMSTER_APP_ROOT=/app HAMSTER_ENV=production
34
+ ENTRYPOINT ["bin/hamster"]
35
+ CMD ["db:migrate"]
36
+
37
+ FROM ${RUNTIME_IMAGE} AS runtime
38
+ # Runtime libraries and a small HTTP health probe; no Ruby, gems or compiler.
39
+ RUN apt-get update && apt-get install -y --no-install-recommends \
40
+ ca-certificates curl libcrypt1 libffi8 libssl3 \
41
+ && rm -rf /var/lib/apt/lists/*
42
+ WORKDIR /app
43
+ COPY --from=builder /runtime/app/ /app/
44
+ # Check linkage in the actual runtime image as well as in the builder.
45
+ RUN ldd /app/bin/__APP_NAME__-server > /tmp/ldd.txt \
46
+ && cat /tmp/ldd.txt && ! grep -F 'not found' /tmp/ldd.txt && rm /tmp/ldd.txt
47
+ ENV HAMSTER_APP_ROOT=/app HAMSTER_ENV=production HOST=0.0.0.0 PORT=4000
48
+ USER 10001:10001
49
+ EXPOSE 4000
50
+ STOPSIGNAL SIGTERM
51
+ HEALTHCHECK --interval=10s --timeout=3s --start-period=15s --retries=3 \
52
+ CMD curl --fail --silent --show-error --max-time 2 "http://127.0.0.1:${PORT}/up" > /dev/null || exit 1
53
+ ENTRYPOINT ["/app/bin/__APP_NAME__-server"]
@@ -1,7 +1,13 @@
1
1
  # __APP_NAME__
2
2
 
3
3
  Run `bin/hamster setup` to install gems and vendor the locked Spin PostgreSQL driver.
4
- Spin and Spinel must already be installed. Configure DATABASE_USERNAME,
4
+ Spin and Spinel must already be installed. The preview installation contract is
5
+ Ruby 3.3.6, Bundler 2.5.23, Hamster __HAMSTER_VERSION__, spinel-spinner
6
+ 0.1.0.pre.1, and Spinel/Spin revision
7
+ `10f112c51666e7ffd308e0ab90a69c2184870c06`. See the framework README at
8
+ https://github.com/dostaglou/hamster-web for compiler installation prerequisites.
9
+ Spinner's gem name is `spinel-spinner`; application code uses `require "spinner"`.
10
+ Both gems are available from https://rubygems.org. Configure DATABASE_USERNAME,
5
11
  DATABASE_PASSWORD, and optionally DATABASE_HOST and DATABASE_PORT for your local
6
12
  PostgreSQL server. DATABASE_NAME defaults to __APP_NAME___development.
7
13
 
@@ -14,7 +20,7 @@ then `bin/hamster serve`. Build does not require a database connection.
14
20
  An empty migration directory is valid; db:migrate initializes migration tracking.
15
21
  The server listens on http://127.0.0.1:4000 by default; configure HOST and PORT
16
22
  to override it. During framework development, install the local hamster-web
17
- gem before running setup.
23
+ gem before running setup. Otherwise the pinned framework is installed from RubyGems.
18
24
 
19
25
  Run a deployed binary from the application root or set HAMSTER_APP_ROOT.
20
26
  Include db/migrations alongside the binary. PostgreSQL TLS is not supported
@@ -30,3 +36,60 @@ Each endpoint has an action.rb and optional view.html.erb in app/routes/.
30
36
  Declare endpoints centrally in app/routes/mappings.rb. Run
31
37
  `bin/hamster manifest` after changing Ruby sources or templates and commit
32
38
  the generated manifest and view registry with your source changes.
39
+
40
+ ## Docker deployment
41
+
42
+ The generated Dockerfile builds the Spinel compiler and `spin` at the pinned
43
+ revision, installs the framework from RubyGems, runs setup and manifest checks,
44
+ and compiles your application. Docker is the only build prerequisite on the
45
+ host. Commit `Gemfile.lock` and `spin.lock` to keep dependency resolution stable.
46
+ No database or database credentials are needed to build either target.
47
+
48
+ ```sh
49
+ docker build -t __APP_NAME__:latest .
50
+ docker build --target migrations -t __APP_NAME__:migrations .
51
+ ```
52
+
53
+ The default image uses Debian Bookworm slim and UID/GID 10001. It contains the
54
+ native executable, shared runtime libraries, SQL migrations and `public/`;
55
+ Ruby, gems, Spinel, application source and build tools stay in the builder.
56
+ Both builder and runtime verify the executable's shared library linkage with
57
+ `ldd`. Public files are retained for application-managed assets; the image does
58
+ not add an asset-serving route.
59
+
60
+ Provide database settings at container runtime, for example in an uncommitted
61
+ `.env.production` file. Set `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`,
62
+ `DATABASE_USERNAME`, and `DATABASE_PASSWORD`. The production database name
63
+ defaults to `__APP_NAME___production`. The database must already exist; use
64
+ `db:create` with separate administrative credentials only when provisioning it.
65
+ The Docker context excludes `.env` files, private keys, local gems, compiled
66
+ host binaries, and local Bundler settings. Keep credentials out of Ruby source
67
+ and Docker build arguments as well.
68
+
69
+ Apply migrations explicitly as a deployment step, then start the native image:
70
+
71
+ ```sh
72
+ docker run --rm --env-file .env.production __APP_NAME__:migrations
73
+ docker run -d --name __APP_NAME__ --env-file .env.production -p 4000:4000 __APP_NAME__:latest
74
+ ```
75
+
76
+ The `migrations` target includes Ruby and build dependencies for the existing
77
+ Hamster CLI; it is a separate operational image. Its default command is
78
+ `db:migrate`, and an explicit argument can select another command. Neither
79
+ image build nor native server startup applies migrations. Startup verifies the
80
+ configured database and rejects missing migration tracking or pending migrations.
81
+
82
+ The runtime sets `HAMSTER_APP_ROOT=/app`, `HAMSTER_ENV=production`,
83
+ `HOST=0.0.0.0` and `PORT=4000`. Override `PORT` and the port mapping together if
84
+ needed. The executable runs directly as PID 1 and receives SIGTERM. Allow its
85
+ graceful shutdown time when stopping it, for example `docker stop -t 20 __APP_NAME__`.
86
+ Only temporary storage needs to be writable; the CI smoke test runs with a
87
+ read-only root filesystem and a writable `/tmp`.
88
+
89
+ `GET /up` returns HTTP 200 with `OK` after successful startup. This is liveness:
90
+ it checks HTTP dispatch without checking out a database connection. A later
91
+ database outage does not make `/up` fail. It is not a readiness check or a
92
+ promise that application requests can reach PostgreSQL. The route is declared
93
+ in `app/routes/mappings.rb`, and `app/application.rb` bypasses the normal
94
+ database checkout for that path. The Docker health check calls `/up` using the
95
+ configured `PORT`.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module __APP_MODULE__
3
+ class Application < Hamster::Application
4
+ def initialize(routes:, database:)
5
+ super(routes: routes, database: database)
6
+ @liveness_router = Hamster::Router.new(routes)
7
+ end
8
+
9
+ def call(env)
10
+ # Liveness checks process/HTTP dispatch only, even during a DB outage.
11
+ return @liveness_router.call(env) if env.fetch("PATH_INFO", "/") == "/up"
12
+ super
13
+ end
14
+ end
15
+ end
@@ -3,6 +3,7 @@ module __APP_MODULE__
3
3
  module Routes
4
4
  class Mappings < Hamster::Routing::Base
5
5
  get "/", to: Home::Index::Action, as: :root
6
+ get "/up", to: Up::Index::Action, as: :up
6
7
  end
7
8
  end
8
9
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module __APP_MODULE__
3
+ module Routes
4
+ module Up
5
+ module Index
6
+ class Action < Hamster::Action::Base
7
+ def call
8
+ respond(body: "OK\n", headers: {"content-type" => "text/plain; charset=utf-8"})
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -9,7 +9,7 @@ module __APP_MODULE__
9
9
  database = Hamster::Database.new(database_configuration, migrations_path: File.join(root, "db/migrations"))
10
10
  begin
11
11
  database.verify!
12
- Hamster::Application.new(routes: Routes::Mappings, database: database)
12
+ Application.new(routes: Routes::Mappings, database: database)
13
13
  rescue StandardError
14
14
  database.shutdown
15
15
  raise
File without changes
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hamster-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.2
4
+ version: 0.1.0.pre.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dillon Wyatt
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-10-29 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: spinel-spinner
@@ -93,13 +94,17 @@ files:
93
94
  - lib/hamster/web/version.rb
94
95
  - lib/hamster/web/view.rb
95
96
  - lib/hamster/web/view/form.rb
97
+ - templates/app/.dockerignore
96
98
  - templates/app/.gitignore
97
99
  - templates/app/AGENTS.md
100
+ - templates/app/Dockerfile
98
101
  - templates/app/Gemfile
99
102
  - templates/app/README.md
103
+ - templates/app/app/application.rb
100
104
  - templates/app/app/routes/home/index/action.rb
101
105
  - templates/app/app/routes/home/index/view.html.erb
102
106
  - templates/app/app/routes/mappings.rb
107
+ - templates/app/app/routes/up/index/action.rb
103
108
  - templates/app/app/views/layouts/application.html.erb
104
109
  - templates/app/bin/hamster
105
110
  - templates/app/bin/server
@@ -108,11 +113,14 @@ files:
108
113
  - templates/app/config/database.rb
109
114
  - templates/app/config/hamster.json
110
115
  - templates/app/db/migrations/.keep
116
+ - templates/app/public/.keep
111
117
  - templates/app/spin.lock
112
118
  - templates/app/spin.toml
119
+ homepage:
113
120
  licenses:
114
121
  - MIT
115
122
  metadata: {}
123
+ post_install_message:
116
124
  rdoc_options: []
117
125
  require_paths:
118
126
  - lib
@@ -127,7 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
135
  - !ruby/object:Gem::Version
128
136
  version: '0'
129
137
  requirements: []
130
- rubygems_version: 4.0.23
138
+ rubygems_version: 3.5.16
139
+ signing_key:
131
140
  specification_version: 4
132
141
  summary: A Spinel web framework and application generator
133
142
  test_files: []