lex-github 0.3.2 → 0.3.4

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: 8ea69decf68b91f650186b1719a7e29646ce4f7308bd2d90eebeadcd6048718d
4
- data.tar.gz: 3bdf52e0d20f137e7efb2f7c7330905de6b924d184edb4007c616435d679f44a
3
+ metadata.gz: 61ef9dc50273e5c0700962c3864a8d3ae24276621ed29215d35551f52fb4573d
4
+ data.tar.gz: b5a4de4b921f743c86320e2c95c99c2773ebcf56b02df788cf2a62323929ae87
5
5
  SHA512:
6
- metadata.gz: 2cc5f719ed57a84ebc740a0009a0836fecfcfaa162794e64806e9770dc653e2368ac37d44ef3655d29bd132ed1957148be691dd4544fadb05e969250949144ce
7
- data.tar.gz: 9bccdb81c9b7f52348c623b19473db41bc36f3d5539680789eceb7d50997136abafe3d42dcccb3010dacb57db8fb7c53998b1ea0374adfedab54e0414b7364af
6
+ metadata.gz: c06065ce5d893b0a4008c7195155669985c3e44cb4b4eb8817c74e2faa99912fdbadb0a8b74fb49be445e95696293e750f0f945ab05576b08cc5d02ebaa645a9
7
+ data.tar.gz: f3d6915a975c4b35c669b3cf0aaf0d9e443a6333136e019df460638574a7f58362904560cc6c366093a4c797ee2518d2c62f742fd9e2a339a5c194bd06c4b11d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.3.4] - 2026-04-06
6
+
7
+ ### Added
8
+ - `resolve_broker_app` to `CREDENTIAL_RESOLVERS` for Broker integration (Phase 8 Wave 3)
9
+ - Stable `installation_id` fingerprint for consistent credential caching across GitHub App installations
10
+
11
+ ## [0.3.3] - 2026-03-31
12
+
13
+ ### Fixed
14
+ - CLI runner output: `status` and `login` commands now print JSON results to stdout
15
+ - CLI runner errors print to stderr via `warn`
16
+
5
17
  ## [0.3.2] - 2026-03-31
6
18
 
7
19
  ### Added
data/CLAUDE.md CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  ## Purpose
8
8
 
9
- Legion Extension that connects LegionIO to GitHub. Provides runners for interacting with the GitHub REST API covering repositories, issues, pull requests, users, organizations, gists, search, labels, comments, commits, branches, file contents, GitHub App authentication, OAuth delegated auth, and webhook handling.
9
+ Legion Extension that connects LegionIO to GitHub. Provides runners for interacting with the GitHub REST API covering repositories, issues, pull requests, users, organizations, gists, search, labels, comments, commits, branches, file contents, Actions workflows, checks, releases, deployments, repository webhooks, GitHub App authentication, OAuth delegated auth, and credential storage.
10
10
 
11
11
  **GitHub**: https://github.com/LegionIO/lex-github
12
12
  **License**: MIT
13
- **Version**: 0.3.0
13
+ **Version**: 0.3.3
14
14
 
15
15
  ## Architecture
16
16
 
@@ -28,21 +28,45 @@ Legion::Extensions::Github
28
28
  │ ├── Comments # CRUD issue/PR comments
29
29
  │ ├── Commits # List, get, compare commits
30
30
  │ ├── Branches # Create branches via Git Data API
31
- └── Contents # Commit multiple files via Git Data API
31
+ ├── Contents # Commit multiple files via Git Data API
32
+ │ ├── Actions # Workflows, runs, jobs, artifacts, logs
33
+ │ ├── Checks # Check runs, check suites, annotations
34
+ │ ├── Releases # CRUD releases, release assets
35
+ │ ├── Deployments # CRUD deployments and deployment statuses
36
+ │ ├── RepositoryWebhooks # CRUD repo webhooks, ping, test, deliveries
37
+ │ └── Auth # Composite runner: delegates to App, CredentialStore, OAuth auth modules
32
38
  ├── App/
