• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

astronomer / astro-cli / 49762f05-7c9b-4bc2-ad5b-90283f076e72

20 Mar 2026 10:25PM UTC coverage: 36.028% (+0.2%) from 35.862%
49762f05-7c9b-4bc2-ad5b-90283f076e72

Pull #2042

circleci

kaxil
Add `astro api registry` command for querying the Airflow Provider Registry

Ports the `af registry` CLI from astronomer/agents to the astro-cli,
giving users access to the public Airflow Provider Registry
(https://airflow.apache.org/registry) without leaving the astro CLI.

New subcommands:
  astro api registry providers              - list all providers
  astro api registry modules <provider>     - list operators/hooks/sensors
  astro api registry parameters <provider>  - show constructor parameters
  astro api registry connections <provider>  - show connection types

Supports --version/-v to pin a provider version, --jq/-q and
--template/-t for output filtering, --registry-url to override the
base URL (also ASTRO_REGISTRY_URL env), and --no-cache to bypass
the file-based cache (~/.astro/.registry_cache/).
Pull Request #2042: Add `astro api registry` command

190 of 213 new or added lines in 3 files covered. (89.2%)

19 existing lines in 1 file now uncovered.

24422 of 67787 relevant lines covered (36.03%)

8.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/cmd/api/registry_cache.go
1
package api
2

3
import (
4
        "crypto/sha256"
5
        "encoding/json"
6
        "fmt"
7
        "os"
8
        "path/filepath"
9
        "time"
10

11
        "github.com/astronomer/astro-cli/config"
12
)
13

14
const (
15
        registryCacheDirName = ".registry_cache"
16
        latestCacheTTL       = 1 * time.Hour
17
        versionedCacheTTL    = 30 * 24 * time.Hour // 30 days
18
)
19

20
// registryCacheEntry is the on-disk format for cached registry responses.
21
type registryCacheEntry struct {
22
        CachedAt int64           `json:"_cached_at"`
23
        URL      string          `json:"_url"` // stored for debugging; not validated on read
24
        Payload  json.RawMessage `json:"_payload"`
25
}
26

27
// registryCacheDir returns the path to the registry cache directory.
28
func registryCacheDir() string {
15✔
29
        return filepath.Join(config.HomeConfigPath, registryCacheDirName)
15✔
30
}
15✔
31

32
// registryCacheKey returns the SHA-256 hex digest of the URL, used as the cache filename.
33
func registryCacheKey(url string) string {
17✔
34
        return fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
17✔
35
}
17✔
36

37
// readRegistryCache returns the cached payload for the given URL if it exists
38
// and has not expired. Expired entries are removed from disk. Returns nil, false
39
// on miss, expiry, or corruption.
40
func readRegistryCache(url string, ttl time.Duration) ([]byte, bool) {
9✔
41
        path := filepath.Join(registryCacheDir(), registryCacheKey(url))
9✔
42
        data, err := os.ReadFile(path)
9✔
43
        if err != nil {
11✔
44
                return nil, false
2✔
45
        }
2✔
46

47
        var entry registryCacheEntry
7✔
48
        if err := json.Unmarshal(data, &entry); err != nil {
8✔
49
                // Corrupt entry — remove it.
1✔
50
                _ = os.Remove(path)
1✔
51
                return nil, false
1✔
52
        }
1✔
53

54
        cachedAt := time.Unix(entry.CachedAt, 0)
6✔
55
        if time.Since(cachedAt) > ttl {
8✔
56
                _ = os.Remove(path)
2✔
57
                return nil, false
2✔
58
        }
2✔
59

60
        return entry.Payload, true
4✔
61
}
62

63
// writeRegistryCache writes the payload to the cache. Errors are silently ignored.
64
func writeRegistryCache(url string, payload []byte) {
3✔
65
        dir := registryCacheDir()
3✔
66
        if err := os.MkdirAll(dir, 0o755); err != nil {
3✔
NEW
67
                return
×
NEW
68
        }
×
69

70
        entry := registryCacheEntry{
3✔
71
                CachedAt: time.Now().Unix(),
3✔
72
                URL:      url,
3✔
73
                Payload:  payload,
3✔
74
        }
3✔
75
        data, err := json.Marshal(entry)
3✔
76
        if err != nil {
3✔
NEW
77
                return
×
NEW
78
        }
×
79

80
        path := filepath.Join(dir, registryCacheKey(url))
3✔
81
        _ = os.WriteFile(path, data, 0o644)
3✔
82
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc