ask-github 0.1.3 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f0e1e42270acf35d49dbe2b9ddacde65159b7aacc9812ec6936e663c32063e9
4
- data.tar.gz: 95ab525daa2236b18f8eacf1bcf6ff1d9159a3616a2c2b0337575a57c29d7be0
3
+ metadata.gz: bd64129291b95815da38080f42a150a158ce4f9bfc154b243ad237c209bcd21c
4
+ data.tar.gz: 9a61c3deae1d9e1902e3c8cb379f1c17c44c6c58ddf9bed24fab10ad7da907bc
5
5
  SHA512:
6
- metadata.gz: 93d4c3b6bcc51abdb61b6d2a088cf14184ccd8e6eb53a8bd7bf833611fb13cb6b5fb234568f4843aec0216feedffc7e9e6ffc1966552ce9d2c41c0be4d25ec31
7
- data.tar.gz: e157ba7fe7bc3565eaca177cf26e5d46cbf96fee8fac978c2313c1efce784d703e2c2b8a4f78359826992e0387e127c6a623ee44bd1b157570a93a27678df45f
6
+ metadata.gz: 9a4e4598c8a7e4924b21d9fb4030c052b2efdb280dcee3c614515e59cf651f896a7320c5fc27d22c9af6509ce3c05c723606c37fe3b3e1a981f19489a8062239
7
+ data.tar.gz: d4d55c62f888a877a31c8b8fcc8523a5e073d5b4ec3f26d12f4936bd3bf3bd373b61bbd0b75aada7842bdbf60a031f8b38e3a1292adca5920a88faa7482f3748
data/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@
4
4
  - Gemspec validation test. Infrastructure: rubocop, overcommit, bin/setup, CI matrix. VCR rake tasks for cassette freshness.
5
5
  # Changelog
6
6
 
7
+ ## [0.2.0] - 2026-08-16
8
+
9
+ ### Added
10
+
11
+ - **client.rb** — `Ask::GitHub.client(token: nil)` accepts an explicit token (the connector path; token resolution still falls back to `Ask::Auth.resolve(:github_token)`).
12
+ - **Content helpers** — `default_branch(repo)`, `tree(repo, branch:)`, `file(repo, path, branch:)`, and `license(repo)` for docs-as-code sources; 401s map to `Ask::Auth::InvalidCredential` like every other call.
13
+
14
+
7
15
  ## [0.1.2] - 2026-06-21
8
16
 
9
17
  ### Added
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # ask-github
2
2
 
