rubybikes 0.3.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 +7 -0
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +33 -0
- data/LICENSE +662 -0
- data/NOTICE +10 -0
- data/PROVIDERS.md +123 -0
- data/README.md +108 -0
- data/RELEASING.md +44 -0
- data/data/ATTRIBUTION.txt +290 -0
- data/data/geojson/ch_cantons.json +53 -0
- data/data/geojson/japan_prefectures.json +49 -0
- data/data/geojson/penang.json +63 -0
- data/data/graphql/charichari.graphql +12 -0
- data/data/graphql/ganxeta.graphql +22 -0
- data/data/graphql/otp.graphql +68 -0
- data/data/providers.json +1 -0
- data/data/pybikes/aksu.json +49 -0
- data/data/pybikes/ambici.json +166 -0
- data/data/pybikes/baksi.json +41 -0
- data/data/pybikes/batumvelo.json +19 -0
- data/data/pybikes/bcycle.json +326 -0
- data/data/pybikes/beryl.json +195 -0
- data/data/pybikes/bicicard.json +205 -0
- data/data/pybikes/bicicas.json +20 -0
- data/data/pybikes/bicielx.json +19 -0
- data/data/pybikes/biciferrolterra.json +21 -0
- data/data/pybikes/bicimad.json +16 -0
- data/data/pybikes/bicincitta.json +1551 -0
- data/data/pybikes/bicing.json +37 -0
- data/data/pybikes/bikeshare_ie.json +46 -0
- data/data/pybikes/bikeu.json +17 -0
- data/data/pybikes/bixi.json +21 -0
- data/data/pybikes/bizkaibizi.json +105 -0
- data/data/pybikes/careem.json +40 -0
- data/data/pybikes/charichari.json +106 -0
- data/data/pybikes/chartered_bike.json +86 -0
- data/data/pybikes/clujbike.json +17 -0
- data/data/pybikes/cyclocity.json +211 -0
- data/data/pybikes/cyclopolis.json +78 -0
- data/data/pybikes/cykleo.json +39 -0
- data/data/pybikes/decobike.json +18 -0
- data/data/pybikes/derp.json +114 -0
- data/data/pybikes/deutschebahn.json +97 -0
- data/data/pybikes/digitransit.json +123 -0
- data/data/pybikes/docomo.json +215 -0
- data/data/pybikes/easybike.json +160 -0
- data/data/pybikes/ecovelo.json +307 -0
- data/data/pybikes/emovity.json +17 -0
- data/data/pybikes/encicla.json +17 -0
- data/data/pybikes/fifteen.json +50 -0
- data/data/pybikes/fsm.json +16 -0
- data/data/pybikes/ganxeta.json +20 -0
- data/data/pybikes/gbfs.json +1578 -0
- data/data/pybikes/gira.json +20 -0
- data/data/pybikes/gyorbike.json +19 -0
- data/data/pybikes/hellocycling.json +248 -0
- data/data/pybikes/joco.json +22 -0
- data/data/pybikes/keolis.json +22 -0
- data/data/pybikes/kolumbus.json +18 -0
- data/data/pybikes/lastenvelo.json +30 -0
- data/data/pybikes/linkbike.json +17 -0
- data/data/pybikes/meiob.json +18 -0
- data/data/pybikes/mobhis.json +43 -0
- data/data/pybikes/movus.json +72 -0
- data/data/pybikes/nextbike.json +2443 -0
- data/data/pybikes/nextbike_gbfs.json +5 -0
- data/data/pybikes/nubija.json +18 -0
- data/data/pybikes/open_source_bike_share.json +28 -0
- data/data/pybikes/open_source_bike_share_v2.json +17 -0
- data/data/pybikes/openmove.json +20 -0
- data/data/pybikes/ov_fiets.json +20 -0
- data/data/pybikes/pedalada.json +66 -0
- data/data/pybikes/publibike.json +127 -0
- data/data/pybikes/qrobici.json +20 -0
- data/data/pybikes/roovee.json +245 -0
- data/data/pybikes/samba.json +52 -0
- data/data/pybikes/sejong.json +19 -0
- data/data/pybikes/seoulbike.json +18 -0
- data/data/pybikes/sharedmobility.json +63 -0
- data/data/pybikes/slovnaft_bajk.json +21 -0
- data/data/pybikes/smartbike.json +28 -0
- data/data/pybikes/smoove.json +26 -0
- data/data/pybikes/soltrafego.json +39 -0
- data/data/pybikes/tashu.json +20 -0
- data/data/pybikes/urbansharing.json +22 -0
- data/data/pybikes/velib.json +23 -0
- data/data/pybikes/velobike_kz.json +17 -0
- data/data/pybikes/velok.json +16 -0
- data/data/pybikes/veloway.json +20 -0
- data/data/pybikes/weelo.json +45 -0
- data/data/pybikes/wegoshare.json +141 -0
- data/data/pybikes/xian.json +19 -0
- data/data/pybikes/yelovelo.json +22 -0
- data/data/pybikes/youbike.json +173 -0
- data/data/upstream.json +7 -0
- data/lib/rubybikes/engine.rb +3 -0
- data/lib/rubybikes/native/authenticated.rb +95 -0
- data/lib/rubybikes/native/engine.rb +103 -0
- data/lib/rubybikes/native/gbfs.rb +169 -0
- data/lib/rubybikes/native/geometry.rb +53 -0
- data/lib/rubybikes/native/graphql.rb +135 -0
- data/lib/rubybikes/native/html_clients.rb +313 -0
- data/lib/rubybikes/native/json_providers.rb +174 -0
- data/lib/rubybikes/native/more_json.rb +126 -0
- data/lib/rubybikes/native/nextbike.rb +50 -0
- data/lib/rubybikes/native/provider.rb +84 -0
- data/lib/rubybikes/native/remaining_clients.rb +102 -0
- data/lib/rubybikes/native/response_cache.rb +78 -0
- data/lib/rubybikes/native/transport.rb +163 -0
- data/lib/rubybikes/native/xml_details.rb +159 -0
- data/lib/rubybikes/native.rb +30 -0
- data/lib/rubybikes/version.rb +5 -0
- data/lib/rubybikes.rb +201 -0
- data/sig/external.rbs +30 -0
- data/sig/manifest.yaml +8 -0
- data/sig/native.rbs +230 -0
- data/sig/rubybikes.rbs +143 -0
- metadata +230 -0
data/PROVIDERS.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Provider support and live status
|
|
2
|
+
|
|
3
|
+
Public checks recorded on **2026-11-04 and 2026-11-05 (UTC)**. RubyBikes implements the **85 concrete clients**
|
|
4
|
+
and preserves the **815 predefined networks** from PyBikes baseline
|
|
5
|
+
[`b8681d2344d2ccc61d7b99b089a8cdba167a169e`](https://github.com/eskerda/pybikes/commit/b8681d2344d2ccc61d7b99b089a8cdba167a169e).
|
|
6
|
+
The upstream snapshot and attribution are included in the gem's `data/` directory.
|
|
7
|
+
|
|
8
|
+
## What provider coverage means
|
|
9
|
+
|
|
10
|
+
Release checks require a successful, nonempty offline fixture update from every
|
|
11
|
+
client, as well as construction of all predefined networks. Fixtures exercise
|
|
12
|
+
real native Ruby parsers, expected station/vehicle fields, and HTTP request
|
|
13
|
+
shapes; external HTTP is disabled in these tests. CI also enforces 95% Ruby line
|
|
14
|
+
coverage and reports branch coverage.
|
|
15
|
+
|
|
16
|
+
This is different from live availability. An operator may retire an endpoint,
|
|
17
|
+
put a website into maintenance, require credentials, or reject requests from a
|
|
18
|
+
particular network. The catalog retains these networks and their implementations
|
|
19
|
+
rather than silently dropping them or returning fabricated availability.
|
|
20
|
+
|
|
21
|
+
Four supported clients have no predefined networks in the baseline:
|
|
22
|
+
`NextbikeGbfs`, `KeolisIlevia`, `VCub`, and `OTP`. Use `build` with the client's
|
|
23
|
+
constructor parameters to configure them. Authenticated clients have fixture
|
|
24
|
+
coverage; their live status remains **requires credentials** unless tested with
|
|
25
|
+
operator-issued access. Public audits do not send placeholder credentials.
|
|
26
|
+
|
|
27
|
+
Discover the packaged catalog without contacting operators:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
bundle exec ruby -Ilib -rrubybikes -e 'RubyBikes.open { |b| puts b.providers.map { |p| [p["module"], p["class"], p["tags"].size].join("\t") } }'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Verified public feed repairs
|
|
34
|
+
|
|
35
|
+
These changes preserve existing network tags and include offline regression
|
|
36
|
+
fixtures. Counts below are observations at the check time, not fixed expectations
|
|
37
|
+
for future operator responses.
|
|
38
|
+
|
|
39
|
+
| Network/client | Repair | Verified result |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `meiob` / Meiob | Parse padded decimal availability, including `08` and `09`, without Ruby's implicit octal interpretation. | 77 stations |
|
|
42
|
+
| `mibisivalencia` / Movus | Follow the official station page's map script to its JSON feed; accept spaced count labels and the accented `Actualizándose` state. Retain the older embedded marker format. | 30 stations |
|
|
43
|
+
| `bicisanvi` / Movus | Discover the current map script and its `/php/puntos.php` JSON endpoint using the same native implementation. | 14 stations |
|
|
44
|
+
| `publibike-aargau` / Publibike | Ignore null canton geometries before geographic filtering, matching the upstream behavior. Verified on 2026-11-05. | 68 stations |
|
|
45
|
+
| `publibike-bern` / Publibike | Apply the same null-geometry correction to both PubliBike and Velospot station formats. Verified on 2026-11-05. | 395 stations |
|
|
46
|
+
| `publibike-fribourg` / Publibike | Apply the same null-geometry correction. Verified on 2026-11-05. | 63 stations |
|
|
47
|
+
|
|
48
|
+
The native Samba implementation reads provider data with a restricted literal
|
|
49
|
+
parser. It accepts the published arrays, tuples, strings, and numeric values;
|
|
50
|
+
it does not evaluate scripts or execute provider-supplied expressions.
|
|
51
|
+
|
|
52
|
+
## Selected successful live checks
|
|
53
|
+
|
|
54
|
+
These public, bounded probes successfully parsed nonempty native snapshots on
|
|
55
|
+
2026-11-04. They are selected checks rather than a statement that every one of
|
|
56
|
+
the 815 catalog networks was available.
|
|
57
|
+
|
|
58
|
+
| Network | Client | Stations observed |
|
|
59
|
+
| --- | --- | ---: |
|
|
60
|
+
| `bicielx` | BiciElx | 114 |
|
|
61
|
+
| `bici-ferrol-terra` | BiciFerrolTerra | 18 |
|
|
62
|
+
| `girocleta` | Emovity | 36 |
|
|
63
|
+
| `passofundo` | Mobhis | 8 |
|
|
64
|
+
| `velobike` | VelobikeKZ | 152 |
|
|
65
|
+
| `bicicuenca` | Samba | 20 |
|
|
66
|
+
|
|
67
|
+
## Known live access issues
|
|
68
|
+
|
|
69
|
+
The following observations were made on 2026-11-04 unless stated otherwise. They
|
|
70
|
+
do not disable fixture-tested clients or remove their
|
|
71
|
+
catalog entries. A timeout or HTTP denial describes the checking environment;
|
|
72
|
+
it is not proof that a service is permanently retired.
|
|
73
|
+
|
|
74
|
+
| Network | Public endpoint checked | Dated observation |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| `gyorbike` | <https://www.gyorbike.hu/en/stations> | HTTP 200, but the operator serves “Karbantartás alatt / This page is under construction” with no station table or marker data. |
|
|
77
|
+
| `bikeu-bra` | <https://www.bra.org.pl/mapa-stacji.html> | Connection timed out at the five-second connection bound. No replacement feed was verified. |
|
|
78
|
+
| `bicicletar` | <https://www.bicicletar.com.br/mapaestacao.aspx> | HTTP 403. The baseline HTTP address and its HTTPS equivalent both rejected access. |
|
|
79
|
+
| `bikesantos` | <https://www.mobilicidade.com.br/bikesantos/mapaestacao.aspx> | HTTP 403 over HTTPS; no accessible replacement verified. |
|
|
80
|
+
| `bikevitoria` | <https://www.bikevitoria.com/mapaestacao.aspx> | HTTP 403; no accessible replacement verified. |
|
|
81
|
+
| Legacy EasyBike entries listed below | `http://reseller.easybike.gr/{city_uid}/api.php` | On 2026-11-05, HTTP 200 with `stations: null`: the endpoint publishes no station feed. No public replacement was verified. |
|
|
82
|
+
|
|
83
|
+
The affected legacy EasyBike entries are `athens-bikes`, `easybike-didymoteicho`,
|
|
84
|
+
`easybike-glyfada`, `easybike-igoumenitsa`, `easybike-ioannina`,
|
|
85
|
+
`easybike-karditsa`, `easybike-kinouria`, `easybike-komotini`, `easybike-patra`,
|
|
86
|
+
`easybike-rethymno`, and `easybike-samos`. The separate `easybike-mani` feed still
|
|
87
|
+
returned two stations in the same check. A null feed raises an explicit provider
|
|
88
|
+
error; a valid empty station array remains an empty snapshot.
|
|
89
|
+
|
|
90
|
+
Do not disable TLS verification or treat an HTML error/maintenance page as an
|
|
91
|
+
empty working bike network to make an audit pass. Preserve the previous snapshot
|
|
92
|
+
when an update fails.
|
|
93
|
+
|
|
94
|
+
## Run a fresh public audit
|
|
95
|
+
|
|
96
|
+
Install the development dependencies, then audit a single network or the full
|
|
97
|
+
catalog:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
bundle install
|
|
101
|
+
bundle exec ruby bin/audit-providers --tag velib --timeout 15 --output /tmp/rubybikes-velib-status.json
|
|
102
|
+
bundle exec ruby bin/audit-providers --timeout 15 --output /tmp/rubybikes-provider-status.json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The audit uses two workers, bounds connection/read time within each network's
|
|
106
|
+
update deadline, honors provider rate-limit cooldowns, and records UTC check
|
|
107
|
+
times, client names, statuses, and station/vehicle counts. It marks authenticated
|
|
108
|
+
entries `requires_credentials` rather than calling them with dummy keys. Output
|
|
109
|
+
statuses include `working`, `empty`, `timeout`, `rate_limited`, `error`, and
|
|
110
|
+
`requires_credentials`. Error reports exclude provider response bodies and
|
|
111
|
+
credential-bearing URLs.
|
|
112
|
+
|
|
113
|
+
The **Audit public provider feeds** GitHub Actions workflow provides the same
|
|
114
|
+
manual check. Supply a network tag for a targeted probe, or leave it empty for
|
|
115
|
+
all predefined networks; download the `provider-status` artifact afterward.
|
|
116
|
+
The JSON report is written incrementally and includes a `complete` flag; partial
|
|
117
|
+
results remain available if an audit is interrupted. Live audits are deliberately separate from pull-request and release test gates,
|
|
118
|
+
so an operator outage does not make deterministic fixture tests fail.
|
|
119
|
+
|
|
120
|
+
When repairing a changed feed, keep its existing tag, verify the operator's
|
|
121
|
+
published endpoint, add a sanitized response fixture and explicit expected
|
|
122
|
+
fields, and record the dated live result. Never commit provider credentials or
|
|
123
|
+
RubyGems recovery codes.
|
data/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# RubyBikes
|
|
2
|
+
|
|
3
|
+
Native Ruby clients for bike-sharing stations and free-floating vehicles. The
|
|
4
|
+
catalog contains **815 networks in 53 countries**, backed by **85 provider
|
|
5
|
+
clients** adapted from [PyBikes](https://github.com/eskerda/pybikes). Operators are
|
|
6
|
+
queried directly; no CityBikes API service or Python installation is required.
|
|
7
|
+
|
|
8
|
+
Requires Ruby **3.1 or newer**. Install with `gem install rubybikes`, or add
|
|
9
|
+
`gem 'rubybikes'` to your application's Gemfile.
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
require 'rubybikes'
|
|
13
|
+
|
|
14
|
+
RubyBikes.open do |bikes|
|
|
15
|
+
network = bikes.get('velib')
|
|
16
|
+
network.update
|
|
17
|
+
network.stations.each do |station|
|
|
18
|
+
puts [station.id, station.name, station.bikes, station.free].inspect
|
|
19
|
+
end
|
|
20
|
+
puts network.to_json
|
|
21
|
+
end
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`get('velib')`, `get(tag: 'velib')`, and the original `get('tag' => 'velib')`
|
|
25
|
+
are equivalent. `get(label: 'Gbfs')` returns matching networks. `tags`, `labels`,
|
|
26
|
+
`catalog`, and `providers` provide discovery without contacting operators.
|
|
27
|
+
Provider records include module/class names, tags, and `authed`, `sync`, and
|
|
28
|
+
`unifeed` flags. Each system exposes `provider` and `client_class`.
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
RubyBikes.open do |bikes|
|
|
32
|
+
system = bikes.build(
|
|
33
|
+
provider: 'NextbikeGbfs', tag: 'custom-ambici', domain: 'bs',
|
|
34
|
+
meta: { name: 'Ambici', city: 'Barcelona', country: 'ES' }
|
|
35
|
+
)
|
|
36
|
+
system.update
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Custom definitions accept upstream constructor parameter names. Class names take
|
|
41
|
+
precedence over module names, case-insensitively. Specify `class_name:` for a
|
|
42
|
+
module with multiple clients, for example `provider: 'keolis', class_name: 'VCub'`.
|
|
43
|
+
All 85 clients are supported, including the four without predefined networks:
|
|
44
|
+
`NextbikeGbfs`, `KeolisIlevia`, `VCub`, and `OTP`.
|
|
45
|
+
|
|
46
|
+
Stations expose `id` (`get_hash`), `name`, `latitude`, `longitude`, `bikes`,
|
|
47
|
+
`free`, UTC `timestamp`, and provider-specific `extra`. Unknown counts remain
|
|
48
|
+
`nil`. Vehicles expose coordinates, `kind`, identity, timestamp, and `extra`.
|
|
49
|
+
Systems, stations, and vehicles support `to_h`/`to_dict`, `to_json`, and
|
|
50
|
+
`to_geojson`. Station IDs retain the PyBikes coordinate-based MD5 convention;
|
|
51
|
+
vehicle IDs retain their network and vehicle identity components.
|
|
52
|
+
|
|
53
|
+
Authenticated clients accept `api_key:` in `get` or `build`. Alternatively,
|
|
54
|
+
configure `RubyBikes.new(keys: { provider_module => credentials })`; tag and
|
|
55
|
+
class-name keys are also accepted. Resolution prefers an explicit key, then a
|
|
56
|
+
network-tag key, provider-module key, and finally a client-class key. Structured keys
|
|
57
|
+
retain the upstream field names, such as BiciMAD `clientid`/`passkey` and Weelo
|
|
58
|
+
`client_id`/`client_secret`. Never commit provider credentials.
|
|
59
|
+
|
|
60
|
+
Updates have a default 60-second overall deadline; use `RubyBikes.new(timeout:
|
|
61
|
+
45)` or `system.update(timeout: 30)` to override it. Individual connections and
|
|
62
|
+
reads are bounded to 5 and 20 seconds and share the update deadline. TLS is
|
|
63
|
+
verified, HTTP redirects are bounded, cookies are scoped, and rate limits raise
|
|
64
|
+
`RubyBikes::RateLimitedError` with `host` and `retry_after`. Authentication refresh
|
|
65
|
+
is supported; failed provider requests are not automatically retried. Failed
|
|
66
|
+
updates retain the previous complete Ruby snapshot. A factory serializes its
|
|
67
|
+
updates; use separate factories for concurrent networks.
|
|
68
|
+
|
|
69
|
+
Errors use `RubyBikes::ProviderError`, `TimeoutError`, `ProtocolError`,
|
|
70
|
+
`NoSystemFoundError`, `NoGetCriteriaError`, and `APIKeyNotAvailableError`.
|
|
71
|
+
Provider response bodies and credential-bearing URLs are excluded from error
|
|
72
|
+
messages. Original top-level exception aliases remain available.
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
bin/setup
|
|
78
|
+
bundle exec rake test build
|
|
79
|
+
ruby .github/scripts/package_smoke.rb
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Tests use Minitest, WebMock, and checked-in response fixtures; external requests
|
|
83
|
+
are disabled. CI requires a successful nonempty fixture update from every client,
|
|
84
|
+
constructs all 815 catalog networks, and enforces 95% line coverage with branch
|
|
85
|
+
coverage reported. Type definitions ship in `sig/`.
|
|
86
|
+
|
|
87
|
+
Quality tooling uses Ruby 3.4 and a separate bundle so runtime compatibility can
|
|
88
|
+
remain Ruby 3.1+:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
BUNDLE_GEMFILE=gemfiles/quality.gemfile bundle install
|
|
92
|
+
BUNDLE_GEMFILE=gemfiles/quality.gemfile bundle exec rake lint typecheck
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for provider changes,
|
|
96
|
+
[PROVIDERS.md](PROVIDERS.md) for live status and known issues, and
|
|
97
|
+
[RELEASING.md](RELEASING.md) for publishing.
|
|
98
|
+
|
|
99
|
+
## Migrating from 0.2
|
|
100
|
+
|
|
101
|
+
The Python subprocess and its requirements have been removed. Delete any
|
|
102
|
+
`python:` constructor argument and `RUBYBIKES_PYTHON` configuration. `engine_info`
|
|
103
|
+
now reports `implementation: 'ruby'`, the gem version, and the upstream baseline
|
|
104
|
+
revision. `close` and the block form remain supported; no child process is used.
|
|
105
|
+
The old direct-require adapter files were retired; use the RubyBikes factory.
|
|
106
|
+
|
|
107
|
+
Distributed under AGPL-3.0. See [LICENSE](LICENSE), [NOTICE](NOTICE), and the
|
|
108
|
+
preserved upstream attribution in `data/ATTRIBUTION.txt`.
|
data/RELEASING.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Releasing RubyBikes
|
|
2
|
+
|
|
3
|
+
Publishing uses the `release.yml` workflow in `edumucelli/rubybikes`, environment
|
|
4
|
+
`release`, and immutable RubyGems owner **255571**. Configure a pending trusted
|
|
5
|
+
publisher under that RubyGems account for the first release, or an existing-gem
|
|
6
|
+
trusted publisher for later releases. Enable MFA on the RubyGems account.
|
|
7
|
+
|
|
8
|
+
The pending publisher described during setup expires after about twelve hours.
|
|
9
|
+
If it expires before the first release, recreate it before publishing. Do not
|
|
10
|
+
release incomplete code merely to use an expiring publisher.
|
|
11
|
+
|
|
12
|
+
The public RubyGems action versions inspected during development do not expose
|
|
13
|
+
an owner input. `.github/scripts/configure_rubygems.rb` performs the documented
|
|
14
|
+
OIDC exchange directly, sending `{jwt: ..., owner: "255571"}`. RubyGems requires
|
|
15
|
+
the owner ID to be a string. It masks the
|
|
16
|
+
short-lived API key and passes it through the temporary Actions environment
|
|
17
|
+
file. No long-lived API key is stored in repository secrets or a credentials
|
|
18
|
+
file. A future migration to an official action must verify that the action
|
|
19
|
+
actually forwards the owner input, especially for the first push.
|
|
20
|
+
|
|
21
|
+
1. Bump `RubyBikes::VERSION` in `lib/rubybikes/version.rb` and update the
|
|
22
|
+
changelog, then push or merge the commit into `master` on GitHub.
|
|
23
|
+
2. The release workflow runs native tests, all-client fixture verification,
|
|
24
|
+
95% coverage, lint, type checks, and the installed-package smoke test.
|
|
25
|
+
3. After CI passes, the workflow reads the version from that file and checks
|
|
26
|
+
RubyGems. Already published versions are skipped; registry errors fail the
|
|
27
|
+
release instead of treating the version as available.
|
|
28
|
+
4. For an unpublished version, it verifies master ancestry, builds and checks
|
|
29
|
+
the package, exchanges OIDC credentials for owner **255571**, and publishes
|
|
30
|
+
to RubyGems. It then creates the matching tag (for example `v0.3.0`) at the
|
|
31
|
+
tested commit and a GitHub release with the gem attached. An existing tag
|
|
32
|
+
pointing to a different commit blocks publication.
|
|
33
|
+
|
|
34
|
+
No manual tag is needed. Changes to `release.yml` or its credential/version
|
|
35
|
+
scripts also trigger the workflow, allowing the initial `0.3.0` release without
|
|
36
|
+
a redundant version bump. To retry
|
|
37
|
+
an unpublished version after fixing a release problem, run `release.yml`
|
|
38
|
+
manually with `workflow_dispatch` on `master`.
|
|
39
|
+
|
|
40
|
+
A failed validation or failed CI run cannot publish. A RubyGems push failure
|
|
41
|
+
prevents GitHub release creation. If publication succeeded but GitHub release
|
|
42
|
+
creation failed, create the release at the published commit without republishing
|
|
43
|
+
or overwriting the gem. RubyGems versions are immutable; rerunning the workflow
|
|
44
|
+
skips a version that is already on RubyGems.
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
aksu.py
|
|
2
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
3
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
4
|
+
|
|
5
|
+
ambici.py
|
|
6
|
+
# Copyright (C) 2010-2023, eskerda <eskerda@gmail.com>
|
|
7
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
8
|
+
|
|
9
|
+
baksi.py
|
|
10
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
11
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
12
|
+
|
|
13
|
+
base.py
|
|
14
|
+
# Copyright (C) 2010-2025, eskerda <eskerda@gmail.com>
|
|
15
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
16
|
+
|
|
17
|
+
batumvelo.py
|
|
18
|
+
# Copyright (C) 2025, Martín González Gómez <m@martingonzalez.net>
|
|
19
|
+
# Copyright (C) 2026, eskerda <eskerda@gmail.com>
|
|
20
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
21
|
+
|
|
22
|
+
bcycle.py
|
|
23
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
24
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
25
|
+
|
|
26
|
+
beryl.py
|
|
27
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
28
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
29
|
+
|
|
30
|
+
bicicard.py
|
|
31
|
+
# Copyright (C) 2023, eskerda <eskerda@gmail.com>
|
|
32
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
33
|
+
|
|
34
|
+
bicicas.py
|
|
35
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
36
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
37
|
+
|
|
38
|
+
bicielx.py
|
|
39
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
40
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
41
|
+
|
|
42
|
+
biciferrolterra.py
|
|
43
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
44
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
45
|
+
|
|
46
|
+
bicimad.py
|
|
47
|
+
# Copyright (C) 2018, eskerda <eskerda@gmail.com>
|
|
48
|
+
# Copyright (C) 2021, Altonss (https://github.com/Altonss)
|
|
49
|
+
# Copyright (C) 2022, eUgEntOptIc44 (https://github.com/eUgEntOptIc44)
|
|
50
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
51
|
+
|
|
52
|
+
bicincitta.py
|
|
53
|
+
# Copyright (C) 2019, eskerda <eskerda@gmail.com>
|
|
54
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
55
|
+
|
|
56
|
+
bikeshare_ie.py
|
|
57
|
+
# Copyright (C) 2025, Martín González Gómez <m@martingonzalez.net>
|
|
58
|
+
# Copyright (C) Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
59
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
60
|
+
|
|
61
|
+
bikeu.py
|
|
62
|
+
# Copyright (C) 2015, thesebas <thesebas@thesebas.net>
|
|
63
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
64
|
+
|
|
65
|
+
bixi.py
|
|
66
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
67
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
68
|
+
|
|
69
|
+
bizkaibizi.py
|
|
70
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
71
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
72
|
+
|
|
73
|
+
careem.py
|
|
74
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
75
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
76
|
+
|
|
77
|
+
charichari.py
|
|
78
|
+
# Copyright (C) 2026, Martín González Gómez <m@martingonzalez.net>
|
|
79
|
+
|
|
80
|
+
clujbike.py
|
|
81
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
82
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
83
|
+
|
|
84
|
+
cyclocity.py
|
|
85
|
+
# Copyright (C) 2010-2026, eskerda <eskerda@gmail.com>
|
|
86
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
87
|
+
|
|
88
|
+
cyclopolis.py
|
|
89
|
+
# Copyright (C) 2015, Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
90
|
+
# Copyright (C) 2025, Martín González Gómez <m@martingonzalez.net.com>
|
|
91
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
92
|
+
|
|
93
|
+
cykleo.py
|
|
94
|
+
# Copyright (C) 2010-2023, eskerda <eskerda@gmail.com>
|
|
95
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
96
|
+
|
|
97
|
+
decobike.py
|
|
98
|
+
# Copyright (C) 2010-2023, eskerda <eskerda@gmail.com>
|
|
99
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
100
|
+
|
|
101
|
+
deutschebahn.py
|
|
102
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
103
|
+
# Copyright (C) 2023, Lluis Esquerda <eskerda@gmail.com>
|
|
104
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
105
|
+
|
|
106
|
+
docomo.py
|
|
107
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
108
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
109
|
+
|
|
110
|
+
easybike.py
|
|
111
|
+
# Copyright (C) 2015, bparmentier <dev@brunoparmentier.be>
|
|
112
|
+
# Copyright (C) 2016, Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
113
|
+
# Copyright (C) 2016, eskerda <eskerda@gmail.com>
|
|
114
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
115
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
116
|
+
|
|
117
|
+
ecovelo.py
|
|
118
|
+
# Copyright (C) 2021, Altonss https://github.com/Altonss
|
|
119
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
120
|
+
|
|
121
|
+
emovity.py
|
|
122
|
+
# Copyright (C) 2010-2021, eskerda <eskerda@gmail.com>
|
|
123
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
124
|
+
|
|
125
|
+
encicla.py
|
|
126
|
+
# Copyright (C) 2015, Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
127
|
+
# Copyright (C) 2023, eskerda <eskerda@gmail.com>
|
|
128
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
129
|
+
|
|
130
|
+
fsm.py
|
|
131
|
+
# Copyright (C) 2017, aronsky <aronsky@gmail.com>
|
|
132
|
+
# Copyright (C) 2023, eskerda <eskerda@gmail.com>
|
|
133
|
+
|
|
134
|
+
ganxeta.py
|
|
135
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
136
|
+
|
|
137
|
+
gbfs.py
|
|
138
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
139
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
140
|
+
|
|
141
|
+
gira.py
|
|
142
|
+
# Copyright (C) 2010-2023, eskerda <eskerda@gmail.com>
|
|
143
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
144
|
+
|
|
145
|
+
gyorbike.py
|
|
146
|
+
# Copyright (C) 2026, Martín González Gómez <m@martingonzalez.net>
|
|
147
|
+
# Copyright (C) 2026, eskerda <eskerda@gmail.com>
|
|
148
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
149
|
+
|
|
150
|
+
hellocycling.py
|
|
151
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
152
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
153
|
+
|
|
154
|
+
joco.py
|
|
155
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
156
|
+
|
|
157
|
+
keolis.py
|
|
158
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
159
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
160
|
+
|
|
161
|
+
kolumbus.py
|
|
162
|
+
# Copyright (C) 2024, eskerda <eskerda@gmail.com>
|
|
163
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
164
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
165
|
+
|
|
166
|
+
lastenvelo.py
|
|
167
|
+
# Copyright (C) 2024, eskerda <eskerda@gmail.com>
|
|
168
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
169
|
+
|
|
170
|
+
linkbike.py
|
|
171
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
172
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
173
|
+
|
|
174
|
+
meiob.py
|
|
175
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
176
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
177
|
+
|
|
178
|
+
mobhis.py
|
|
179
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
180
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
181
|
+
|
|
182
|
+
movus.py
|
|
183
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
184
|
+
# Copyright (C) 2023, Lluis Esquerda <eskerda@gmail.com>
|
|
185
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
186
|
+
|
|
187
|
+
nextbike.py
|
|
188
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
189
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
190
|
+
|
|
191
|
+
nextbike_gbfs.py
|
|
192
|
+
# Copyright (C) 2025, eskerda <eskerda@gmail.com>
|
|
193
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
194
|
+
|
|
195
|
+
nubija.py
|
|
196
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
197
|
+
# Copyright (C) 2025, eskerda <eskerda@gmail.com>
|
|
198
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
199
|
+
|
|
200
|
+
open_source_bike_share.py
|
|
201
|
+
# Copyright (C) Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
202
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
203
|
+
|
|
204
|
+
open_source_bike_share_v2.py
|
|
205
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
206
|
+
|
|
207
|
+
openmove.py
|
|
208
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
209
|
+
|
|
210
|
+
ov_fiets.py
|
|
211
|
+
# Copyright (C) 2024, eskerda <eskerda@gmail.com>
|
|
212
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
213
|
+
|
|
214
|
+
publibike.py
|
|
215
|
+
# Copyright (C) 2010-2026, eskerda <eskerda@gmail.com>
|
|
216
|
+
# Copyright (C) 2022-2023, eUgEntOptIc44 (https://github.com/eUgEntOptIc44)
|
|
217
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
218
|
+
|
|
219
|
+
qrobici.py
|
|
220
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
221
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
222
|
+
|
|
223
|
+
samba.py
|
|
224
|
+
# Original work Copyright (C) 2014, iomartin <iomartin@iomartin.net>
|
|
225
|
+
# Modified work Copyright (C) 2015 Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
226
|
+
# Modified work Copyright (C) 2023 Martín González Gómez <m@martingonzalez.net>
|
|
227
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
228
|
+
|
|
229
|
+
sejong.py
|
|
230
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
231
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
232
|
+
|
|
233
|
+
seoulbike.py
|
|
234
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
235
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
236
|
+
|
|
237
|
+
slovnaft_bajk.py
|
|
238
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
239
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
240
|
+
|
|
241
|
+
smartbike.py
|
|
242
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
243
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
244
|
+
|
|
245
|
+
smoove.py
|
|
246
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
247
|
+
# Copyright (C) 2019, Louis Turpinat <turpinat.louis@gmail.com>
|
|
248
|
+
# Copyright (C) 2016, Lluis Esquerda <eskerda@gmail.com>
|
|
249
|
+
# Copyright (C) 2015, Eduardo Mucelli Rezende Oliveira <edumucelli@gmail.com>
|
|
250
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
251
|
+
|
|
252
|
+
soltrafego.py
|
|
253
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
254
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
255
|
+
|
|
256
|
+
tashu.py
|
|
257
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
258
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
259
|
+
|
|
260
|
+
urbansharing.py
|
|
261
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
262
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
263
|
+
|
|
264
|
+
utils.py
|
|
265
|
+
# Copyright (C) 2010-2012, eskerda <eskerda@gmail.com>
|
|
266
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
267
|
+
|
|
268
|
+
veloway.py
|
|
269
|
+
# Copyright (C) 2010-2021, eskerda <eskerda@gmail.com>
|
|
270
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
271
|
+
|
|
272
|
+
weelo.py
|
|
273
|
+
# Copyright (C) 2010-2023, eskerda <eskerda@gmail.com>
|
|
274
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
275
|
+
|
|
276
|
+
wegoshare.py
|
|
277
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
278
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
279
|
+
|
|
280
|
+
xian.py
|
|
281
|
+
# Copyright (C) 2024, Martín González Gómez <m@martingonzalez.net>
|
|
282
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
283
|
+
|
|
284
|
+
yelovelo.py
|
|
285
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
286
|
+
# Distributed under the AGPL license, see LICENSE.txt
|
|
287
|
+
|
|
288
|
+
youbike.py
|
|
289
|
+
# Copyright (C) 2023, Martín González Gómez <m@martingonzalez.net>
|
|
290
|
+
# Distributed under the AGPL license, see LICENSE.txt
|