openvibers/openvibe.network Commits

Deploy drift and library tags await their GitHub token: unawaited, every call sent "Bearer [object Promise]" and GitHub answered 401 (#312)

OP OpenVibers committed 21 days ago · 2d17315b80 · 4 files, +23 −5

Changes

ddiff --git a/server/registry/deploy-drift.js b/server/registry/deploy-drift.js
iindex 0a24b3dc..b32ce3d2 100644
---- a/server/registry/deploy-drift.js
++++ b/server/registry/deploy-drift.js
@@@ -42,14 +42,17 @@ function driftSeconds(now = Date.now()) {
* services(): [{ id, release, repository }] for what runs now (the registry's releases view).
*/
function createDeployDrift({ services, fetchImpl = globalThis.fetch, token = () => process.env.GITHUB_TOKEN || '', intervalMs = 3600e3, now = () => Date.now(), log = console } = {}) {
-- const tokenNow = () => (typeof token === 'function' ? token() : token) || '';
++ // The token may come from an async source (server/index.js reads the integration's): awaited, or every call sent
++ // "Bearer [object Promise]" and GitHub answered 401 (from 2026-09-25 until 10-23).
++ const tokenNow = async () => String((await (typeof token === 'function' ? token() : token)) || '');
async function checkOne({ id, release, repository }) {
const at = new Date(now()).toISOString();
if (!SHA_RE.test(String(release || '')) || !REPO_RE.test(String(repository || ''))) { state.delete(id); return null; }
const prev = state.get(id);
try {
++ const auth = await tokenNow();
const res = await fetchImpl(`https://api.github.com/repos/${repository}/compare/${release}...main`, {
-- headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'OpenVibe.Network registry', ...(tokenNow() ? { Authorization: `Bearer ${tokenNow()}` } : {}) },
++ headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'OpenVibe.Network registry', ...(auth ? { Authorization: `Bearer ${auth}` } : {}) },
signal: AbortSignal.timeout(10000),
});
if (res.status === 404) { state.set(id, { repo: repository, deployed: release, state: 'unknown', error: 'commit not on GitHub', checked_at: at }); return state.get(id); }
ddiff --git a/server/registry/library-tags.js b/server/registry/library-tags.js
iindex 48a3cd61..1807d9d9 100644
---- a/server/registry/library-tags.js
++++ b/server/registry/library-tags.js
@@@ -21,14 +21,17 @@ function latestOf(names) {
}
function createLibraryTags({ fetchImpl = globalThis.fetch, token = () => process.env.GITHUB_TOKEN || '', intervalMs = 3600e3, onUpdate = null, log = console } = {}) {
-- const tokenNow = () => (typeof token === 'function' ? token() : token) || '';
++ // Awaited: server/index.js passes an async token function, and unawaited it went out as "Bearer [object Promise]"
++ // (GitHub's 401, so the registry kept the installed versions until 2026-10-23).
++ const tokenNow = async () => String((await (typeof token === 'function' ? token() : token)) || '');
const latest = new Map(); // package -> 'vX.Y.Z'
let timer = null;
async function refresh() {
++ const auth = await tokenNow().catch(() => '');
for (const [pkg, repo] of Object.entries(REPOS)) {
try {
const res = await fetchImpl(`https://api.github.com/repos/OpenVibers/${repo}/tags?per_page=100`, {
-- headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'OpenVibe.Network registry', ...(tokenNow() ? { Authorization: `Bearer ${tokenNow()}` } : {}) },
++ headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'OpenVibe.Network registry', ...(auth ? { Authorization: `Bearer ${auth}` } : {}) },
signal: AbortSignal.timeout(10000),
});
if (!res.ok) continue;
ddiff --git a/test/deploy-drift.test.js b/test/deploy-drift.test.js
iindex 97e2c333..2fcddbcd 100644
---- a/test/deploy-drift.test.js
++++ b/test/deploy-drift.test.js
@@@ -2,7 +2,7 @@
// Production drift (WS-S task 7): the deployed commit against main through GitHub's compare API —
// current, behind (how many commits and since the oldest undeployed one), diverged, unknown; a failed
// lookup keeps the last answer; the gauge gives seconds behind (0 when current); services that stop
--// running are dropped; a non-commit release is skipped.
++// running are dropped; a non-commit release is skipped; an async token is awaited.
const assert = require('assert');
const drift = require('../server/registry/deploy-drift');
@@@ -68,6 +68,14 @@ const fetchImpl = async (url, opts) => {
await d.refresh();
assert.strictEqual(drift.current('media'), null, 'a service that stopped running is dropped');
drift._reset();
++ // server/index.js passes an async token function: it is awaited, never sent as "[object Promise]" (GitHub's 401).
++ // No token at all: no Authorization header (anonymous, 60 an hour).
++ asked.length = 0;
++ await drift.createDeployDrift({ services: () => running.slice(0, 1), fetchImpl, token: async () => 'ghp_async', now: () => NOW, log: null }).refresh();
++ assert.strictEqual(asked[0].auth, 'Bearer ghp_async');
++ await drift.createDeployDrift({ services: () => running.slice(0, 1), fetchImpl, token: async () => null, now: () => NOW, log: null }).refresh();
++ assert.strictEqual(asked[1].auth, undefined);
++ drift._reset();
// server/index.js feeds the checks from the registry's releases view.
const eco = require('../server/registry/ecosystem').createEcosystemRegistry({ issuer: 'https://openvibe.network', fetchImpl: async () => { throw new Error('offline'); } });
assert.strictEqual(typeof eco.releases, 'function', 'the registry exposes releases()');
ddiff --git a/test/library-tags.test.js b/test/library-tags.test.js
iindex 9481beda..282be1a8 100644
---- a/test/library-tags.test.js
++++ b/test/library-tags.test.js
@@@ -21,5 +21,9 @@ assert.strictEqual(latestOf([]), null);
assert.strictEqual(libs['openvibe-sdk'].distribution, 'https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.8.0');
assert.strictEqual(libs['openvibe-shared'].release, 'v1.11.1');
assert.strictEqual(libs['openvibe-contracts'].release, `v${require('openvibe-contracts/package.json').version}`, 'a refused lookup keeps the installed version');
++ // An async token (server/index.js) is awaited, never sent as "[object Promise]".
++ const auths = [];
++ await createLibraryTags({ fetchImpl: async (url, opts) => { auths.push(opts.headers.Authorization); return fetchImpl(url); }, token: async () => 'ghp_async', log: null }).refresh();
++ assert.ok(auths.length && auths.every((a) => a === 'Bearer ghp_async'), auths.join(','));
console.log('library tags: all checks passed');
})().catch((e) => { console.error(e); process.exit(1); });