33
- └── Runners/
34
- ├── Auth # JWT generation, installation token exchange, list/get installations
35
- ├── Webhooks # HMAC signature verification, event parsing
36
- ├── Manifest # GitHub App manifest flow (generate, exchange code, manifest URL)
37
- └── Installations # Full installation management (list repos, suspend, delete)
39
+ ├── Runners/
40
+ ├── Auth # JWT generation, installation token exchange, list/get installations
41
+ ├── Webhooks # HMAC signature verification, event parsing
42
+ ├── Manifest # GitHub App manifest flow (generate, exchange code, manifest URL)
43
+ │ ├── Installations # Full installation management (list repos, suspend, delete)
44
+ │ │ └── CredentialStore # Store app credentials and OAuth tokens in Vault
45
+ │ ├── Actors/
46
+ │ │ ├── TokenRefresh # Periodic App installation token refresh
47
+ │ │ └── WebhookPoller # Polls GitHub webhook deliveries
48
+ │ └── Transport/ # AMQP transport (exchanges/queues/messages)
38
49
  ├── OAuth/
39
- └── Runners/
40
- └── Auth # PKCE + Authorization Code, device code, refresh, revoke
50
+ ├── Runners/
51
+ └── Auth # PKCE + Authorization Code, device code, refresh, revoke
52
+ │ ├── Actors/
53
+ │ │ └── TokenRefresh # Periodic OAuth delegated token refresh
54
+ │ └── Transport/ # AMQP transport (exchanges/queues)
55
+ ├── Middleware/
56
+ │ ├── RateLimit # Tracks rate-limit headers, skips exhausted credentials
57
+ │ ├── ScopeProbe # Detects scope-denied 403s for specific owner/repo
58
+ │ └── CredentialFallback # Triggers fallback to next credential source on auth failure
41
59
  ├── Helpers/
42
60
  │ ├── Client # 8-source scope-aware credential resolution chain + Faraday builder
43
61
  │ ├── Cache # Two-tier read-through/write-through API response caching
44
62
  │ ├── TokenCache # Token lifecycle management (store, fetch, expiry, rate limits)
45
- └── ScopeRegistry # Credential-to-scope authorization cache (org/repo level)
63
+ ├── ScopeRegistry # Credential-to-scope authorization cache (org/repo level)
64
+ │ ├── BrowserAuth # Delegated OAuth orchestrator (PKCE, headless detection, browser launch)
65
+ │ └── CallbackServer # Ephemeral TCP server for OAuth redirect callback
66
+ ├── CLI/
67
+ │ ├── Auth # `legion lex exec github auth login/status`
68
+ │ ├── App # `legion lex exec github app setup/complete_setup`
69
+ │ └── Runner # CLI dispatch registration
46
70
  └── Client # Standalone client class (includes all runners)
47
71
  ```
48
72
 
@@ -63,12 +87,16 @@ Rate-limited credentials are skipped. Scope-denied credentials (for a given owne
63
87
 
64
88
  | Gem | Purpose |
65
89
  |-----|---------|
66
- | `faraday` | HTTP client for GitHub REST API |
67
- | `jwt` (~> 2.7) | RS256 JWT generation for GitHub App authentication |
90
+ | `faraday` (>= 2.0) | HTTP client for GitHub REST API |
91
+ | `jwt` (>= 2.7) | RS256 JWT generation for GitHub App authentication |
68
92
  | `base64` (>= 0.1) | PKCE code challenge computation |
69
- | `legion-cache` | Two-tier caching (global Redis + local in-memory) |
70
- | `legion-crypt` | Vault secret resolution for credentials |
71
- | `legion-settings` | Settings-based credential resolution |
93
+ | `legion-cache` (>= 1.3.11) | Two-tier caching (global Redis + local in-memory) |
94
+ | `legion-crypt` (>= 1.4.9) | Vault secret resolution for credentials |
95
+ | `legion-data` (>= 1.4.17) | Data persistence |
96
+ | `legion-json` (>= 1.2.1) | JSON serialization |
97
+ | `legion-logging` (>= 1.3.2) | Logging |
98
+ | `legion-settings` (>= 1.3.14) | Settings-based credential resolution |
99
+ | `legion-transport` (>= 1.3.9) | AMQP transport for actors |
72
100
 
73
101
  ## Key Files
74
102
 
@@ -80,15 +108,20 @@ Rate-limited credentials are skipped. Scope-denied credentials (for a given owne
80
108
  | `lib/legion/extensions/github/helpers/cache.rb` | Two-tier API response caching |
81
109
  | `lib/legion/extensions/github/helpers/token_cache.rb` | Token lifecycle + rate limit tracking |
82
110
  | `lib/legion/extensions/github/helpers/scope_registry.rb` | Credential-to-scope authorization cache |
111
+ | `lib/legion/extensions/github/helpers/browser_auth.rb` | OAuth PKCE browser launch + headless detection |
112
+ | `lib/legion/extensions/github/helpers/callback_server.rb` | Ephemeral TCP server for OAuth redirect |
83
113
  | `lib/legion/extensions/github/app/runners/auth.rb` | JWT generation, installation tokens |
84
114
  | `lib/legion/extensions/github/app/runners/webhooks.rb` | Webhook signature verification, event parsing |
85
115
  | `lib/legion/extensions/github/app/runners/manifest.rb` | GitHub App manifest registration flow |
86
116
  | `lib/legion/extensions/github/app/runners/installations.rb` | Installation management |
117
+ | `lib/legion/extensions/github/app/runners/credential_store.rb` | Store app/OAuth credentials in Vault |
87
118
  | `lib/legion/extensions/github/oauth/runners/auth.rb` | OAuth PKCE, device code, token refresh/revoke |
119
+ | `lib/legion/extensions/github/runners/auth.rb` | Composite auth runner (delegates to app + oauth + credential_store) |
120
+ | `lib/lex/github.rb` | Redirect shim for `require 'lex/github'` |
88
121
 
89
122
  ## Testing
90
123
 
91
- 131 specs across 23 spec files (growing with each new runner).
124
+ 234 specs across 38 spec files.
92
125
 
93
126
  ```bash
