docker-swarm 0.10.0 → 0.11.0
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 +4 -4
- data/CHANGELOG.md +14 -0
- data/docs/consumed/docker-engine-api.md +11 -0
- data/docs/interface/interface.md +3 -3
- data/docs/test/testing.md +1 -1
- data/docs/topology/topology.md +5 -5
- data/lib/docker_swarm/models/container.rb +15 -0
- data/lib/docker_swarm/models/image.rb +13 -0
- data/lib/docker_swarm/version.rb +1 -1
- data/skill/SKILL.md +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4b67b8f60093fc00f4305221d2f4619ebda26d59979db28cffa12947b1aa2b51
|
|
4
|
+
data.tar.gz: 6a220462c6f427c9ed883651d92c7e54f7eb058925d4eb1e3b6f61764c9db545
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a9189e2987390ed20f32ca0288d18ee96df35b637f0b675ef8d5ff0e9bddbe5743b8145afbc57dedf1e921e45a5f7031c4b9cd4c91992dfb1120a637aef9ad9
|
|
7
|
+
data.tar.gz: aa102d0979a97aed02dab90a0dacf03c89a81001750072957e9ec2ac5a6a8e12aa1ba9b4c08442c00a83af74bfb0291e7723e0b3123b4ae3cacee44fa58d4562
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.11.0] — 2026-08-07
|
|
8
|
+
|
|
9
|
+
### Correcciones
|
|
10
|
+
- **`Container.where(since:)` / `where(before:)` filtran de verdad, y `size` llega al Engine** (#35). Las dos claves son **filtros** de `GET /containers/json` según el spec v1.41 (`ContainerList`), no query params, pero el default de `Base.index_query_params` las ruteaba a la URL: el Engine **las ignoraba y devolvía la lista sin filtrar, sin ningún error** — resultado incorrecto silencioso. Y `size` (query param propio, pide el tamaño de los archivos del container) viajaba dentro de `?filters=` como filtro inválido. `Container` ahora declara `%i[all limit size]` — @Pslp
|
|
11
|
+
- **Mismo bug en `Image`**, con la misma evidencia: `/images/json` declara `all` y `digests` como query params propios y lista `before`/`since` entre sus filtros. `Image` ahora declara `%i[all digests]`.
|
|
12
|
+
- **Cambio de comportamiento observable:** `Container.where(since: id)` antes devolvía **todos** los containers y ahora filtra. Si algún consumidor compensaba filtrando en Ruby, el resultado no cambia; si dependía de recibir la lista completa, cambia.
|
|
13
|
+
- `Base` **no** se toca: su default (`%i[all force limit since before]`) no matchea el listado de ningún recurso, pero limpiarlo convertiría no-ops silenciosos en filtros inválidos hacia el Engine para los 7 modelos que hoy no declaran lista propia. Queda como decisión aparte.
|
|
14
|
+
|
|
15
|
+
### Mejoras internas
|
|
16
|
+
- Bump `activesupport` y `activemodel` 8.1.3 → 8.1.3.1 (#25) — @dependabot. Las release notes de 8.1.3.1 declaran "No changes" para Active Support y Active Model: es el patch de la familia Rails, sin cambios propios en las dos gemas que la gema usa.
|
|
17
|
+
- Bump `excon` 1.5.0 → 1.6.0 (#20) — @dependabot. Verificado con la suite completa (203 ejemplos, incluida la integración contra un swarm real), no solo con el subconjunto de CI.
|
|
18
|
+
- Bump `actions/checkout` 6 → 7 en `main.yml` y `release.yml` (#14) — @dependabot.
|
|
19
|
+
- `docs/topology/topology.md`: versiones resueltas de las tres dependencias runtime al día.
|
|
20
|
+
|
|
7
21
|
## [0.10.0] — 2026-08-05
|
|
8
22
|
|
|
9
23
|
### Nuevas funcionalidades
|
|
@@ -65,6 +65,17 @@ Serialización: request body no-String → JSON (`Content-Type: application/json
|
|
|
65
65
|
|
|
66
66
|
Los nombres **no** son globales — el mismo `status` es query param propio en `/services` y filtro válido en `/containers/json` (`running`, `exited`, …). De ahí que la lista sea por modelo y no una whitelist única.
|
|
67
67
|
|
|
68
|
+
**Partición real por listado**, verificada contra el spec v1.41 (`ContainerList`, `ImageList`, `ServiceList`, …). El resto de los recursos (`/networks`, `/volumes`, `/nodes`, `/tasks`, `/secrets`, `/configs`) declara **solo** `filters`:
|
|
69
|
+
|
|
70
|
+
| listado | query params propios | dónde caen `since`/`before` |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `GET containers/json` | `all`, `limit`, `size` | **filtros** del recurso |
|
|
73
|
+
| `GET images/json` | `all`, `digests` | **filtros** del recurso |
|
|
74
|
+
| `GET services` | `status` | no existen |
|
|
75
|
+
| `GET networks` · `volumes` · `nodes` · `tasks` · `secrets` · `configs` | — (solo `filters`) | no existen |
|
|
76
|
+
|
|
77
|
+
Consecuencia para el default de `Base` (`%i[all force limit since before]`): **no matchea el listado de ningún recurso**. `since`/`before` son filtros donde existen, `force` no es query param de ningún listado (es de `DELETE`/prune) y `limit` solo aplica a containers. Un modelo que no declare su lista propia rutea `since`/`before` a la URL, donde el Engine **los ignora y devuelve la lista sin filtrar, sin error** — resultado incorrecto silencioso. `Container` e `Image` declaran la suya por eso (#35); los que solo aceptan `filters` no se ven afectados en la práctica, porque esas claves tampoco son filtros válidos ahí.
|
|
78
|
+
|
|
68
79
|
**`?status=true` en `/services`** (API ≥ v1.41) agrega a cada elemento:
|
|
69
80
|
|
|
70
81
|
```json
|
data/docs/interface/interface.md
CHANGED
|
@@ -48,7 +48,7 @@ Inventario completo de opciones: [`docs/config/configuracion.md`](../config/conf
|
|
|
48
48
|
| `.all(filters = {})` | método de clase | `GET index`; mapea a instancias; aplica `root_key`; `[]` si vacío |
|
|
49
49
|
| `.find(id)` | método de clase | `GET show`; `nil` si `Errors::NotFound` |
|
|
50
50
|
| `.where(filters)` | método de clase | alias de `all` |
|
|
51
|
-
| `.index_query_params` | método de clase | `%i[all force limit since before]` por default; override por modelo (`+ :status`
|
|
51
|
+
| `.index_query_params` | método de clase | `%i[all force limit since before]` por default; **override por modelo**: `Service` (`+ :status`), `Container` (`%i[all limit size]`), `Image` (`%i[all digests]`). Claves que viajan como **query params propios** del listado; **todo lo no declarado se serializa dentro del JSON de `?filters=`** — si tampoco es filtro válido del recurso, el Engine lo rechaza o lo ignora. El default de `Base` no matchea el listado de ningún recurso concreto: `since`/`before`/`force` no son query params de ningún listado del spec v1.41 (ver #35) |
|
|
52
52
|
| `#initialize(attributes = {})` | método de instancia | `assign_attributes` si presente |
|
|
53
53
|
| `#assign_attributes(new_attributes)` | método de instancia | normaliza `Id`→`ID`; `deep_merge` del campo `Spec`; `ArgumentError` si no es Hash |
|
|
54
54
|
| `#attributes` | método de instancia | `instance_values` sin internos de ActiveModel |
|
|
@@ -80,8 +80,8 @@ Inventario completo de opciones: [`docs/config/configuracion.md`](../config/conf
|
|
|
80
80
|
| `DockerSwarm::Service` | clase < Base | Creatable, Updatable, Deletable, Loggable; `#restart` (incrementa `TaskTemplate.ForceUpdate`); `create`/`update` aceptan `registry_auth:` (+ `update`: `registry_auth_from:`) para auth de registry privado; `.index_query_params` agrega `:status` → `where(status: true)` puebla `ServiceStatus` (`RunningTasks`/`DesiredTasks`/`CompletedTasks`), único lugar donde el Engine publica el deseado de un service `global` |
|
|
81
81
|
| `DockerSwarm::Node` | clase < Base | Updatable, Deletable (sin `create`: los nodos se unen fuera de la gema) |
|
|
82
82
|
| `DockerSwarm::Task` | clase < Base | Loggable (read-only; generadas por el orquestador) |
|
|
83
|
-
| `DockerSwarm::Container` | clase < Base | Creatable, Deletable, Loggable; `#start`, `#stop`; `.create_query_params == %w[name]` (el Engine toma el nombre por query string — en el body lo descarta en silencio y el container nace con nombre aleatorio). El `create` **no** es gap intencional desde ADR-025 cláusula 1 |
|
|
84
|
-
| `DockerSwarm::Image` | clase < Base | Deletable + `.pull(image_reference, registry_auth: nil)`. **NO** es Creatable (`Image.create` retirado sin alias). `.pull` = pull explícito síncrono: consume el stream NDJSON hasta EOF, eleva `DockerSwarm::Error` ante frame `error`/`errorDetail`, retorna `{ status: :pulled, image_ref:, digest? }` (sin `find` posterior) |
|
|
83
|
+
| `DockerSwarm::Container` | clase < Base | Creatable, Deletable, Loggable; `#start`, `#stop`; `.create_query_params == %w[name]` (el Engine toma el nombre por query string — en el body lo descarta en silencio y el container nace con nombre aleatorio). El `create` **no** es gap intencional desde ADR-025 cláusula 1; `.index_query_params == %i[all limit size]` — `since`/`before` son **filtros** de `/containers/json`, no query params (#35) |
|
|
84
|
+
| `DockerSwarm::Image` | clase < Base | Deletable + `.pull(image_reference, registry_auth: nil)`. **NO** es Creatable (`Image.create` retirado sin alias). `.pull` = pull explícito síncrono: consume el stream NDJSON hasta EOF, eleva `DockerSwarm::Error` ante frame `error`/`errorDetail`, retorna `{ status: :pulled, image_ref:, digest? }` (sin `find` posterior); `.index_query_params == %i[all digests]` — `since`/`before` son **filtros** de `/images/json`, no query params (#35) |
|
|
85
85
|
| `DockerSwarm::Network` | clase < Base | Creatable, Updatable, Deletable |
|
|
86
86
|
| `DockerSwarm::Volume` | clase < Base | Creatable, Deletable; `.root_key = "Volumes"` (respuesta wrapped) |
|
|
87
87
|
| `DockerSwarm::Config` | clase < Base | Creatable, Deletable (sin `update`: recrear) |
|
data/docs/test/testing.md
CHANGED
|
@@ -54,7 +54,7 @@ Ninguna. No hay `SimpleCov`/`.simplecov` ni umbral declarado en el repo (verific
|
|
|
54
54
|
- CRUD genérico de `config`, `secret`, `volume`: vía `shared_crud_spec` (`it_behaves_like "a crud resource"`) — no tienen spec dedicado pero **sí** están cubiertos (create/find/destroy). `image` salió del CRUD genérico (su `create` era un pull) → tiene spec propio (abajo).
|
|
55
55
|
- `image`: `image_spec` (dedicado) — `Image.pull` (stream NDJSON, extracción de digest del frame `Digest:`, error tipado ante `error`/`errorDetail`, forma polimórfica del body) + `Deletable` y listado.
|
|
56
56
|
- Auth de registry privado: `registry_auth_spec` (helper `RegistryAuth`: exclusión mutua `registry_auth`/`registry_auth_from`, enum del `from`, traducción a header/query) + bloque registry-auth en `service_spec` (create/update, no-exposición de la credencial en logs).
|
|
57
|
-
- Partición query params propios vs. `?filters=` del listado (`index_query_params`): `base_spec` (default, override, partición mixta), `service_spec` (`status: true` → query param; `ServiceStatus` expuesto y tolerancia a su ausencia), `container_spec` (**regresión**: `status` sigue viajando como filtro). Integration: `services_spec` verifica contra el daemon que `ServiceStatus` aparece **solo** con `status: true`, y un `context` en modo **`global`** pinnea el caso que justifica la feature — `DesiredTasks` legible donde `Spec.Mode.Replicated` no existe. Ese context es el que vuelve necesario el poll del helper `listed_with_status`: en un global el deseado arranca en 0 y el Engine lo completa después (~1s), así que la condición de corte es `DesiredTasks.positive?`, no `ServiceStatus.present?`.
|
|
57
|
+
- Partición query params propios vs. `?filters=` del listado (`index_query_params`): `base_spec` (default, override, partición mixta), `service_spec` (`status: true` → query param; `ServiceStatus` expuesto y tolerancia a su ausencia), `container_spec` (**regresión**: `status` sigue viajando como filtro; y #35: los tres query params de `ContainerList`, `since` ruteado a filtros, `size` a la URL, `force` ausente), `image_spec` (#35: `%i[all digests]`, `since` a filtros, `digests` a la URL). Integration: `services_spec` verifica contra el daemon que `ServiceStatus` aparece **solo** con `status: true`, y un `context` en modo **`global`** pinnea el caso que justifica la feature — `DesiredTasks` legible donde `Spec.Mode.Replicated` no existe. Ese context es el que vuelve necesario el poll del helper `listed_with_status`: en un global el deseado arranca en 0 y el Engine lo completa después (~1s), así que la condición de corte es `DesiredTasks.positive?`, no `ServiceStatus.present?`.
|
|
58
58
|
- Infra de transporte: `api_spec`, `connection_spec`, `configuration_spec`, `log_helper_spec`, los 4 middleware specs.
|
|
59
59
|
- `swarm`, `system` (singletons): `swarm_spec`, `system_spec`.
|
|
60
60
|
|
data/docs/topology/topology.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Topología — docker-swarm
|
|
2
2
|
|
|
3
|
-
> meta: artefacto · RFC-006 · generado arch-structure · anclado a `
|
|
3
|
+
> meta: artefacto · RFC-006 · generado arch-structure · anclado a `d731a8a` · cobertura: dependencias runtime (`.gemspec` + `Gemfile.lock`) y mapa de contexto de la gema
|
|
4
4
|
|
|
5
5
|
## 1. Resumen
|
|
6
6
|
|
|
@@ -14,9 +14,9 @@ Runtime declaradas en `docker-swarm.gemspec`; versiones resueltas en `Gemfile.lo
|
|
|
14
14
|
|
|
15
15
|
| nombre | versión (constraint) | resuelta | rol |
|
|
16
16
|
|---|---|---|---|
|
|
17
|
-
| `activesupport` | `>= 6.0` | 8.1.3 | core-ext (`HashWithIndifferentAccess`, `deep_merge`, `blank?`, `demodulize`, `pluralize`) |
|
|
18
|
-
| `activemodel` | `>= 6.0` | 8.1.3 | `ActiveModel::Model` (validaciones, API de atributos) en `Base` |
|
|
19
|
-
| `excon` | `>= 0.80` | 1.
|
|
17
|
+
| `activesupport` | `>= 6.0` | 8.1.3.1 | core-ext (`HashWithIndifferentAccess`, `deep_merge`, `blank?`, `demodulize`, `pluralize`) |
|
|
18
|
+
| `activemodel` | `>= 6.0` | 8.1.3.1 | `ActiveModel::Model` (validaciones, API de atributos) en `Base` |
|
|
19
|
+
| `excon` | `>= 0.80` | 1.6.0 | cliente HTTP con soporte nativo de Unix socket + stack de middlewares |
|
|
20
20
|
|
|
21
21
|
Desarrollo / test (no se empaquetan): `rake ~> 13.0`, `rspec ~> 3.0`, `pry`, `rubocop-rails-omakase`.
|
|
22
22
|
|
|
@@ -45,7 +45,7 @@ No aplica: es una librería embebida en el proceso del consumidor (sin web/worke
|
|
|
45
45
|
|
|
46
46
|
| afirmación | confidence | a verificar |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| `activesupport`/`activemodel` 8.1.3 son las resueltas hoy, pero el constraint `>= 6.0` admite Rails 6/7/8 | declared | `Gemfile.lock` fija 8.1.3; el `.gemspec` no pone techo |
|
|
48
|
+
| `activesupport`/`activemodel` 8.1.3.1 son las resueltas hoy, pero el constraint `>= 6.0` admite Rails 6/7/8 | declared | `Gemfile.lock` fija 8.1.3.1; el `.gemspec` no pone techo |
|
|
49
49
|
| La gema no abre puertos ni corre procesos propios | declared | sin `config/`, sin `bin/` server, sin Railtie/Engine |
|
|
50
50
|
|
|
51
51
|
## 4. Cobertura y fronteras
|
|
@@ -17,6 +17,21 @@ module DockerSwarm
|
|
|
17
17
|
%w[name].freeze
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# `GET /containers/json` declara exactamente tres query params propios además de
|
|
21
|
+
# `filters`: `all`, `limit` y `size` (spec v1.41, `ContainerList`).
|
|
22
|
+
#
|
|
23
|
+
# No hereda el default de {DockerSwarm::Base} porque **`since` y `before` son
|
|
24
|
+
# filtros** de este recurso, no query params: ruteados a la URL el Engine los ignora
|
|
25
|
+
# y devuelve **la lista sin filtrar, sin error** — resultado incorrecto silencioso,
|
|
26
|
+
# peor que el rechazo ruidoso de #22. Y `size` faltaba: es query param propio (pide
|
|
27
|
+
# el tamaño de los archivos del container), así que viajaba dentro de `filters` como
|
|
28
|
+
# filtro inválido. Ver #35.
|
|
29
|
+
#
|
|
30
|
+
# @return [Array<Symbol>] Symbols (matchean contra las claves de `filters`)
|
|
31
|
+
def self.index_query_params
|
|
32
|
+
%i[all limit size].freeze
|
|
33
|
+
end
|
|
34
|
+
|
|
20
35
|
# Starts the container
|
|
21
36
|
# @return [Boolean] true if successful
|
|
22
37
|
def start
|
|
@@ -15,6 +15,19 @@ module DockerSwarm
|
|
|
15
15
|
DIGEST_STATUS = /\bDigest:\s*(sha256:[0-9a-f]+)/
|
|
16
16
|
|
|
17
17
|
class << self
|
|
18
|
+
# `GET /images/json` declara dos query params propios además de `filters`: `all` y
|
|
19
|
+
# `digests` (spec v1.41, `ImageList`).
|
|
20
|
+
#
|
|
21
|
+
# Mismo caso que {DockerSwarm::Container}: **`since` y `before` son filtros** de
|
|
22
|
+
# este recurso (`<image-name>[:<tag>]`, `<image id>` o `<image@digest>`), así que
|
|
23
|
+
# el default de {DockerSwarm::Base} los mandaba a la URL, donde el Engine los ignora
|
|
24
|
+
# y devuelve la lista sin filtrar **sin error**. Ver #35.
|
|
25
|
+
#
|
|
26
|
+
# @return [Array<Symbol>] Symbols (matchean contra las claves de `filters`)
|
|
27
|
+
def index_query_params
|
|
28
|
+
%i[all digests].freeze
|
|
29
|
+
end
|
|
30
|
+
|
|
18
31
|
# Pull explícito de una imagen (POST /images/create).
|
|
19
32
|
#
|
|
20
33
|
# Operación SÍNCRONA: consume el stream NDJSON de progreso hasta EOF, eleva
|
data/lib/docker_swarm/version.rb
CHANGED
data/skill/SKILL.md
CHANGED
|
@@ -139,7 +139,7 @@ Todas heredan de `DockerSwarm::Error`. Tres formas de acceso equivalentes: `Dock
|
|
|
139
139
|
- **`Spec` se mergea con `deep_merge` en updates**, no se reemplaza. Pasale sólo los campos que cambian: `service.update(Mode: {...})`, no `service.update(Spec: {...completo})`.
|
|
140
140
|
- **`assign_attributes` muta antes de validar.** Si `update` falla por `valid?` o por el API, la instancia local quedó mutada. Hacé `reload` si necesitás estado limpio.
|
|
141
141
|
- **`Container.create` manda el nombre por query string.** Docker **descarta en silencio** un `name:` en el body y responde `201`: el container nace con nombre aleatorio y un reintento duplica en vez de adoptar. La gema lo resuelve sola vía `Container.create_query_params == %w[name]` — pero si armás el request por afuera (`DockerSwarm.request`), el `?name=` es tuyo. Ver ADR-025 cláusula 1 y §3.11 de `docs/behavior/behavior.md`.
|
|
142
|
-
- **`where` parte las claves en dos: query params propios vs. `?filters=`.** Solo lo declarado en `
|
|
142
|
+
- **`where` parte las claves en dos: query params propios vs. `?filters=`.** Solo lo declarado en `index_query_params` viaja en la URL; **todo lo demás se serializa como filtro de Docker**. La lista es **por modelo**: `Container` → `%i[all limit size]`, `Image` → `%i[all digests]`, `Service` → default `+ :status`. Si le pasás un query param propio que el modelo no declara, no llega: va dentro de `filters` y el Engine lo rechaza o lo ignora — sin error que indique que iba en la URL. Los nombres no son globales: `status` es query param en `/services` y **filtro válido** en `/containers/json`. ⚠️ **El default de `Base` (`%i[all force limit since before]`) no matchea ningún listado real** — `since`/`before` son *filtros* donde existen y `force` no es query param de ningún listado; un modelo sin lista propia los rutea a la URL y el Engine **devuelve la lista sin filtrar, sin error** (#35).
|
|
143
143
|
- **`ServiceStatus` solo aparece con `Service.where(status: true)`**, y es el **único** lugar donde el Engine publica el deseado de un service en modo `global` (un replicado lo tiene en `Spec.Mode.Replicated.Replicas`; un global no tiene ese campo). Sin `DesiredTasks` un global corriendo en 2 de 3 nodos elegibles es indistinguible de uno sano. Requiere API ≥ v1.41 y **degrada en silencio**: la gema no fija `?version=`, así que en un Engine anterior el parámetro se ignora y `ServiceStatus` llega `nil` — no hay señal de "no soportado", el consumidor tiene que tolerarlo. Y **`DesiredTasks: 0` no es "sin nodos elegibles"**: en un `global` recién creado el Engine publica los tres contadores en 0 y calcula el deseado después (~1s, medido), así que hay una ventana donde `RunningTasks == DesiredTasks == 0` y comparar los dos números miente — tratá `DesiredTasks.positive?` como precondición para decidir salud. Ver §3.12 de `docs/behavior/behavior.md`.
|
|
144
144
|
- **`logs` devuelve texto ya demultiplexado.** Sin TTY el Engine enmarca cada fragmento con 8 bytes de cabecera; `Middleware::LogStreamDemuxer` los saca en `Container`, `Service` y `Task`. Dos consecuencias: **`stdout` y `stderr` vienen intercalados** en un solo String (si necesitás un dato puntual, delimitalo en origen desde el `Cmd`), y **un frame partido entre chunks no se reensambla** — el demux es todo-o-nada, así que ante cualquier inconsistencia te devuelve el body intacto en vez de texto a medias. Con `follow: 1` el body no llega completo, así que no esperes demux ahí.
|
|
145
145
|
- **`Image.create` retirado (breaking).** Ya no existe (`Image` dejó de ser Creatable; el `create` estaba roto y sin consumidores). Usá `Image.pull(image_reference, registry_auth:)`.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docker-swarm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gabriel
|
|
@@ -136,9 +136,9 @@ licenses:
|
|
|
136
136
|
metadata:
|
|
137
137
|
homepage_uri: https://github.com/sequre/docker-swarm
|
|
138
138
|
source_code_uri: https://github.com/sequre/docker-swarm
|
|
139
|
-
changelog_uri: https://github.com/sequre/docker-swarm/blob/v0.
|
|
139
|
+
changelog_uri: https://github.com/sequre/docker-swarm/blob/v0.11.0/CHANGELOG.md
|
|
140
140
|
bug_tracker_uri: https://github.com/sequre/docker-swarm/issues
|
|
141
|
-
documentation_uri: https://github.com/sequre/docker-swarm/blob/v0.
|
|
141
|
+
documentation_uri: https://github.com/sequre/docker-swarm/blob/v0.11.0/skill/SKILL.md
|
|
142
142
|
rubygems_mfa_required: 'true'
|
|
143
143
|
rdoc_options: []
|
|
144
144
|
require_paths:
|