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

badges / shields / 19457485593

16 Nov 2025 08:32PM UTC coverage: 98.15% (+0.04%) from 98.113%
19457485593

push

github

web-flow
Migrate [FlathubVersion] badge to v2 API (#11507)

* Migrate [FlathubVersion] badge to v2 API

* Rename to FlathubVersion

* Replace test with package name containing hyphens

5940 of 6202 branches covered (95.78%)

43 of 43 new or added lines in 1 file covered. (100.0%)

104 existing lines in 6 files now uncovered.

49861 of 50801 relevant lines covered (98.15%)

133.5 hits per line

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

53.55
/services/github/github-constellation.js
1
import { AuthHelper } from '../../core/base-service/auth-helper.js'
3✔
2
import SqlTokenPersistence from '../../core/token-pooling/sql-token-persistence.js'
3✔
3
import log from '../../core/server/log.js'
3✔
4
import GithubApiProvider from './github-api-provider.js'
3✔
5
import { setRoutes as setAcceptorRoutes } from './auth/acceptor.js'
3✔
6

3✔
7
// Convenience class with all the stuff related to the Github API and its
3✔
8
// authorization tokens, to simplify server initialization.
3✔
9
class GithubConstellation {
3✔
10
  static _createOauthHelper(config) {
3✔
11
    return new AuthHelper(
19✔
12
      {
19✔
13
        userKey: 'gh_client_id',
19✔
14
        passKey: 'gh_client_secret',
19✔
15
        authorizedOrigins: ['https://api.github.com'],
19✔
16
        isRequired: true,
19✔
17
      },
19✔
18
      config,
19✔
19
    )
19✔
20
  }
19✔
21

3✔
22
  constructor(config) {
3✔
23
    this._debugEnabled = config.service.debug.enabled
18✔
24
    this._debugIntervalSeconds = config.service.debug.intervalSeconds
18✔
25
    this._metricsIntervalSeconds = config.metricsIntervalSeconds
18✔
26

18✔
27
    let authType = GithubApiProvider.AUTH_TYPES.NO_AUTH
18✔
28

18✔
29
    const { postgres_url: pgUrl, gh_token: globalToken } = config.private
18✔
30
    if (pgUrl) {
18✔
31
      log.log('Github Token persistence configured with pgUrl')
10✔
32
      this.persistence = new SqlTokenPersistence({
10✔
33
        url: pgUrl,
10✔
34
        table: 'github_user_tokens',
10✔
35
      })
10✔
36
      authType = GithubApiProvider.AUTH_TYPES.TOKEN_POOL
10✔
37
    }
10✔
38

18✔
39
    if (globalToken) {
18✔
40
      authType = GithubApiProvider.AUTH_TYPES.GLOBAL_TOKEN
12✔
41
    }
12✔
42

18✔
43
    log.log(`Github using auth type: ${authType}`)
18✔
44

18✔
45
    this.apiProvider = new GithubApiProvider({
18✔
46
      baseUrl: config.service.baseUri,
18✔
47
      globalToken,
18✔
48
      authType,
18✔
49
      onTokenInvalidated: tokenString => this.onTokenInvalidated(tokenString),
18✔
50
      restApiVersion: config.service.restApiVersion,
18✔
51
    })
18✔
52

18✔
53
    this.oauthHelper = this.constructor._createOauthHelper(config)
18✔
54
  }
18✔
55

3✔
56
  scheduleDebugLogging() {
3✔
57
    if (this._debugEnabled) {
×
58
      this.debugInterval = setInterval(() => {
×
59
        const debugInfo = this.apiProvider.getTokenDebugInfo()
×
60
        log.log(debugInfo)
×
61
      }, 1000 * this._debugIntervalSeconds)
×
UNCOV
62
    }
×
UNCOV
63
  }
×
64

3✔
65
  scheduleMetricsCollection() {
3✔
UNCOV
66
    if (this.metricInstance) {
×
67
      this.metricsInterval = setInterval(() => {
×
68
        const debugInfo = this.apiProvider.getTokenDebugInfo()
×
69
        this.metricInstance.noteGithubTokenPoolMetrics(debugInfo)
×
70
      }, 1000 * this._metricsIntervalSeconds)
×
71
    }
×
72
  }
×
73

3✔
74
  async initialize(server, metricInstance) {
3✔
75
    if (this.apiProvider.authType !== GithubApiProvider.AUTH_TYPES.TOKEN_POOL) {
9✔
76
      return
9✔
77
    }
9✔
78

×
79
    this.metricInstance = metricInstance
×
80

×
81
    this.scheduleDebugLogging()
×
82
    this.scheduleMetricsCollection()
×
83

×
84
    if (!this.persistence) {
×
85
      return
×
86
    }
×
87

×
88
    let tokens = []
×
89
    try {
×
90
      tokens = await this.persistence.initialize()
×
91
    } catch (e) {
×
UNCOV
92
      log.error(e)
×
UNCOV
93
    }
×
UNCOV
94

×
95
    tokens.forEach(tokenString => {
×
96
      this.apiProvider.addToken(tokenString)
×
97
    })
×
98

×
99
    if (this.oauthHelper.isConfigured) {
×
100
      setAcceptorRoutes({
×
101
        server,
×
102
        authHelper: this.oauthHelper,
×
103
        onTokenAccepted: tokenString => this.onTokenAdded(tokenString),
×
104
      })
×
105
    }
×
106
  }
9✔
107

3✔
108
  onTokenAdded(tokenString) {
3✔
109
    if (!this.persistence) {
×
110
      throw Error('Token persistence is not configured')
×
111
    }
×
112
    this.apiProvider.addToken(tokenString)
×
113
    process.nextTick(async () => {
×
114
      try {
×
115
        await this.persistence.noteTokenAdded(tokenString)
×
116
      } catch (e) {
×
117
        log.error(e)
×
118
      }
×
UNCOV
119
    })
×
UNCOV
120
  }
×
121

3✔
122
  onTokenInvalidated(tokenString) {
3✔
123
    if (this.persistence) {
×
124
      process.nextTick(async () => {
×
UNCOV
125
        try {
×
UNCOV
126
          await this.persistence.noteTokenRemoved(tokenString)
×
UNCOV
127
        } catch (e) {
×
UNCOV
128
          log.error(e)
×
UNCOV
129
        }
×
130
      })
×
131
    }
×
UNCOV
132
  }
×
133

3✔
134
  async stop() {
3✔
135
    if (this.debugInterval) {
9!
UNCOV
136
      clearInterval(this.debugInterval)
×
UNCOV
137
      this.debugInterval = undefined
×
UNCOV
138
    }
×
139

9✔
140
    if (this.metricsInterval) {
9!
UNCOV
141
      clearInterval(this.metricsInterval)
×
UNCOV
142
      this.metricsInterval = undefined
×
UNCOV
143
    }
×
144

9✔
145
    if (this.persistence) {
9✔
146
      try {
8✔
147
        await this.persistence.stop()
8✔
148
      } catch (e) {
8!
UNCOV
149
        log.error(e)
×
UNCOV
150
      }
×
151
    }
8✔
152
  }
9✔
153
}
3✔
154

3✔
155
export default GithubConstellation
3✔
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