94
127
  bundle install
@@ -15,9 +15,9 @@ module Legion
15
15
  csec = client_secret || settings_client_secret
16
16
  sc = scopes || settings_scopes
17
17
 
18
- unless cid && csec
18
+ unless cid
19
19
  return { error: 'missing_config',
20
- description: 'Set github.oauth.client_id or github.app.client_id and github.app.client_secret in settings or pass as arguments' }
20
+ description: 'Set github.oauth.client_id or github.app.client_id in settings' }
21
21
  end
22
22
 
23
23
  browser = Helpers::BrowserAuth.new(client_id: cid, client_secret: csec, scopes: sc)
@@ -1,90 +1,101 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'legion/extensions/github/cli/auth'
4
- require 'legion/extensions/github/cli/app'
5
- require 'legion/extensions/github/app/runners/credential_store'
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'uri'
6
+ require 'rbconfig'
6
7
 
7
8
  module Legion
8
9
  module Extensions
9
10
  module Github
10
11
  module CLI
11
- class AuthRunner
12
- include Legion::Logging::Helper if defined?(Legion::Logging::Helper)
13
- include Github::CLI::Auth
14
- include Github::App::Runners::CredentialStore
15
-
16
- def credential_fingerprint(auth_type:, identifier:)
17
- "#{auth_type}:#{identifier}"
18
- end
12
+ DAEMON_URL = ENV.fetch('LEGION_API_URL', 'http://127.0.0.1:4567')
19
13
 
20
- def vault_get(path)
21
- return nil unless defined?(Legion::Crypt)
14
+ module DaemonApi
15
+ private
22
16
 
23
- ::Legion::Crypt.get(path)
24
- rescue StandardError => e
25
- log.warn("[lex-github] vault_get failed: #{e.message}")
26
- nil
17
+ def api_post(path, body = {})
18
+ uri = URI("#{DAEMON_URL}#{path}")
19
+ http = Net::HTTP.new(uri.host, uri.port)
20
+ http.open_timeout = 5
21
+ http.read_timeout = 30
22
+ request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
23
+ request.body = ::JSON.generate(body)
24
+ parse_response(http.request(request))
25
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET => _e
26
+ { error: 'daemon_unavailable', description: "Legion daemon not running at #{DAEMON_URL}. Start it with: legionio start" }
27
27
  end
28
28
 
29
- def cache_connected?
30
- defined?(Legion::Cache) && ::Legion::Cache.connected?
31
- rescue StandardError => e
32
- log.debug("[lex-github] cache_connected? check failed: #{e.message}")
33
- false
29
+ def api_get(path)
30
+ uri = URI("#{DAEMON_URL}#{path}")
31
+ parse_response(Net::HTTP.get_response(uri))
32
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET => _e
33
+ { error: 'daemon_unavailable', description: "Legion daemon not running at #{DAEMON_URL}. Start it with: legionio start" }
34
34
  end
35
35
 