3
- GitHub service context for AI agents in the ask-rb ecosystem.
3
+ [![Gem Version](https://badge.fury.io/rb/ask-github.svg)](https://badge.fury.io/rb/ask-github)
4
4
 
5
- Provides an authenticated Octokit client, metadata constants for system prompts, and a structured error guide for common GitHub API issues.
5
+ GitHub service context for AI agents in the ask-rb ecosystem. It provides an
6
+ authenticated Octokit client for the GitHub REST API, metadata constants for
7
+ system prompts, and a structured error guide for common GitHub API issues.
8
+
9
+ ## Installation
6
10
 
7
11
  ```ruby
8
12
  gem "ask-github"
@@ -10,8 +14,6 @@ gem "ask-github"
10
14
 
11
15
  ## Quick Start
12
16
 
13
- ### Get an authenticated client
14
-
15
17
  ```ruby
16
18
  require "ask-github"
17
19
 
@@ -23,47 +25,42 @@ client.contents("owner/repo", path: "Gemfile")
23
25
  client.search_issues("query")
24
26
  ```
25
27
 
26
- The client is an `Octokit::Client` wrapped in a proxy that converts `Octokit::Unauthorized` into `Ask::Auth::InvalidCredential` with actionable error messages.
27
-
28
- ### Authentication
29
-
30
- The client resolves a GitHub token via `Ask::Auth.resolve(:github_token)`. Tokens can be provided through any configured auth provider:
31
-
32
- 1. **Environment variable:** `GITHUB_TOKEN`
33
- 2. **Credentials file:** `~/.ask/credentials.yml`
34
- 3. **Rails credentials:** `Rails.application.credentials.github_token`
35
- 4. **OAuth / Database:** Custom providers
28
+ ## Authentication
36
29
 
37
- Generate a token at [github.com/settings/tokens](https://github.com/settings/tokens) with the `repo` and `read:org` scopes.
30
+ `Ask::GitHub.client` resolves a token via `Ask::Auth.resolve(:github_token)`.
31
+ Set it in your environment:
38
32
 
39
- ## Context Constants
33
+ ```bash
34
+ export GITHUB_TOKEN=your_token_here
35
+ ```
40
36
 
41
- Use these constants to build system prompts for AI agents:
37
+ Or add it to `~/.ask/credentials.yml`:
42
38
 
43
- | Constant | Value |
44
- |---|---|
45
- | `Ask::GitHub::DESCRIPTION` | "GitHub — code hosting, issues, pull requests, actions, packages" |
46
- | `Ask::GitHub::DOCS_URL` | https://docs.github.com/en/rest |
47
- | `Ask::GitHub::OPENAPI_URL` | https://api.github.com/openapi.json |
48
- | `Ask::GitHub::AUTH_NAME` | `:github_token` |
49
- | `Ask::GitHub::GEM_NAME` | `"octokit"` |
50
- | `Ask::GitHub::GEM_VERSION` | `"~> 9.0"` |
51
- | `Ask::GitHub::QUICK_START` | Copy-paste Ruby code snippet |
39
+ ```yaml
40
+ github_token: your_token_here
41
+ ```
52
42
 
53
- ## Error Guide
43
+ Credentials can also come from Rails credentials, a database, or an OAuth
44
+ provider, depending on your `ask-auth` configuration. Generate a token at
45
+ [github.com/settings/tokens](https://github.com/settings/tokens) with the
46
+ `repo` and `read:org` scopes.
54
47
 
55
- `Ask::GitHub::Errors` provides structured knowledge for agents:
48
+ ## Key entry points
56
49
 
57
- ```ruby
58
- Ask::GitHub::Errors.for("Octokit::NotFound")
59
- # => { message: "...", action: "..." }
50
+ - `Ask::GitHub.client` - an authenticated `Octokit::Client` (auto-paginating,
51
+ `per_page: 100`, retry middleware). It is wrapped in a proxy that converts
52
+ `Octokit::Unauthorized` into `Ask::Auth::InvalidCredential`.
53
+ - `Ask::GitHub::Errors` - structured error knowledge for agents: guidance by
54
+ exception class, HTTP status code descriptions, and rate limit info.
55
+ - `Ask::GitHub::DESCRIPTION`, `DOCS_URL`, `AUTH_NAME`, `GEM_NAME`,
56
+ `GEM_VERSION`, and `QUICK_START` - metadata constants for system prompts.
60
57
 
61
- Ask::GitHub::Errors.status_code_description(404)
62
- # => "Not Found — Resource does not exist or is private."
58
+ ## Full documentation
63
59
 
64
- Ask::GitHub::Errors::RATE_LIMIT[:authenticated]
65
- # => "5,000 requests per hour"
66
- ```
60
+ The full ask-rb documentation lives at https://ask-rb.github.io/ask-docs.
61
+ [Services: GitHub](https://ask-rb.github.io/ask-docs/services/github) covers
62
+ ask-github in depth, including the client, error guide, and constants.
63
+ API reference: https://ask-rb.github.io/ask-docs/reference/api.
67
64
 
68
65
  ## Development
69
66
 
@@ -5,27 +5,36 @@ require "ask/auth"
5
5
 
6
6
  module Ask
7
7
  module GitHub
8
- # Returns an authenticated Octokit client configured for an AI agent.
8
+ # Returns an authenticated Octokit client configured for an AI agent
9
+ # or a content connector.
9
10
  #
10
- # Resolves the GitHub token via +Ask::Auth.resolve(:github_token)+ and
11
- # configures the client with sensible defaults:
11
+ # Resolves the GitHub token via +Ask::Auth.resolve(:github_token)+,
12
+ # or uses the +token:+ given explicitly (the connector path — the
13
+ # token comes from the host app's own credential store). Configures
14
+ # the client with sensible defaults:
12
15
  #
13
16
  # - +auto_paginate+: +true+ (collects all pages automatically)
14
17
  # - +per_page+: +100+ (maximum items per page)
15
18
  # - +middleware+: Faraday retry middleware (3 retries, exponential backoff)
16
19
  #
17
20
  # The client is wrapped in a +ClientProxy+ that converts
18
- # +Octokit::Unauthorized+ into +Ask::Auth::InvalidCredential+.
21
+ # +Octokit::Unauthorized+ into +Ask::Auth::InvalidCredential+, and
22
+ # exposes the repo-content helpers (+default_branch+, +tree+, +file+,
23
+ # +license+) for docs-as-code sources.
19
24
  #
20
25
  # @example
21
26
  # client = Ask::GitHub.client
22
27
  # client.issues("owner/repo")
23
28
  #
24
- # @return [Octokit::Client] an authenticated client
29
+ # @example connector with an explicit token
30
+ # client = Ask::GitHub.client(token: credential.token)
31
+ # client.default_branch("owner/repo")
32
+ #
33
+ # @return [ClientProxy] an authenticated client
25
34
  # @raise [Ask::Auth::MissingCredential] if no GitHub token is configured
26
35
  # @raise [Ask::Auth::InvalidCredential] if the token is rejected (401)
27
- def self.client
28
- token = Ask::Auth.resolve(:github_token)
36
+ def self.client(token: nil)
37
+ token ||= Ask::Auth.resolve(:github_token)
29
38
 
30
39
  client = Octokit::Client.new(access_token: token, auto_paginate: true, per_page: 100)
31
40
 
@@ -39,11 +48,78 @@ module Ask
39
48
  ClientProxy.new(client)
40
49
  end
41
50
 
42
- # Proxies method calls to an +Octokit::Client+, converting authentication
43
- # errors into +Ask::Auth::InvalidCredential+.
51
+ # The repo-content helpers: the raw pieces a docs-as-code connector
52
+ # needs (tree listing, raw file reads, the default branch, and the
53
+ # repo's license). Explicit methods, so connectors never poke at
54
+ # Octokit's full surface.
55
+ class Content
56
+ def initialize(client)
57
+ @client = client
58
+ end
59
+
60
+ # The repository's default branch name (e.g. "main").
61
+ def default_branch(repo)
62
+ call { @client.repo(repo).default_branch }
63
+ end
64
+
65
+ # The recursive file tree for a branch: [{path:, type:}] entries.
66
+ # GitHub truncates enormous trees; callers bound what they consume.
67
+ def tree(repo, branch: nil)
68
+ sha = branch || default_branch(repo)
69
+ call { @client.tree(repo, sha, recursive: true) }.tree.map do |entry|
70
+ {path: entry.path, type: entry.type}
71
+ end
72
+ end
73
+
74
+ # A file's raw content at a path, or nil when the path doesn't exist.
75
+ def file(repo, path, branch: nil)
76
+ call do
77
+ @client.contents(repo, path: path, ref: branch || default_branch(repo),
78
+ accept: "application/vnd.github.raw")
79
+ end
80
+ rescue ::Octokit::NotFound
81
+ nil
82
+ end
83
+
84
+ # The repo's SPDX license id (e.g. "mit"), or nil when unlicensed.
85
+ def license(repo)
86
+ call { @client.license(repo) }&.license&.spdx_id
87
+ rescue ::Octokit::NotFound
88
+ nil
89
+ end
90
+
91
+ private
92
+
93
+ def call
94
+ yield
95
+ rescue ::Octokit::Unauthorized
96
+ ::Kernel.raise ::Ask::Auth::InvalidCredential, :github_token
97
+ end
98
+ end
99
+
100
+ # Proxies method calls to an +Octokit::Client+, converting
101
+ # authentication errors into +Ask::Auth::InvalidCredential+, and
102
+ # exposing the content helpers.
44
103
  class ClientProxy < BasicObject
45
104
  def initialize(client)
46
105
  @client = client
106
+ @content = ::Ask::GitHub::Content.new(client)
107
+ end
108
+
109
+ def default_branch(repo)
110
+ @content.default_branch(repo)
111
+ end
112
+
113
+ def tree(repo, branch: nil)
114
+ @content.tree(repo, branch: branch)
115
+ end
116
+
117
+ def file(repo, path, branch: nil)
118
+ @content.file(repo, path, branch: branch)
119
+ end
120
+
121
+ def license(repo)
122
+ @content.license(repo)
47
123
  end
48
124
 
49
125
  def method_missing(name, ...)
@@ -52,9 +128,13 @@ module Ask
52
128
  ::Kernel.raise ::Ask::Auth::InvalidCredential, :github_token
53
129
  end
54
130
 
55
- def respond_to_missing?(name, include_private = false)
56
- @client.respond_to?(name, include_private) || super
131
+ # BasicObject has no +respond_to?+ — report the content helpers
132
+ # explicitly, forward everything else to the wrapped client.
133
+ def respond_to?(name, include_private = false)
134
+ CONTENT_METHODS.include?(name) || @client.respond_to?(name, include_private)
57
135
  end
136
+
137
+ CONTENT_METHODS = %i[default_branch tree file license].freeze
58
138
  end
59
139
  end
60
140
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module GitHub
5
- VERSION = "0.1.3"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0.1'
18
+ version: 0.3.2
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '0.1'
25
+ version: 0.3.2
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: octokit
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -160,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  - !ruby/object:Gem::Version
161
161
  version: '0'
162
162
  requirements: []
163
- rubygems_version: 4.0.3
163
+ rubygems_version: 4.0.18
164
164
  specification_version: 4
165
165
  summary: GitHub service context for the ask-rb ecosystem
166
166
  test_files: []