diff --git a/.dockerignore b/.dockerignore index e2727550..dc0c6d99 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ -**/node_modules_AAAA +**/node_modules Dockerfile .dockerignore .git @@ -9,4 +9,4 @@ docker-compose.* kind.* .eslintrc.js README.md -**/dist_AAAAA \ No newline at end of file +**/dist \ No newline at end of file diff --git a/.github/workflows/docker-prerelease.yaml b/.github/workflows/docker-prerelease.yaml index 4201e4fc..5e19ab45 100644 --- a/.github/workflows/docker-prerelease.yaml +++ b/.github/workflows/docker-prerelease.yaml @@ -44,7 +44,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: - platforms: 'amd64' + platforms: 'amd64,arm64' # Workaround: https://github.com/docker/build-push-action/issues/461 - name: Setup Docker buildx @@ -74,13 +74,13 @@ jobs: # https://github.com/docker/build-push-action - name: Build and push Docker image id: kubero-build-and-push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: true tags: ${{ steps.kubero-meta.outputs.tags }} build-args: VERSION=${{ inputs.version }} - platforms: linux/amd64 + platforms: linux/amd64,linux/arm64/v8 labels: ${{ steps.kubero-meta.outputs.labels }} # Sign the resulting Docker image digest except on PRs. diff --git a/.github/workflows/jest-codecov.yaml b/.github/workflows/jest-codecov.yaml new file mode 100644 index 00000000..d6b9719f --- /dev/null +++ b/.github/workflows/jest-codecov.yaml @@ -0,0 +1,28 @@ +name: 'Jest Codecov' +on: + workflow_dispatch: + push: + branches: + - main +defaults: + run: + working-directory: ./server +jobs: + codecov: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 # checkout the repo + - name: Install dependencies # install dependencies + run: yarn install --frozen-lockfile + - run: yarn build # install packages + - run: yarn test # run tests (configured to use jest-junit reporter) + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v5 + with: + directory: server/coverage + token: ${{ secrets.CODECOV_TOKEN }} + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/jest-pr.yaml b/.github/workflows/jest-pr.yaml new file mode 100644 index 00000000..d373388b --- /dev/null +++ b/.github/workflows/jest-pr.yaml @@ -0,0 +1,29 @@ +name: 'Jest PR Test' +on: + pull_request: + workflow_dispatch: +permissions: + pull-requests: write +defaults: + run: + working-directory: ./server +jobs: + build-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 # checkout the repo + - name: Install dependencies # install dependencies + run: yarn install --frozen-lockfile + - run: yarn build # install packages + - run: yarn test:ci # run tests (configured to use jest-junit reporter) + - name: Jest Coverage Comment + uses: MishaKav/jest-coverage-comment@main + with: + coverage-summary-path: server/coverage/coverage-summary.json + junitxml-path: server/reports/jest-junit.xml + - uses: actions/upload-artifact@v4 # upload test results + if: ${{ !cancelled() }} # run this step even if previous step failed + with: + name: test-results # Name of the check run which will be created + path: server/reports/jest-junit.xml + reporter: jest-junit # Format of test results \ No newline at end of file diff --git a/.github/workflows/jest-report.yaml b/.github/workflows/jest-report.yaml new file mode 100644 index 00000000..2fe61419 --- /dev/null +++ b/.github/workflows/jest-report.yaml @@ -0,0 +1,20 @@ +name: 'Jest Test Report' +on: + workflow_run: + workflows: ['Jest PR Test'] # runs after 'Jest PR Test' workflow + types: + - completed +permissions: + contents: read + actions: read + checks: write +jobs: + report: + runs-on: ubuntu-latest + steps: + - uses: dorny/test-reporter@v2 + with: + artifact: test-results # artifact name + name: JEST Tests # Name of the check run which will be created + path: '*.xml' # Path to test results (inside artifact .zip) + reporter: jest-junit # Format of test results \ No newline at end of file diff --git a/.github/workflows/stargazers.yaml b/.github/workflows/stargazers.yaml index d7662237..67858c98 100644 --- a/.github/workflows/stargazers.yaml +++ b/.github/workflows/stargazers.yaml @@ -8,14 +8,21 @@ jobs: name: 'stargazers' runs-on: ubuntu-latest steps: - - name: 💌 Send email, you star + - name: Send email uses: dawidd6/action-send-mail@v1.3.0 with: server_address: smtp.gmail.com server_port: 465 username: ${{ secrets.GMAIL_USER }} password: ${{ secrets.GMAIL_PASS }} - subject: Your a star ✨ - body: ${{ github.actor }} just starred your mail-on-star repo!!! ${{ github.repository }} + subject: ${{ github.event.repository.stargazers_count }} ✨ ${{ github.actor }} stared ${{ github.repository }} + body: | + ${{ github.actor }} just starred your mail-on-star repo!!! + ${{ github.event.repository.html_url }} + Forks: ${{ github.event.repository.forks_count }} + Stars: ${{ github.event.repository.stargazers_count }} + Issues: ${{ github.event.repository.open_issues_count }} + + ${{ github.repository }} to: ${{ secrets.GMAIL_ADDRESS }} from: ${{ secrets.GMAIL_ADDRESS }} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8db5f7b8..9a9e13ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,17 +13,22 @@ Willing to contribute something, but you don't know where to start? Have a look 5. Open a PR ## Techstack -**Infrastructure** -- [Kubernetes](https://kubernetes.io/) -- [Operator SDK](https://sdk.operatorframework.io/) -- [Helm (Operator)](https://helm.sh/) -- [Kind (Development)](https://kind.sigs.k8s.io/) - -**Code** -- [Express](https://expressjs.com/) -- [TypeScript](https://www.typescriptlang.org/) -- [Vue.js](https://vuejs.org/) -- [Vuetify](https://vuetifyjs.com/en/) +- Backend + - [NestJS](https://nestjs.com/) + - [TypeScript](https://www.typescriptlang.org/) + - [Jest](https://jestjs.io/) +- Frontend + - [Vue.js](https://vuejs.org/) + - [Vuetify](https://vuetifyjs.com/en/) +- CLI + - [Go](https://golang.org/) + - [Cobra](https://cobra.dev/) +- Operator + - [Operator SDK](https://sdk.operatorframework.io/) + - [Helm](https://helm.sh/) +- Infrastructure + - [Kubernetes](https://kubernetes.io/) + - [Kind (Development)](https://kind.sigs.k8s.io/) ## Development setup for the Kubero UI diff --git a/Dockerfile b/Dockerfile index 0ba5f3dc..8d6c0352 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,8 +8,7 @@ COPY server ./server RUN cd /build/server && \ yarn install RUN cd /build/server && \ - yarn build && \ - yarn swaggergen + yarn build ## Client COPY client ./client @@ -18,7 +17,7 @@ RUN cd /build/client && \ RUN cd /build/client && \ yarn build -FROM build AS release +FROM node:22-alpine AS release ARG VERSION=unknown LABEL maintainer='www.kubero.dev' @@ -30,13 +29,17 @@ WORKDIR /app/ COPY --from=build /build/server/dist /app/server COPY --from=build /build/server/package.json /app/server/package.json -COPY --from=build /build/server/src/modules/templates /app/server/modules/templates +COPY --from=build /build/server/src/deployments/templates /app/server/deployments/templates COPY --from=build /build/server/node_modules /app/server/node_modules -COPY --from=build /build/server/swagger.json /app/swagger.json +COPY server/prisma /app/server/prisma +# temporary fix for the public folder +COPY --from=build /build/server/dist/public /app/server/public +ENV DATABASE_URL=file:/app/server/db/kubero.sqlite +ENV DATABASE_TYPE=sqlite RUN echo -n $VERSION > /app/server/VERSION WORKDIR /app/server -CMD [ "node", "index.js" ] \ No newline at end of file +CMD [ "node", "main" ] \ No newline at end of file diff --git a/README.md b/README.md index 1d475c53..281d2d3b 100644 --- a/README.md +++ b/README.md @@ -10,29 +10,35 @@ Kubero [pronounced: Kube Hero] is a self-hosted PaaS (Platform as a Service) that allows any developer to deploy their application on Kubernetes without specialized knowledge. Kubero follows the principles of 12-factor apps. It is possible to run apps based on existing containers or from source code. +> [!NOTE] +> Kubero v3.0.0 is on the way! +> +> We're gearing up for the Kubero v3.0.0 release! 🎉 This major update features a rewritten backend, now powered by NestJS, bringing best practices and maintainability. + + ![](https://raw.githubusercontent.com/kubero-dev/docs/refs/heads/main/static/assets/screenshots/createapp.gif) More [Screenshots](https://www.kubero.dev/docs/screenshots) and a full video on [YouTube](https://www.youtube.com/watch?v=kmqhddc6UlI) ## Features ([DEMO](https://demo.kubero.dev)) -- **CI/CD Pipelines:** Create unlimited pipelines with up to 4 separate staging environments for all your applications. -- **GitOps Review Apps:** Automatically build, start, and clean up review apps when opening or closing pull requests. -- **Automatic Redeployments:** Trigger app redeployments on pushes to branches or tags. -- **Docker Deployments:** Deploy Docker containers on Kubernetes without needing Helm charts. -- **App Templates:** Deploy popular applications like WordPress and Grafana with ready-to-use templates. -- **Add-ons Integration:** Seamlessly deploy add-ons such as PostgreSQL and Redis alongside your applications. -- **API & CLI:** Integrate seamlessly with existing tools and CI/CD workflows. -- **Metrics & Monitoring:** Access integrated metrics to monitor application health. -- **Notifications:** Get build and deployment updates via Discord, Slack, or Webhooks. -- **Vulnerability Scans:** Perform scheduled or triggered scans for running applications. -- **Application Logs:** View logs directly from the web UI for easy monitoring. -- **Safe Restarts:** Restart applications safely and easily through the web UI. -- **Web Console:** Use the built-in container web console for direct access. -- **Scheduled Tasks:** Easily create and manage cronjobs. -- **Multi-Tenancy:** Support for managing multiple tenants. -- **Single Sign-On (SSO):** Authenticate securely with GitHub and OAuth2. -- **Basic Auth:** Configure Basic Auth for your applications with ease. +- **Docker Deployments**
Deploy Docker containers on Kubernetes without needing Helm charts. +- **App Templates (+160)**
Deploy popular applications like WordPress and Grafana with ready-to-use [templates](https://www.kubero.dev/templates/). +- **CI/CD Pipelines**
Create unlimited pipelines with up to 4 separate staging environments for all your applications. +- **GitOps Review Apps**
Automatically build, start, and clean up review apps when opening or closing pull requests. +- **Automatic Redeployments**
Trigger app redeployments on pushes to branches or tags. +- **Add-ons Integration**
Seamlessly deploy add-ons such as PostgreSQL and Redis alongside your applications. +- **API & CLI**
Integrate seamlessly with existing tools and CI/CD workflows. +- **Metrics & Monitoring**
Access integrated metrics to monitor application health. +- **Notifications**
Get build and deployment updates via Discord, Slack, or Webhooks. +- **Vulnerability Scans**
Perform scheduled or triggered scans for running applications. +- **Application Logs**
View logs directly from the web UI for easy monitoring. +- **Safe Restarts**
Restart applications safely and easily through the web UI. +- **Web Console**
Use the built-in container web console for direct access. +- **Scheduled Tasks**
Easily create and manage cronjobs. +- **Multi-Tenancy**
Support for managing multiple tenants. +- **Single Sign-On (SSO)**
Authenticate securely with GitHub and OAuth2. +- **Basic Auth**
Configure Basic Auth for your applications with ease. ## Basic Concept @@ -129,11 +135,28 @@ Basically *everything* that can be packaged in a single container can be deploye Kubero starts now building your app. Once the build is complete, Kubero will launch the final container and make it accessible via the configured domain. -## Documentation -https://www.kubero.dev/docs/quickstart - -## Roadmap -https://github.com/orgs/kubero-dev/projects/1/views/3 +## Techstack + +- Backend + - [NestJS](https://nestjs.com/) + - [TypeScript](https://www.typescriptlang.org/) + - [Jest](https://jestjs.io/) +- Frontend + - [Vue.js](https://vuejs.org/) + - [Vuetify](https://vuetifyjs.com/en/) +- CLI + - [Go](https://golang.org/) + - [Cobra](https://cobra.dev/) +- Operator + - [Operator SDK](https://sdk.operatorframework.io/) + - [Helm](https://helm.sh/) +- Infrastructure + - [Kubernetes](https://kubernetes.io/) + - [Kind (Development)](https://kind.sigs.k8s.io/) + +## Links +- Documentation https://www.kubero.dev/docs/ +- Roadmap https://github.com/orgs/kubero-dev/projects/1/views/3 ## Community [![kubero Discord server Banner](https://discordapp.com/api/guilds/1051249947472826408/widget.png?style=banner2)](https://discord.gg/tafRPMWS4r) diff --git a/SECURITY.md b/SECURITY.md index e7b33dd4..66751aaa 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,6 +5,7 @@ | Version | Supported | | ------- | ------------------ | | 2.X.X | :white_check_mark: | +| 2.X.X | EOL 31.03.2025 | | 1.X.X | EOL 28.09.2024 | | 0.X.X | | diff --git a/client/package.json b/client/package.json index 5ef8a6b4..4026014c 100644 --- a/client/package.json +++ b/client/package.json @@ -3,8 +3,8 @@ "private": true, "license": "GPL-3.0", "scripts": { - "dev": "vite", - "watch": "vue-tsc --noEmit && vite build --watch", + "run": "vite", + "dev": "vue-tsc --noEmit && vite build --watch", "build": "vue-tsc --noEmit && vite build", "preview": "vite preview", "lint": "eslint . --fix --ignore-path .gitignore" @@ -16,6 +16,7 @@ "axios": "^1.7.4", "chart.js": "^4.4.1", "core-js": "^3.29.0", + "jwt-decode": "^4.0.0", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "pinia": "^2.1.7", @@ -24,6 +25,7 @@ "sweetalert2": "^11.10.2", "vue": "^3.4.0", "vue-chartjs": "^5.3.1", + "vue-i18n": "11", "vue-router": "^4.2.0", "vue-socket.io-extended": "^4.2.0", "vue3-apexcharts": "^1.5.2", @@ -44,8 +46,8 @@ "sass": "^1.60.0", "typescript": "^5.0.0", "unplugin-fonts": "^1.0.3", - "vite": "^5.1.8", - "vite-plugin-vuetify": "^1.0.0", - "vue-tsc": "^2.1.0" + "vite": "^6.3.4", + "vite-plugin-vuetify": "^2.1.1", + "vue-tsc": "^2.2.10" } } diff --git a/client/public/img/icons/avatar.svg b/client/public/img/icons/avatar.svg new file mode 100644 index 00000000..8dfad577 --- /dev/null +++ b/client/public/img/icons/avatar.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/src/components/accounts/index.vue b/client/src/components/accounts/index.vue new file mode 100644 index 00000000..7f6610dd --- /dev/null +++ b/client/src/components/accounts/index.vue @@ -0,0 +1,46 @@ + + + diff --git a/client/src/components/accounts/roles.vue b/client/src/components/accounts/roles.vue new file mode 100644 index 00000000..8846476c --- /dev/null +++ b/client/src/components/accounts/roles.vue @@ -0,0 +1,567 @@ + + + diff --git a/client/src/components/accounts/teams.vue b/client/src/components/accounts/teams.vue new file mode 100644 index 00000000..0b74208d --- /dev/null +++ b/client/src/components/accounts/teams.vue @@ -0,0 +1,232 @@ + + + diff --git a/client/src/components/accounts/tokens.vue b/client/src/components/accounts/tokens.vue new file mode 100644 index 00000000..13bc7856 --- /dev/null +++ b/client/src/components/accounts/tokens.vue @@ -0,0 +1,178 @@ + + + diff --git a/client/src/components/accounts/users.vue b/client/src/components/accounts/users.vue new file mode 100644 index 00000000..a426dbc0 --- /dev/null +++ b/client/src/components/accounts/users.vue @@ -0,0 +1,475 @@ + + + \ No newline at end of file diff --git a/client/src/components/activity/view.vue b/client/src/components/activity/view.vue index 0c78e8ad..3efa386e 100644 --- a/client/src/components/activity/view.vue +++ b/client/src/components/activity/view.vue @@ -1,6 +1,6 @@ + :disabled="!authStore.hasPermission('app:write')" + :title="$t('app.actions.edit')"> + :title="$t('app.actions.openApp')"> + :disabled="!authStore.hasPermission('reboot:ok')" + :title="$t('app.actions.restart')"> + :title="$t('app.actions.downloadTemplate')"> + :disabled="!kubero.consoleEnabled || !authStore.hasPermission('console:ok')" + :title="$t('app.actions.openConsole')"> + :disabled="!authStore.hasPermission('app:write')" + :title="$t('app.actions.delete')"> @@ -99,9 +102,17 @@ import Vulnerabilities from "./vulnerabilities.vue"; import Swal from 'sweetalert2'; import { useKuberoStore } from '../../stores/kubero' import { mapState } from 'pinia' +import { useAuthStore } from '../../stores/auth' +const authStore = useAuthStore(); export default defineComponent({ + name: 'AppDetail', + setup() { + return { + authStore, + } + }, data () { return { loadingState: false, @@ -160,7 +171,7 @@ export default defineComponent({ }); }, loadApp() { - axios.get('/api/pipelines/'+this.pipeline+'/'+this.phase+'/'+this.app).then(response => { + axios.get('/api/apps/'+this.pipeline+'/'+this.phase+'/'+this.app).then(response => { this.appData = response.data; //console.log(this.appData); }); @@ -172,7 +183,7 @@ export default defineComponent({ this.$router.push(`/pipeline/${this.pipeline}/${this.phase}/apps/${this.app}`); }, ActionStartDownload() { - axios.get('/api/pipelines/'+this.pipeline+'/'+this.phase+'/'+this.app+'/download').then(response => { + axios.get('/api/apps/'+this.pipeline+'/'+this.phase+'/'+this.app+'/download').then(response => { //console.log(response.data); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); @@ -197,7 +208,7 @@ export default defineComponent({ }) .then((result) => { if (result.isConfirmed) { - axios.delete(`/api/pipelines/${this.pipeline}/${this.phase}/${this.app}`) + axios.delete(`/api/apps/${this.pipeline}/${this.phase}/${this.app}`) .then(response => { // sleep 1 second setTimeout(() => { @@ -213,7 +224,7 @@ export default defineComponent({ }); }, async restartApp() { - axios.get(`/api/pipelines/${this.pipeline}/${this.phase}/${this.app}/restart`) + axios.get(`/api/apps/${this.pipeline}/${this.phase}/${this.app}/restart`) .then(response => { //console.log(response); this.loadingState = true; diff --git a/client/src/components/apps/events.vue b/client/src/components/apps/events.vue index 67998405..759f59c4 100644 --- a/client/src/components/apps/events.vue +++ b/client/src/components/apps/events.vue @@ -1,10 +1,5 @@