36
- def local_cache_connected?
37
- defined?(Legion::Cache::Local) && ::Legion::Cache::Local.connected?
38
- rescue StandardError => e
39
- log.debug("[lex-github] local_cache_connected? check failed: #{e.message}")
40
- false
36
+ def parse_response(response)
37
+ ::JSON.parse(response.body, symbolize_names: true)
38
+ rescue ::JSON::ParserError => _e
39
+ { error: "http_#{response.code}", description: response.body&.strip }
41
40
  end
42
41
 
43
- def cache_get(key)
44
- ::Legion::Cache.get(key)
45
- rescue StandardError => e
46
- log.debug("[lex-github] cache_get failed: #{e.message}")
47
- nil
42
+ def print_json(result)
43
+ if result.is_a?(Hash) && result[:error]
44
+ warn "Error: #{result[:error]}"
45
+ warn " #{result[:description]}" if result[:description]
46
+ else
47
+ puts ::JSON.pretty_generate(result)
48
+ end
48
49
  end
49
50
 
50
- def local_cache_get(key)
51
- ::Legion::Cache::Local.get(key)
52
- rescue StandardError => e
53
- log.debug("[lex-github] local_cache_get failed: #{e.message}")
54
- nil
51
+ def open_browser(url)
52
+ cmd = case RbConfig::CONFIG['host_os']
53
+ when /darwin/ then 'open'
54
+ when /linux/ then 'xdg-open'
55
+ when /mswin|mingw/ then 'start'
56
+ end
57
+ system(cmd, url) if cmd
55
58
  end
59
+ end
56
60
 
57
- def cache_set(key, value, ttl: 300)
58
- ::Legion::Cache.set(key, value, ttl)
59
- rescue StandardError => e
60
- log.debug("[lex-github] cache_set failed: #{e.message}")
61
- nil
61
+ class AuthRunner
62
+ include DaemonApi
63
+
64
+ def status
65
+ print_json(api_post('/api/extensions/github/runners/auth/status'))
62
66
  end
63
67
 
64
- def local_cache_set(key, value, ttl: 300)
65
- ::Legion::Cache::Local.set(key, value, ttl)
66
- rescue StandardError => e
67
- log.debug("[lex-github] local_cache_set failed: #{e.message}")
68
- nil
68
+ def login
69
+ print_json(api_post('/api/extensions/github/runners/auth/login'))
69
70
  end
70
71
  end
71
72
 
72
73
  class AppRunner
73
- include Legion::Logging::Helper if defined?(Legion::Logging::Helper)
74
- include Github::CLI::App
75
- include Github::App::Runners::CredentialStore
74
+ include DaemonApi
76
75
 
77
- def credential_fingerprint(auth_type:, identifier:)
78
- "#{auth_type}:#{identifier}"
79
- end
76
+ def setup
77
+ result = api_post('/api/extensions/github/cli/app/setup')
80
78
 
81
- def vault_get(path)
82
- return nil unless defined?(Legion::Crypt)
79
+ if result[:error]
80
+ print_json(result)
81
+ return
82
+ end
83
+
84
+ url = result.dig(:data, :manifest_url)
85
+ if url
86
+ warn 'Opening browser to create GitHub App...'
87
+ open_browser(url)
88
+ warn 'Waiting for callback...'
89
+ poll = api_post('/api/extensions/github/cli/app/await_callback',
90
+ { timeout: 300 })
91
+ print_json(poll)
92
+ else
93
+ print_json(result)
94
+ end
95
+ end
83
96
 
84
- ::Legion::Crypt.get(path)
85
- rescue StandardError => e
86
- log.warn("[lex-github] vault_get failed: #{e.message}")
87
- nil
97
+ def complete_setup
98
+ print_json(api_post('/api/extensions/github/cli/app/complete_setup'))
88
99
  end
89
100
  end
90
101
  end
@@ -14,7 +14,7 @@ module Legion
14
14
 
15
15
  attr_reader :client_id, :client_secret, :scopes
16
16
 
17
- def initialize(client_id:, client_secret:, scopes: DEFAULT_SCOPES, auth: nil, **)
17
+ def initialize(client_id:, client_secret: nil, scopes: DEFAULT_SCOPES, auth: nil, **)
18
18
  @client_id = client_id
19
19
  @client_secret = client_secret
20
20
  @scopes = scopes
@@ -15,6 +15,7 @@ module Legion
15
15
 
