Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR check for vscode-extensions.json fields #625

Merged
merged 1 commit into from
Sep 23, 2020
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
18 changes: 18 additions & 0 deletions .ci/vscode-extensions-field-validation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
# Copyright (c) 2020 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# Red Hat, Inc. - initial API and implementation

set -e
set -o pipefail

yarn
cd ./tools/pr-check
yarn run compile
node ./lib/pr-check.js validate-vscode-extensions.json-fields
31 changes: 31 additions & 0 deletions .github/workflows/vscode-extensions-pr-check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#
# Copyright (c) 2020 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#

name: vscode-extension.json field validation

on:
pull_request:
paths:
- 'vscode-extensions.json'

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/setup-node@v1
with:
node-version: '12'
- name: Clone source code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Check fields and verify validity
run: |
./.ci/vscode-extensions-field-validation.sh
121 changes: 116 additions & 5 deletions tools/pr-check/src/pr-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,43 @@
import * as fs from 'fs-extra';
import * as glob from 'glob';
import * as jsyaml from 'js-yaml';

import * as path from 'path';
import Axios from 'axios';
import simpleGit, { SimpleGit } from 'simple-git';

const EXTENSION_ROOT_DIR = '/tmp/extension_repository';

export interface Extension {
// Object matching each entry in vscode-extensions.json
export interface VSCodeExtensionEntry {
repository: string;
revision: string;
directory?: string;
sidecar?: {
image: string;
source: {
repository: string;
revision?: string;
directory?: string;
};
};
}

export interface VSCodeExtension {
repository: string;
revision: string;
sidecar?: {
image: string;
source: {
repository: string;
revision?: string;
directory?: string;
};
};
error: boolean;
errorMessages: string[];
}

export interface MetaYamlExtension {
name?: string;
version?: string;
icon?: string;
Expand All @@ -25,13 +58,88 @@ export interface Extension {

const metaYamlFiles = glob.sync('./../../v3/plugins/**/*.yaml');

async function vscodeExtensionsFieldValidation() {
const { extensions } = JSON.parse(await fs.readFile('./../../vscode-extensions.json', 'utf-8'));
const vsCodeExtensions: VSCodeExtension[] = await Promise.all(
extensions.map(
async (extensionEntry: VSCodeExtensionEntry): Promise<VSCodeExtension> => {
let vscodeExtension: VSCodeExtension = {
repository: extensionEntry.repository,
revision: extensionEntry.revision,
error: false,
errorMessages: [],
};
const git: SimpleGit = simpleGit();
let extensionRepoValid = true;

// Check repository validity before cloning and checking out revision
try {
await Axios.head(vscodeExtension.repository);
} catch (err) {
// Sometimes valid repos return 400, even though they are clone-able
if (!err || !err.response) {
extensionRepoValid = false;
vscodeExtension.error = true;
vscodeExtension.errorMessages.push(`Error cloning extension repository ${vscodeExtension.repository}`);
}
if (err.response && err.response.status == 404) {
extensionRepoValid = false;
vscodeExtension.error = true;
vscodeExtension.errorMessages.push(`Extension repository ${vscodeExtension.repository} is not valid (response: 404)`);
}
}
// If the repository is valid, proceed with the clone and checkout the revision
if (extensionRepoValid) {
const cloneName = extensionEntry.repository.replace(/[^\w\s]/gi, '');
const clonePath = path.resolve(EXTENSION_ROOT_DIR, cloneName);
await git.clone(vscodeExtension.repository, clonePath);
try {
await simpleGit(clonePath).checkout(vscodeExtension.revision);
} catch (err) {
vscodeExtension.error = true;
vscodeExtension.errorMessages.push(`Error checking out revision ${vscodeExtension.revision} for ${vscodeExtension.repository}`);
}
await fs.remove(clonePath);
}

if (extensionEntry.sidecar) {
vscodeExtension.sidecar = extensionEntry.sidecar;
try {
await Axios.head(vscodeExtension.sidecar.source.repository);
} catch (err) {
vscodeExtension.error = true;
vscodeExtension.errorMessages.push(`Sidecar repository ${vscodeExtension.sidecar.source.repository} is not valid`);
}
}
return vscodeExtension;
}
)
);
// Clean up any cloned paths
await fs.remove(EXTENSION_ROOT_DIR)

// Check for errors, print them, and exit with code 1 if there are any
let errors = vsCodeExtensions.filter((extension) => {
if (extension.error) {
extension.errorMessages.forEach((error: string) => {
console.error(error)
});
return true;
}
return false;
});
if (errors && errors.length > 0) {
process.exit(1);
}
}

async function iconsExtensions404Check() {
const extensions: Extension[] = await Promise.all(
const extensions: MetaYamlExtension[] = await Promise.all(
metaYamlFiles.map(
async (metaYamlFile: string): Promise<Extension> => {
async (metaYamlFile: string): Promise<MetaYamlExtension> => {
let metaYaml = await fs.readFile(metaYamlFile, 'utf-8');
let metaYamlString;
let extension: Extension = {
let extension: MetaYamlExtension = {
error: false,
};
try {
Expand Down Expand Up @@ -107,6 +215,9 @@ async function iconsExtensions404Check() {
case 'icons-extensions-404':
await iconsExtensions404Check();
break;
case 'validate-vscode-extensions.json-fields':
await vscodeExtensionsFieldValidation();
break;
case 'all':
default:
await iconsExtensions404Check();
Expand Down