Before you start - you need a local instance of the unikube cluster.
After that setup the frontend as follows:
npm install
The unikube frontend projects is mostly written with Vue, TypeScript and SASS.
Notable packages used:
Create a file called .env.development.local
(and adapt according to your cluster):
VUE_APP_UPLOAD_URL=http://gateway.unikube.127.0.0.1.nip.io:8085/upload
VUE_APP_GRAPHQL_URL=http://gateway.unikube.127.0.0.1.nip.io:8085/graphql
VUE_APP_KEYCLOAK_JS=/js/keycloak.js
VUE_APP_KEYCLOAK_AUTHZ_JS=/js/keycloak-authz.js
VUE_APP_KEYCLOAK_URL=http://keycloak.127.0.0.1.nip.io:8085/auth
VUE_APP_KEYCLOAK_REALM=unikube
VUE_APP_KEYCLOAK_CLIENT_ID=frontend
Compiles and hot-reloads for development
npm run serve
Compiles and minifies for production
npm run build
Run your unit tests
Unit tests are written with Jest and Jasmine.
npm run test:unit
Run your end-to-end tests
This command starts integration testing with Cypress. Cypress runs through different views and imitates user workflows.
npm run test:e2e
# or
npm run test:e2e:ci # for CI
Lints and fixes files
npm run lint
Authentication as well as authorization happens via Keycloak. To make sure a user is authenticated before entering the frontend application it (the VueJS app) is wrapped into a "Keycloak validation".
If everything is fine - the application is initialized with all its plugins. Unauthenticated users will be redirected onto the Keycloak authentication page.
The Keycloak auth token is updated as soon as it is valid for less than 30 seconds.
Unikube makes heavy use of GraphQL between frontend and multiple microservices. To perform queries we're leveraging Apollo with vue-apollo.
For enhanced type-safety we're converting the GraphQL schema provided by the API-Gateway into TypeScript types/enums/interfaces. With a local cluster the TypeScript definitions can be updated via the following command.
npm run codegen
This command is provided by the GraphQL-Code-Generator.
The configuration can be found in codegen.yml
.
It is extended by a custom command (npm run kindify
) which extends
the GraphQL converted nodes (TypeScript types then) by a field kind
. The command
is called as part of an afterOneFileWrite
hook configured in codegen.yml
.
This field contains an identifier which then is used by CASL to determine
what kind of object it deals with when it comes to permissions.
The automatically generated types are stored within generated/graphql.ts
.
We're using CASL to handle frontend permissions.
The auth.ts
vuex store module converts information from the Keycloak
RPT token into CASL permissions.
CASL is neatly integrated with Vue in this project. Therefore, it is possible to create a permission-based reactive frontend. Meaning as soon as the (rpt) token for the frontend's requests gets updated the frontend rerenders based on the updated permissions. Tokens usually have a short lifetime.
import { TProjectNode } from './graphql';
export default class ProjectList extends Vue {
get projects() {
this.projectList.filter((project: TProjectNode) => {
this.$can('view', project)
})
}
}
The example above may not be needed in a real case, since the backend
will probably not return any TProjectNode
objects which are not viewable
for the user.
The versioning system used for this project is semantic versioning.
We're using release-it
and
auto-changelog
for an automated release workflow.
Depending on the kind of release (patch, minor, major) you would like to create run the following command:
npm run release patch
The command:
The creation of the tag triggers a job which builds a new Docker image containing the frontend application, which then is served by NGINX.
On a new release a Docker image is automatically created and pushed to quay.
There are 2 versions of the image - production and development.
The development, which image is used for local development with Unikube,
is tagged with a -dev
suffix.
For every release 2 new tags are created, based on the version e.g. 1.0.0 and 1.0.0-dev.
Furthermore the latest
and latest-dev
tag are bumped to the latest
release.