Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,52 @@ jobs:
run: |
npm run collect-assets -- --use-release

- name: Verify runtime assets downloaded
working-directory: ./.upstream-workspace
run: |
echo "🔍 Verifying required runtime assets..."
MISSING=0

# Language extension provider binaries (must be bundled — no runtime fallback)
for provider in java-external-provider generic-external-provider golang-dependency-provider c-sharp-analyzer-provider; do
DIR="downloaded_assets/${provider}"
if [[ ! -d "$DIR" ]] || [[ -z "$(ls -A "$DIR" 2>/dev/null)" ]]; then
echo "❌ Missing required provider binary: ${provider}"
MISSING=$((MISSING + 1))
else
COUNT=$(find "$DIR" -type f | wc -l)
echo "✅ ${provider}: ${COUNT} files"
fi
done

# Seed assets
for asset in rulesets jdtls-bundles opensource-labels-file; do
DIR="downloaded_assets/${asset}"
if [[ ! -d "$DIR" ]] || [[ -z "$(ls -A "$DIR" 2>/dev/null)" ]]; then
echo "⚠️ Missing seed asset: ${asset}"
else
echo "✅ ${asset}: present"
fi
done

# kai binary is optional (core uses fallbackAssets for runtime download)
KAI_DIR="downloaded_assets/kai"
if [[ -d "$KAI_DIR" ]] && [[ -n "$(ls -A "$KAI_DIR" 2>/dev/null)" ]]; then
echo "✅ kai: present (will be bundled)"
else
echo "ℹ️ kai: not bundled (core extension uses fallbackAssets for runtime download)"
fi

if [[ $MISSING -gt 0 ]]; then
echo ""
echo "❌ ${MISSING} required provider binaries are missing."
echo "❌ Language extensions will not function without these binaries."
exit 1
fi

echo ""
echo "✅ All required runtime assets verified"

- name: Set version for build
working-directory: ./.upstream-workspace
run: |
Expand Down
2 changes: 1 addition & 1 deletion mta-build.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
upstream:
repository: konveyor/editor-extensions
ref: 504c825dd15f415ae0282fec44274b8bcbb577ea
ref: a87decba30735b514cdaca456760460511d10b9c
semanticRef: release-0.4
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mta-vscode-extension-builder",
"version": "8.0.0",
"version": "8.1.0",
"private": true,
"description": "Build orchestrator for MTA VSCode extension based on release-0.2",
"scripts": {
Expand Down
24 changes: 11 additions & 13 deletions scripts/postbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,13 @@ function check(condition, errorMsg) {
return true;
}

// ─── Version Updates ────────────────────────────────────────────────────────
// ─── Version Verification ────────────────────────────────────────────────────
// Version is set by prebuild.js (before webpack) so EXTENSION_VERSION constants
// are baked correctly at compile time. Here we just verify it stuck.

console.log(`📝 Updating all package.json versions to ${extensionVersion}...`);
console.log(`📝 Verifying version ${extensionVersion} across workspaces...`);

const workspaces = [
"package.json",
"extra-types/package.json",
"shared/package.json",
"webview-ui/package.json",
"agentic/package.json",
"vscode/core/package.json",
"vscode/java/package.json",
"vscode/javascript/package.json",
Expand All @@ -67,13 +64,14 @@ for (const ws of workspaces) {
const fullPath = path.join(__dirname, "..", ws);
if (fs.existsSync(fullPath)) {
const pkg = JSON.parse(fs.readFileSync(fullPath, "utf8"));
pkg.version = extensionVersion;
fs.writeFileSync(fullPath, JSON.stringify(pkg, null, 2));
console.log(` ✅ Updated ${ws}`);
check(
pkg.version === extensionVersion,
`${ws} version: expected "${extensionVersion}", got "${pkg.version}"`,
);
}
}

console.log("📝 Version updates complete!\n");
console.log("📝 Version verification complete!\n");

// ─── Core Extension Verification ────────────────────────────────────────────

Expand Down Expand Up @@ -177,8 +175,8 @@ if (corePkg.fallbackAssets) {
warnings.push(`Only ${assetCount} platforms in fallback assets (expected 6)`);
}
check(
corePkg.fallbackAssets.sha256sumFile === "sha256sum.txt",
`sha256sumFile: expected "sha256sum.txt", got "${corePkg.fallbackAssets.sha256sumFile}"`,
corePkg.fallbackAssets.sha256sumFile === "SHA256SUM",
`sha256sumFile: expected "SHA256SUM", got "${corePkg.fallbackAssets.sha256sumFile}"`,
);
} else {
warnings.push("No fallback assets configuration found on core extension");
Expand Down
103 changes: 89 additions & 14 deletions scripts/prebuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ export const shortName = "MTA";
export const repositoryUrl = "https://github.com/migtools/editor-extensions";
export const bugsUrl = "https://github.com/migtools/editor-extensions/issues";
export const homepageUrl = "https://developers.redhat.com/products/mta/overview";
// export const fallbackAssetsUrl = "https://developers.redhat.com/content-gateway/rest/browse/pub/mta/8.0.1/"
export const fallbackAssetsUrl = "https://download.devel.redhat.com/devel/candidates/middleware/migrationtoolkit/MTA-8.1.0.CR2/"

// ─── TEMPORARY PRE-RELEASE ASSET HANDLING ───────────────────────────────────
// TODO: REMOVE THIS SECTION WHEN MTA 8.1.0 GOES GA AND ASSETS ARE PUBLIC
// Currently using CR2 (candidate release) which requires VPN access
const isPreRelease = fallbackAssetsUrl.includes('candidates') || fallbackAssetsUrl.includes('CR');
// ─────────────────────────────────────────────────────────────────────────────

// Extension name mapping: upstream → downstream
const NAME_MAP = {
Expand Down Expand Up @@ -207,10 +215,26 @@ function brandCoreExtension(pkg) {
}));
}

