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

Move from github.com/feloy/devfile-builder #6937

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
21 changes: 21 additions & 0 deletions .github/workflows/ui-e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: e2e
feloy marked this conversation as resolved.
Show resolved Hide resolved
on:
pull_request:
branches:
- main
paths:
- 'ui'
- '.github/workflows/ui-e2e.yaml'

jobs:
cypress-run:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cypress run
uses: cypress-io/github-action@v5
with:
working-directory: ui
start: npm start
wait-on: 'npx wait-on --timeout 180000 http://0.0.0.0:4200'
2 changes: 1 addition & 1 deletion .ibm/pipelines/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ skip_if_only() {
}

skip() {
SKIP_IF_ONLY="docs/ CONTRIBUTING.md OWNERS README.md USAGE_DATA.md scripts/ .github/ .threatmodel/"
SKIP_IF_ONLY="docs/ CONTRIBUTING.md OWNERS README.md USAGE_DATA.md scripts/ .github/ .threatmodel/ ui/"
change=$1
for skip in ${SKIP_IF_ONLY}; do
if [[ "${change}" == "${skip}"* ]]; then
Expand Down
2 changes: 1 addition & 1 deletion scripts/check-gofmt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# - ignore files in certain directories, like 'vendor' or 'dist' (created when building RPM Packages of odo)
# - gofmt doesn't exit with error code when there are errors

GO_FILES=$(find . \( -path ./vendor -o -path ./dist -o -path ./.ibm/tools/tests-results/vendor \) -prune -o -name '*.go' -print)
GO_FILES=$(find . \( -path ./vendor -o -path ./dist -o -path ./.ibm/tools/tests-results/vendor -o -path ./ui/wasm/vendor \) -prune -o -name '*.go' -print)

for file in $GO_FILES; do
gofmtOutput=$(gofmt -l "$file")
Expand Down
46 changes: 46 additions & 0 deletions ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

# Compiled output
/dist
/tmp
/out-tsc
/bazel-out

# Node
/node_modules
npm-debug.log
yarn-error.log

# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*

# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings

# System files
.DS_Store
Thumbs.db

/cypress/videos

.odo
12 changes: 12 additions & 0 deletions ui/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
build-wasm:
( \
cd wasm/ && \
GOOS=js GOARCH=wasm go build -o ../src/assets/devfile.wasm && \
HASH=$$(md5sum ../src/assets/devfile.wasm | awk '{ print $$1 }') && \
echo $${HASH} && \
mv ../src/assets/devfile.wasm ../src/assets/devfile.$${HASH}.wasm && \
sed -i "s/devfile\.[a-z0-9]*\.wasm/devfile\.$${HASH}.wasm/" ../src/app/app.module.ts \
rm3l marked this conversation as resolved.
Show resolved Hide resolved
)

deploy:
npm run deploy
36 changes: 36 additions & 0 deletions ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Devfile Builder

Devfile Builder is a tool to help users edit and create Devfile (https://devfile.io).

## Development with Devfile

Run `odo dev --platform podman` from this directory to start a development session.

## Development (generic, from Angular documentation)

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.2.2.

### Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.

### Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

### Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.

### Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

### Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

### Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

106 changes: 106 additions & 0 deletions ui/angular.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"devfile-builder": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/devfile-builder",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/CNAME",
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": [
"src/assets/wasm_exec.js"
]
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "1500kb",
"maximumError": "2mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "devfile-builder:build:production"
},
"development": {
"browserTarget": "devfile-builder:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "devfile-builder:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": []
}
},
"deploy": {
"builder": "angular-cli-ghpages:deploy"
}
}
}
}
}
11 changes: 11 additions & 0 deletions ui/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from "cypress";

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
viewportWidth: 1080,
viewportHeight: 660,
});
8 changes: 8 additions & 0 deletions ui/cypress/e2e/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const TAB_YAML = 0;
export const TAB_CHART = 1;
export const TAB_METADATA = 2;
export const TAB_COMMANDS = 3;
export const TAB_VOLUMES = 4;
export const TAB_CONTAINERS = 5;
export const TAB_IMAGES = 6;
export const TAB_RESOURCES = 7;
133 changes: 133 additions & 0 deletions ui/cypress/e2e/errs.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { TAB_COMMANDS, TAB_CONTAINERS, TAB_IMAGES, TAB_RESOURCES } from "./consts";

describe('devfile editor errors handling', () => {

it('fails when YAML is not valid', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.setDevfile("wrong yaml content");
cy.getByDataCy("yaml-error").should('contain.text', 'error parsing devfile YAML');
});

it('fails when adding a container with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-container.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_CONTAINERS);
cy.getByDataCy('add').click();
cy.getByDataCy('container-name').type('container1');
cy.getByDataCy('container-image').type('an-image');
cy.getByDataCy('container-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`container1 already exists`)
});
});

it('fails when adding an image with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-container.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_IMAGES);
cy.getByDataCy('image-name').type('container1');
cy.getByDataCy('image-image-name').type('an-image-name');
cy.getByDataCy('image-build-context').type('/path/to/build/context');
cy.getByDataCy('image-dockerfile-uri').type('/path/to/dockerfile');
cy.getByDataCy('image-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`container1 already exists`)
});
});

it('fails when adding a resource with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-container.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_RESOURCES);
cy.getByDataCy('resource-name').type('container1');
cy.getByDataCy('resource-toggle-inlined').click();
cy.getByDataCy('resource-manifest').type('a-resource-manifest');
cy.getByDataCy('resource-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`container1 already exists`)
});
});

it('fails when adding an exec command with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-exec-command.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_COMMANDS);
cy.getByDataCy('add').click();
cy.getByDataCy('new-command-exec').click();

cy.getByDataCy('command-exec-name').type('command1');
cy.getByDataCy('command-exec-command-line').type('a-cmdline');
cy.getByDataCy('command-exec-working-dir').type('/path/to/working/dir');
cy.getByDataCy('select-container').click().get('mat-option').contains('container1').click();
cy.getByDataCy('command-exec-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`command1 already exists`)
});
});

it('fails when adding an apply command with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-apply-command.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_COMMANDS);
cy.getByDataCy('add').click();
cy.getByDataCy('new-command-apply').click();

cy.getByDataCy('command-apply-name').type('command1');
cy.getByDataCy('select-container').click().get('mat-option').contains('resource1').click();
cy.getByDataCy('command-apply-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`command1 already exists`)
});
});

it('fails when adding an image command with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-image-command.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_COMMANDS);
cy.getByDataCy('add').click();
cy.getByDataCy('new-command-image').click();

cy.getByDataCy('command-image-name').type('command1');
cy.getByDataCy('select-container').click().get('mat-option').contains('image1').click();
cy.getByDataCy('command-image-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`command1 already exists`)
});
});

it('fails when adding a composite command with an already used name', () => {
cy.visit('http://localhost:4200');
cy.clearDevfile();
cy.fixture('input/with-image-command.yaml').then(yaml => {
cy.setDevfile(yaml);
});
cy.selectTab(TAB_COMMANDS);
cy.getByDataCy('add').click();
cy.getByDataCy('new-command-composite').click();

cy.getByDataCy('command-composite-name').type('command1');
cy.getByDataCy('command-composite-create').click();
cy.on('window:alert', (str) => {
expect(str).to.contain(`command1 already exists`)
});
});
});
Loading