@versatil/sdlc-framework
Version:
🚀 AI-Native SDLC framework with 11-MCP ecosystem, RAG memory, OPERA orchestration, and 6 specialized agents achieving ZERO CONTEXT LOSS. Features complete CI/CD pipeline with 7 GitHub workflows (MCP testing, security scanning, performance benchmarking),
261 lines • 9.23 kB
JavaScript
/**
* VERSATIL SDLC Framework - GitHub Release Checker
* Fetch and parse GitHub releases for framework updates
*/
import { parseVersion, compareVersions } from './semantic-version.js';
export class GitHubReleaseError extends Error {
constructor(message) {
super(message);
this.name = 'GitHubReleaseError';
}
}
export class GitHubReleaseChecker {
constructor(repoOwner = 'MiraclesGIT', repoName = 'versatil-sdlc-framework') {
this.apiBase = 'https://api.github.com';
this.cache = new Map();
this.cacheTTL = 60 * 60 * 1000; // 1 hour
this.repoOwner = repoOwner;
this.repoName = repoName;
}
/**
* Get latest release from GitHub
*/
async getLatestRelease(includePrerelease = false) {
const cacheKey = `latest-${includePrerelease}`;
// Check cache first
const cached = this.getFromCache(cacheKey);
if (cached) {
return cached;
}
try {
const url = `${this.apiBase}/repos/${this.repoOwner}/${this.repoName}/releases/latest`;
const response = await fetch(url, {
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'VERSATIL-SDLC-Framework'
}
});
if (!response.ok) {
if (response.status === 404) {
throw new GitHubReleaseError('No releases found for this repository');
}
throw new GitHubReleaseError(`GitHub API error: ${response.status} ${response.statusText}`);
}
const release = await response.json();
// If we don't want prereleases and this is one, get all releases
if (!includePrerelease && release.prerelease) {
return this.getLatestStableRelease();
}
const releaseInfo = this.parseRelease(release);
this.setCache(cacheKey, releaseInfo);
return releaseInfo;
}
catch (error) {
if (error instanceof GitHubReleaseError) {
throw error;
}
throw new GitHubReleaseError(`Failed to fetch releases: ${error.message}`);
}
}
/**
* Get latest stable (non-prerelease) release
*/
async getLatestStableRelease() {
const url = `${this.apiBase}/repos/${this.repoOwner}/${this.repoName}/releases`;
const response = await fetch(url, {
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'VERSATIL-SDLC-Framework'
}
});
if (!response.ok) {
throw new GitHubReleaseError(`GitHub API error: ${response.status} ${response.statusText}`);
}
const releases = await response.json();
// Find first non-prerelease
const stableRelease = releases.find((r) => !r.prerelease && !r.draft);
if (!stableRelease) {
throw new GitHubReleaseError('No stable releases found');
}
return this.parseRelease(stableRelease);
}
/**
* Parse GitHub release response
*/
parseRelease(release) {
return {
version: release.tag_name.replace(/^v/, ''),
tagName: release.tag_name,
publishedAt: release.published_at,
changelog: release.body || 'No changelog available',
releaseNotes: release.body || 'No release notes available',
downloadUrl: release.tarball_url,
assets: release.assets ? release.assets.map((asset) => ({
name: asset.name,
browser_download_url: asset.browser_download_url,
size: asset.size,
content_type: asset.content_type
})) : [],
prerelease: release.prerelease || false,
draft: release.draft || false
};
}
/**
* Check if update is available
*/
async checkForUpdate(currentVersion, includePrerelease = false) {
try {
const latestRelease = await this.getLatestRelease(includePrerelease);
const latestVersion = latestRelease.version;
const comparison = compareVersions(latestVersion, currentVersion);
if (comparison > 0) {
// Newer version available
const currentParsed = parseVersion(currentVersion);
const latestParsed = parseVersion(latestVersion);
let updateType = 'patch';
if (latestParsed.major > currentParsed.major) {
updateType = 'major';
}
else if (latestParsed.minor > currentParsed.minor) {
updateType = 'minor';
}
return {
hasUpdate: true,
currentVersion,
latestVersion,
releaseInfo: latestRelease,
updateType
};
}
// Up to date
return {
hasUpdate: false,
currentVersion,
latestVersion
};
}
catch (error) {
// If update check fails (offline, rate limit, etc.), return no update
// Don't throw error to prevent blocking normal operations
return {
hasUpdate: false,
currentVersion,
latestVersion: currentVersion
};
}
}
/**
* Get all releases
*/
async getAllReleases(limit = 10) {
try {
const url = `${this.apiBase}/repos/${this.repoOwner}/${this.repoName}/releases?per_page=${limit}`;
const response = await fetch(url, {
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'VERSATIL-SDLC-Framework'
}
});
if (!response.ok) {
throw new GitHubReleaseError(`GitHub API error: ${response.status} ${response.statusText}`);
}
const releases = await response.json();
return releases.map((r) => this.parseRelease(r));
}
catch (error) {
if (error instanceof GitHubReleaseError) {
throw error;
}
throw new GitHubReleaseError(`Failed to fetch releases: ${error.message}`);
}
}
/**
* Get specific release by tag
*/
async getReleaseByTag(tag) {
try {
const url = `${this.apiBase}/repos/${this.repoOwner}/${this.repoName}/releases/tags/${tag}`;
const response = await fetch(url, {
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'VERSATIL-SDLC-Framework'
}
});
if (!response.ok) {
if (response.status === 404) {
throw new GitHubReleaseError(`Release not found: ${tag}`);
}
throw new GitHubReleaseError(`GitHub API error: ${response.status} ${response.statusText}`);
}
const release = await response.json();
return this.parseRelease(release);
}
catch (error) {
if (error instanceof GitHubReleaseError) {
throw error;
}
throw new GitHubReleaseError(`Failed to fetch release: ${error.message}`);
}
}
/**
* Get release by version
*/
async getReleaseByVersion(version) {
try {
// Try with 'v' prefix
const tag = version.startsWith('v') ? version : `v${version}`;
return await this.getReleaseByTag(tag);
}
catch (error) {
return null;
}
}
/**
* Get releases between two versions
*/
async getReleasesBetween(fromVersion, toVersion) {
const releases = await this.getAllReleases(100);
const filtered = [];
for (const release of releases) {
const comparison = compareVersions(release.version, fromVersion);
if (comparison > 0 && compareVersions(release.version, toVersion) <= 0) {
filtered.push(release);
}
}
return filtered.sort((a, b) => compareVersions(b.version, a.version));
}
/**
* Clear cache
*/
clearCache() {
this.cache.clear();
}
/**
* Get from cache if not expired
*/
getFromCache(key) {
const cached = this.cache.get(key);
if (!cached)
return null;
const now = Date.now();
if (now - cached.timestamp > this.cacheTTL) {
this.cache.delete(key);
return null;
}
return cached.data;
}
/**
* Set cache
*/
setCache(key, data) {
this.cache.set(key, {
data,
timestamp: Date.now()
});
}
}
/**
* Default instance for convenience
*/
export const defaultReleaseChecker = new GitHubReleaseChecker();
//# sourceMappingURL=github-release-checker.js.map