16
16
  CREDENTIAL_RESOLVERS = %i[
17
17
  resolve_vault_delegated resolve_settings_delegated
18
+ resolve_broker_app
18
19
  resolve_vault_app resolve_settings_app
19
20
  resolve_vault_pat resolve_settings_pat
20
21
  resolve_gh_cli resolve_env
@@ -139,6 +140,23 @@ module Legion
139
140
  nil
140
141
  end
141
142
 
143
+ def resolve_broker_app
144
+ return nil unless defined?(Legion::Identity::Broker)
145
+
146
+ token = Legion::Identity::Broker.token_for(:github)
147
+ return nil unless token
148
+
149
+ lease = Legion::Identity::Broker.lease_for(:github)
150
+ installation_id = lease&.metadata&.dig(:installation_id) || 'unknown'
151
+ fp = credential_fingerprint(auth_type: :app_installation,
152
+ identifier: "broker_app_#{installation_id}")
153
+ { token: token, auth_type: :app_installation,
154
+ metadata: { source: :broker, credential_type: :installation_token,
155
+ credential_fingerprint: fp } }
156
+ rescue StandardError => _e
157
+ nil
158
+ end
159
+
142
160
  def resolve_vault_app
143
161
  return nil unless defined?(Legion::Crypt)
144
162
 
@@ -33,21 +33,19 @@ module Legion
33
33
  { result: "https://github.com/login/oauth/authorize?#{params}" }
34
34
  end
35
35
 
36
- def exchange_code(client_id:, client_secret:, code:, redirect_uri:, code_verifier:, **)
37
- response = oauth_connection.post('/login/oauth/access_token', {
38
- client_id: client_id, client_secret: client_secret,
39
- code: code, redirect_uri: redirect_uri,
40
- code_verifier: code_verifier
41
- })
36
+ def exchange_code(client_id:, code:, redirect_uri:, code_verifier:, client_secret: nil, **)
37
+ body = { client_id: client_id, code: code,
38
+ redirect_uri: redirect_uri, code_verifier: code_verifier }
39
+ body[:client_secret] = client_secret if client_secret
40
+ response = oauth_connection.post('/login/oauth/access_token', body)
42
41
  { result: response.body }
43
42
  end
44
43
 
45
- def refresh_token(client_id:, client_secret:, refresh_token:, **)
46
- response = oauth_connection.post('/login/oauth/access_token', {
47
- client_id: client_id, client_secret: client_secret,
48
- refresh_token: refresh_token,
49
- grant_type: 'refresh_token'
50
- })
44
+ def refresh_token(client_id:, refresh_token:, client_secret: nil, **)
45
+ body = { client_id: client_id, refresh_token: refresh_token,
46
+ grant_type: 'refresh_token' }
47
+ body[:client_secret] = client_secret if client_secret
48
+ response = oauth_connection.post('/login/oauth/access_token', body)
51
49
  { result: response.body }
52
50
  end
53
51
 
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/github/helpers/client'
4
+ require 'legion/extensions/github/helpers/browser_auth'
5
+ require 'legion/extensions/github/app/runners/auth'
6
+ require 'legion/extensions/github/app/runners/credential_store'
7
+ require 'legion/extensions/github/oauth/runners/auth'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module Github
12
+ module Runners
13
+ module Auth
14
+ include Legion::Extensions::Github::Helpers::Client
15
+ include Legion::Extensions::Github::App::Runners::Auth
16
+ include Legion::Extensions::Github::App::Runners::CredentialStore
17
+ include Legion::Extensions::Github::OAuth::Runners::Auth
18
+
19
+ def self.remote_invocable?
20
+ false
21
+ end
22
+
23
+ def status(**)
24
+ cred = resolve_credential
25
+ unless cred
26
+ log.warn('[lex-github] auth status: no credential found across all sources')
27
+ return { result: { authenticated: false } }
28
+ end
29
+
30
+ log.info("[lex-github] auth status: credential found via #{cred[:auth_type]}")
31
+
32
+ user_info = {}
33
+ scopes = nil
34
+ begin
35
+ response = connection(token: cred[:token]).get('/user')
36
+ user_info = response.body || {}
37
+ headers = response.respond_to?(:headers) ? response.headers : {}
38
+ scopes_header = headers['X-OAuth-Scopes'] || headers['x-oauth-scopes']
39
+ scopes = scopes_header&.split(',')&.map(&:strip)
40
+ log.info("[lex-github] auth status: authenticated as #{user_info['login']} (#{cred[:auth_type]})")
41
+ rescue StandardError => e
42
+ log.warn("[lex-github] auth status: credential found but /user request failed: #{e.message}")
43
+ end
44
+
45
+ { result: { authenticated: true, auth_type: cred[:auth_type],
46
+ user: user_info['login'], scopes: scopes } }
47
+ end
48
+
49
+ def login(client_id: nil, scopes: nil, **)
50
+ cid = client_id || settings_client_id
51
+ unless cid
52
+ log.error('[lex-github] auth login: no client_id configured — set github.app.client_id in settings')
53
+ return { error: 'missing_config', description: 'Set github.app.client_id in settings' }
54
+ end
55
+
56
+ log.info("[lex-github] auth login: starting OAuth flow with client_id=#{cid[0..7]}...")
57
+
58
+ sc = scopes || settings_scopes
59
+ browser = Helpers::BrowserAuth.new(client_id: cid, scopes: sc)
60
+ result = browser.authenticate
61
+
62
+ if result[:error]
63
+ log.error("[lex-github] auth login failed: #{result[:error]} — #{result[:description]}")
64
+ return { result: nil, error: result[:error], description: result[:description] }
65
+ end
66
+
67
+ if result[:result]&.dig('access_token')
68
+ user = begin
69
+ current_user(token: result[:result]['access_token'])
70
+ rescue StandardError => e
71
+ log.warn("[lex-github] auth login: token obtained but /user lookup failed: #{e.message}")
72
+ 'default'
73
+ end
74
+
75
+ log.info("[lex-github] auth login: authenticated as #{user}")
76
+
77
+ if respond_to?(:store_oauth_token, true)
78
+ store_oauth_token(
79
+ user: user,
80
+ access_token: result[:result]['access_token'],
81
+ refresh_token: result[:result]['refresh_token'],
82
+ expires_in: result[:result]['expires_in']
83
+ )
84
+ log.info("[lex-github] auth login: token stored for user=#{user}")
85
+ else
86
+ log.warn('[lex-github] auth login: store_oauth_token not available — token not persisted')
87
+ end
88
+ else
89
+ log.warn('[lex-github] auth login: OAuth completed but no access_token in response')
90
+ end
91
+
92
+ result
93
+ end
94
+
95
+ def installations(**)
96
+ log.info('[lex-github] listing app installations')
97
+ list_installations(**)
98
+ end
99
+
100
+ private
101
+
102
+ def current_user(token:)
103
+ connection(token: token).get('/user').body['login']
104
+ end
105
+
106
+ def settings_client_id
107
+ defined?(Legion::Settings) &&
108
+ (Legion::Settings.dig(:github, :oauth, :client_id) ||
109
+ Legion::Settings.dig(:github, :app, :client_id))
110
+ rescue StandardError => _e
111
+ nil
112
+ end
113
+
114
+ def settings_scopes
115
+ defined?(Legion::Settings) && Legion::Settings.dig(:github, :oauth, :scopes)
116
+ rescue StandardError => _e
117
+ nil
118
+ end
119
+
120
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
121
+ Legion::Extensions::Helpers.const_defined?(:Lex, false)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Github
6
- VERSION = '0.3.2'
6
+ VERSION = '0.3.4'
7
7
  end
8
8
  end
9
9
  end
@@ -35,6 +35,7 @@ require 'legion/extensions/github/runners/actions'
35
35
  require 'legion/extensions/github/runners/checks'
36
36
  require 'legion/extensions/github/runners/releases'
37
37
  require 'legion/extensions/github/runners/deployments'
38
+ require 'legion/extensions/github/runners/auth'
38
39
  require 'legion/extensions/github/runners/repository_webhooks'
39
40
  require 'legion/extensions/github/client'
40
41
  require 'legion/extensions/github/cli/runner'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -203,6 +203,7 @@ files:
203
203
  - lib/legion/extensions/github/oauth/transport/exchanges/oauth.rb
204
204
  - lib/legion/extensions/github/oauth/transport/queues/auth.rb
205
205
  - lib/legion/extensions/github/runners/actions.rb
206
+ - lib/legion/extensions/github/runners/auth.rb
206
207
  - lib/legion/extensions/github/runners/branches.rb
207
208
  - lib/legion/extensions/github/runners/checks.rb
208
209
  - lib/legion/extensions/github/runners/comments.rb