// Remove kai from includedAssetPaths (runtime download via fallback)
if (pkg.includedAssetPaths?.kai !== undefined) {
delete pkg.includedAssetPaths.kai;
console.log(" ✅ Removed kai binary assets from package (runtime download enabled)");
// Asset management strategy for production vs pre-release builds
if (isPreRelease && pkg.includedAssetPaths?.kai !== undefined) {
// Pre-release builds: Keep assets bundled to avoid VPN requirements
console.log(" 📦 Keeping kai binary assets bundled (pre-release build)");
console.log(" 🚨 Pre-release mode: Assets bundled to avoid VPN requirement at runtime");
} else if (!isPreRelease && pkg.includedAssetPaths?.kai !== undefined) {
// Production builds: Fail hard if dev assets are still bundled
console.error(" ❌ PRODUCTION BUILD ERROR: Dev assets still bundled!");
console.error(" ❌ Found bundled kai assets in production build");
console.error(" ❌ This would ship dev/internal assets to end users");
console.error(" 💡 Solution: Remove kai assets from upstream package.json");
console.error(" or verify fallbackAssetsUrl points to public release");
process.exit(1);
} else if (!isPreRelease) {
// Production builds: Assets removed, runtime download enabled
console.log(" ✅ No bundled assets (runtime download from public servers)");
} else {
// Pre-release but no assets found
console.log(" ⚠️ Pre-release mode but no kai assets found");
console.log(" ⚠️ Extension may fail at runtime without bundled or downloadable assets");
}

return pkg;
Expand Down Expand Up @@ -333,8 +357,7 @@ function transformSourceCode() {
async function generateFallbackAssets(pkg) {
console.log(" 🔧 Generating fallback assets configuration...");

const FALLBACK_ASSETS_URL =
"https://developers.redhat.com/content-gateway/rest/browse/pub/mta/8.0.0/";
const FALLBACK_ASSETS_URL = fallbackAssetsUrl;

const PLATFORM_MAPPING = {
"linux-x64": "linux-amd64",
Expand All @@ -357,18 +380,24 @@ async function generateFallbackAssets(pkg) {
try {
console.log(` Fetching from: ${FALLBACK_ASSETS_URL}`);

// Verify sha256sum.txt exists
console.log(" 🔍 Verifying sha256sum.txt exists...");
// Verify SHA256SUM exists
console.log(" 🔍 Verifying SHA256SUM exists...");
try {
const sha256Response = await fetchText(`${FALLBACK_ASSETS_URL}sha256sum.txt`);
const sha256Response = await fetchText(`${FALLBACK_ASSETS_URL}SHA256SUM`);
if (!sha256Response || sha256Response.trim().length === 0) {
throw new Error("sha256sum.txt is empty");
throw new Error("SHA256SUM is empty");
}
console.log(" ✅ sha256sum.txt found and not empty");
console.log(" ✅ SHA256SUM found and not empty");
} catch (sha256Error) {
console.error(` ❌ Failed to fetch sha256sum.txt: ${sha256Error.message}`);
if (isPreRelease) {
console.warn(` ⚠️ Failed to fetch SHA256SUM: ${sha256Error.message}`);
console.warn(" ⚠️ Pre-release build: skipping fallback assets (server unreachable)");
console.warn(" 📦 Assets are bundled, so runtime downloads are not required");
return pkg;
}
console.error(` ❌ Failed to fetch SHA256SUM: ${sha256Error.message}`);
console.error(
" ❌ Build failed: sha256sum.txt is required for secure asset downloads",
" ❌ Build failed: SHA256SUM is required for secure asset downloads",
);
process.exit(1);
}
Expand Down Expand Up @@ -430,14 +459,20 @@ async function generateFallbackAssets(pkg) {

pkg.fallbackAssets = {
baseUrl: FALLBACK_ASSETS_URL,
sha256sumFile: "sha256sum.txt",
sha256sumFile: "SHA256SUM",
assets,
};

console.log(
` ✅ Generated fallback assets for ${Object.keys(assets).length} platforms`,
);
} catch (error) {
if (isPreRelease) {
console.warn(` ⚠️ Failed to generate fallback assets: ${error.message}`);
console.warn(" ⚠️ Pre-release build: skipping fallback assets (server unreachable)");
console.warn(" 📦 Assets are bundled, so runtime downloads are not required");
return pkg;
}
console.error(` ❌ Failed to generate fallback assets: ${error.message}`);
console.error(
" ❌ Build failed: fallback assets are required for extension functionality",
Expand Down Expand Up @@ -498,6 +533,46 @@ const isDirectExecution =
if (isDirectExecution) {
console.log("🔄 Running MTA prebuild for multi-extension architecture...\n");

// Show loud warning for pre-release builds
if (isPreRelease) {
console.log("🚨🚨🚨 PRE-RELEASE BUILD DETECTED 🚨🚨🚨");
console.log(" Using candidate release assets that require VPN access:");
console.log(` ${fallbackAssetsUrl}`);
console.log(" Assets will be BUNDLED to avoid runtime download failures");
console.log(" 📝 TODO: Update to GA URL when MTA 8.1.0 is officially released:");
console.log(" https://developers.redhat.com/content-gateway/rest/browse/pub/mta/8.1.0/");
console.log("🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨\n");
}

// 0. Set version across all workspaces BEFORE webpack runs
// This ensures webpack's DefinePlugin bakes the correct MTA version
// into EXTENSION_VERSION constants at compile time.
console.log(`📝 Setting version ${extensionVersion} across all workspaces...`);
const workspacePaths = [
"package.json",
"extra-types/package.json",
"shared/package.json",
"webview-ui/package.json",
"agentic/package.json",
"vscode/core/package.json",
"vscode/java/package.json",
"vscode/javascript/package.json",
"vscode/go/package.json",
"vscode/csharp/package.json",
"vscode/konveyor/package.json",
];

for (const ws of workspacePaths) {
const fullPath = path.join(__dirname, "..", ws);
if (fs.existsSync(fullPath)) {
const pkg = JSON.parse(fs.readFileSync(fullPath, "utf8"));
pkg.version = extensionVersion;
fs.writeFileSync(fullPath, JSON.stringify(pkg, null, 2));
console.log(` ✅ ${ws}`);
}
}
console.log("");

// 1. Transform core extension
console.log("📦 Branding core extension (vscode/core)...");
let corePkg = readPackageJson("vscode/core/package.json");
Expand Down
Loading