diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml new file mode 100644 index 0000000..f139667 --- /dev/null +++ b/.github/workflows/releaser.yml @@ -0,0 +1,67 @@ +name: Chart Release + +on: + push: + branches: + - master + +env: + CR_CONFIGFILE: "${{ github.workspace }}/cr.yaml" + CR_TOOL_PATH: "${{ github.workspace }}/.cr-tool" + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + TARGET_BRANCH: "${{ github.ref_name }}" + +jobs: + setup: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@v4 + + - name: Prepare GPG key #this step is for using exported keys and make your github runner + run: | + gpg_dir=.cr-gpg + mkdir "$gpg_dir" + keyring="$gpg_dir/secring.gpg" #referring keyring to private key of gpg + base64 -d <<< "$GPG_KEYRING_BASE64" > "$keyring" #storing base64 GPG key into keyring + passphrase_file="$gpg_dir/passphrase" + echo "$GPG_PASSPHRASE" > "$passphrase_file" #storing passphrase data into a file + echo "CR_PASSPHRASE_FILE=$passphrase_file" >> "$GITHUB_ENV" #saving passphrase into github-environment + echo "CR_KEYRING=$keyring" >> "$GITHUB_ENV" #saving private key into github-environemnt + env: + GPG_KEYRING_BASE64: "${{ secrets.GPG_KEYRING_BASE64 }}" #Referring secrets of github above + GPG_PASSPHRASE: "${{ secrets.GPG_PASSPHRASE }}" + + - name: Rename Chart + if: github.ref_name != 'master' + run: | + flatBranchName=$(echo "${{ env.TARGET_BRANCH }}" | sed 's/\//\-/g') + + sed -i "s/name: plane-ce/name: plane-ce-${flatBranchName}/" charts/plane-ce/Chart.yaml + sed -i "s/name: plane-enterprise/name: plane-enterprise-${flatBranchName}/" charts/plane-enterprise/Chart.yaml + + - name: Release Charts + uses: helm/chart-releaser-action@v1.6.0 + with: + charts_dir: charts + config: cr.yaml + packages_with_index: false + skip_existing: true + env: + CR_TOKEN: ${{ env.CR_TOKEN }} + CR_KEY: "Plane" + CR_KEYRING: ${{ env.CR_KEYRING }} + CR_PASSPHRASE_FILE: ${{ env.CR_PASSPHRASE_FILE }} + CR_SIGN: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a4745c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +dist/ +test-helm.yaml +.DS_Store +*/local-values.yaml +test.yaml +test-*.yaml diff --git a/artifacthub-repo.yml b/artifacthub-repo.yml new file mode 100644 index 0000000..db1fca9 --- /dev/null +++ b/artifacthub-repo.yml @@ -0,0 +1,16 @@ +# Artifact Hub repository metadata file +# +# Some settings like the verified publisher flag or the ignored packages won't +# be applied until the next time the repository is processed. Please keep in +# mind that the repository won't be processed if it has not changed since the +# last time it was processed. Depending on the repository kind, this is checked +# in a different way. For Helm http based repositories, we consider it has +# changed if the `index.yaml` file changes. For git based repositories, it does +# when the hash of the last commit in the branch you set up changes. This does +# NOT apply to ownership claim operations, which are processed immediately. +# +repositoryID: 1f012931-5011-4f86-bd8e-c0ef4f819ace + +ignore: + - name: plane-ce + version: develop diff --git a/charts/plane-ce/.helmignore b/charts/plane-ce/.helmignore new file mode 100644 index 0000000..2d4a744 --- /dev/null +++ b/charts/plane-ce/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +test-*.yaml \ No newline at end of file diff --git a/charts/plane-ce/Chart.lock b/charts/plane-ce/Chart.lock new file mode 100644 index 0000000..e69de29 diff --git a/charts/plane-ce/Chart.yaml b/charts/plane-ce/Chart.yaml new file mode 100644 index 0000000..3ccdcf7 --- /dev/null +++ b/charts/plane-ce/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 + +name: plane-ce +description: Meet Plane. An open-source software development tool to manage issues, sprints, and product roadmaps with peace of mind. + +type: application + +version: 1.0.18 +appVersion: "0.20.0" + +home: https://plane.so +icon: https://plane.so/favicon/favicon-32x32.png +sources: + - https://github.com/makeplane/plane + +annotations: + artifacthub.io/license: AGPL-3.0 diff --git a/charts/plane-ce/README.md b/charts/plane-ce/README.md new file mode 100644 index 0000000..a6204d8 --- /dev/null +++ b/charts/plane-ce/README.md @@ -0,0 +1,130 @@ +### Plane Helm Setup +--- + +Follow below steps to setup **Plane** + +Add Helm Repo +``` +helm repo add makeplane https://helm.plane.so/ +``` + +You must refer the configuration variables before proceeding. This can be done by running the below command or visiting **Configuration** tab. +``` +helm show values plane-ce --repo https://helm.plane.so +``` + + +Basic Install +``` +helm install \ + --create-namespace \ + --namespace plane-ns \ + --set ingress.appHost="plane.example.com" \ + --set ingress.minioHost="plane-minio.example.com" \ + my-plane makeplane/plane-ce +``` + +Customise Remote Postgress URL +``` + --set postgres.local_setup=false \ + --set env.pgdb_remote_url="postgress://[username]:[password]@[pg-host]/[db-name]" \ +``` + +Customise Remote Redis URL +``` + --set redis.local_setup=false \ + --set env.remote_redis_url="redis://[redis-host]:[6379]" \ +``` + +Customise Document Store - Change from Minio to AWS S3 +``` + --set minio.local_setup=false \ + --set env.aws_access_key="xxxxxxx" \ + --set env.aws_secret_access_key="xxxxxxx" \ + --set env.aws_region="xxxxxxx" \ + --set env.docstore_bucket="xxxxxxx" \ +``` + +Customise with SSL + +_Before proceeding with SSL configuration, make sure you have followed the steps in "**SSL Certificate**" tab_ +``` + --set ssl.createIssuer=true \ + --set ssl.issuer=cloudflare \ + --set ssl.token=xxxxxxxx \ + --set ssl.email="plane-admin@example.com" \ + --set ssl.generateCerts=true \ + +``` + +Configuration Settings Available + +| Setting | Default | Required | Description | +|--- |:---: |:---: |--- | +| planeVersion | stable | Yes | | +| **Ingress Setup** | | | | +| ingress.appHost | 'plane.example.com' | Yes | | +| ingress.minioHost | 'plane-minio.example.com' | | (Optional) Required to open minio console interface | +| ingress.ingressClass | 'nginx' | Yes | can be any of the supported ingress controller class (eg. nginx, traefik, etc) | +| ingress.clientMaxBodySize | 5m | Yes | This is set at the ingress controller level to support max data from client. | +| **SSL Settings** | | | | +| ssl.createIssuer | false | | Set it to true to create Let's Encrypt Service based issuer | +| ssl.issuer | http | | (Yes, if createIssuer = true) Allowed - cloudflare, digitalocean, http | +| ssl.token | | | (Yes, if createIssuer = true) api token of dns provider, not required for http | +| ssl.server | https://acme-v02.api.letsencrypt.org/directory | | (Yes, if createIssuer = true)Lets Encrypt SSL Generation API. Staging: https://acme-staging-v02.api.letsencrypt.org/directory | +| ssl.email | plane-admin@example.com | | (Yes, if createIssuer = true) Required by Let's Encrypt. Change to a valid email id | +| ssl.generateCerts | false | | | +| **Redis Setup** | | | | +| redis.local_setup | true | | | +| redis.image | redis:6.2.7-alpine | | | +| redis.servicePort | 6379 | | Yes, if redis.local_setup=true | +| redis.storageClass | longhorn | | Yes, if redis.local_setup=true | +| redis.volumeSize | 1Gi | | Yes, if redis.local_setup=true | +| **Postgress DB Setup** | | | | +| postgres.local_setup | true | | | +| postgres.image | postgres:15.5-alpine | | Yes, if postgres.local_setup=true | +| postgres.servicePort | 5432 | | Yes, if postgres.local_setup=true | +| postgres.cliConnectPort | | | Provide if you want to expose the NODE PORT for local connectivity | +| postgres.storageClass | longhorn | | Yes, if postgres.local_setup=true | +| postgres.volumeSize | 5Gi | | Yes, if postgres.local_setup=true | +| **Doc Store (Minio) Setup** | | | | +| minio.local_setup | true | | In case this is false, AWS-S3 will settings will be required | +| minio.image | minio/minio:latest | | Yes, if minio.local_setup=true | +| minio.storageClass | longhorn | | Yes, if minio.local_setup=true | +| minio.volumeSize | 5Gi | | Yes, if minio.local_setup=true | +| minio.root_user | admin | | Yes, if minio.local_setup=true | +| minio.root_password | password | | Yes, if minio.local_setup=true | +| **Web Deployment** | | | | +| web.replicas | 1 | Yes | must be >=1 | +| web.memoryLimit | 1000Mi | | | +| web.cpuLimit | 500m | | | +| **Space Deployment** | | | | +| space.replicas | 1 | Yes | must be >=1 | +| space.memoryLimit | 1000Mi | | | +| space.cpuLimit | 500m | | | +| **API Deployment** | | | | +| api.replicas | 1 | Yes | must be >=1 | +| api.memoryLimit | 1000Mi | | | +| api.cpuLimit | 500m | | | +| **Worker Deployment** | | | | +| worker.replicas | 1 | Yes | must be >=1 | +| worker.memoryLimit | 1000Mi | | | +| worker.cpuLimit | 500m | | | +| **Beat Worker Deployment** | | | | +| beatworker.replicas | 1 | Yes | must be >=1 | +| beatworker.memoryLimit | 1000Mi | | | +| beatworker.cpuLimit | 500m | | | +| **Common Environment Settings** | | | | +| env.pgdb_username | plane | | Used for postgres.local_setup=true | +| env.pgdb_password | plane | | Used for postgres.local_setup=true | +| env.pgdb_name | plane | | Used for postgres.local_setup=true | +| env.pgdb_remote_url | '' | | Provided with Postgress Remote DB URI when postgres.local_setup=false | +| env.remote_redis_url | '' | | Provided with Remote Redis URI when redis.local_setup=false | +| env.docstore_bucket | 'uploads' | YES | Minio / AWS-S3 Bucket Name | +| env.doc_upload_size_limit | 5242880 | YES | Document Upload Size Limit (default to 5Mb) | +| env.aws_access_key | '' | | Required, in case minio.local_setup = false | +| env.aws_secret_access_key | '' | | Required, in case minio.local_setup = false | +| env.aws_region | '' | | Required, in case minio.local_setup = false | +| env.secret_key | '60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5' | | Random secret key for data encoding during transit. | +| env.sentry_dsn | '' | | Sentry DSN for error logging | +| env.sentry_environment | '' | | Sentry Environment Name | diff --git a/charts/plane-ce/questions.yml b/charts/plane-ce/questions.yml new file mode 100644 index 0000000..effd805 --- /dev/null +++ b/charts/plane-ce/questions.yml @@ -0,0 +1,364 @@ +questions: + +- variable: dockerRegistry.enabled + label: Docker Registry Enabled + type: boolean + default: false + group: "Docker Registry" + show_subquestion_if: true + subquestions: + - variable: dockerRegistry.loginid + label: "Registry Host" + type: string + - variable: dockerRegistry.loginid + label: "Login ID" + type: string + - variable: dockerRegistry.password + label: "Password/Token" + type: password + +- variable: planeVersion + label: Plane Version (Docker Image Tag) + type: string + default: stable + required: true + group: "Docker Images" + subquestions: + - variable: web.image + label: Frontend Docker Image + type: string + required: true + default: "makeplane/plane-frontend" + - variable: space.image + label: Space Docker Image + type: string + required: true + default: "makeplane/plane-space" + - variable: admin.image + label: Admin Docker Image + type: string + required: true + default: "makeplane/plane-admin" + - variable: api.image + label: Backend Docker Image + type: string + required: true + default: "makeplane/plane-backend" + description: "Used by API, Worker, Beat-Worker" + +- variable: web.replicas + label: "Default Replica Count" + type: int + default: 1 + group: "Web Setup" + subquestions: + - variable: web.memoryLimit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: web.cpuLimit + label: "CPU Limit" + type: string + default: 500m + +- variable: space.replicas + label: "Default Replica Count" + type: int + default: 1 + group: "Spaces Setup" + subquestions: + - variable: space.memoryLimit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: space.cpuLimit + label: "CPU Limit" + type: string + default: 500m + +- variable: admin.replicas + label: "Default Replica Count" + type: int + default: 1 + group: "Admin Setup" + subquestions: + - variable: admin.memoryLimit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: admin.cpuLimit + label: "CPU Limit" + type: string + default: 500m + +- variable: api.replicas + label: "Default Replica Count" + type: int + default: 1 + group: "API Setup" + subquestions: + - variable: api.memoryLimit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: api.cpuLimit + label: "CPU Limit" + type: string + default: 500m + - variable: env.gunicorn_api_workers + label: "Workers" + type: int + default: 1 + - variable: env.cors_allowed_origins + label: "CORS Allowed Origins" + type: string + default: "" + +- variable: worker.replicas + label: "Default Replica Count" + type: int + default: 1 + group: "Worker Setup" + subquestions: + - variable: worker.memoryLimit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: worker.cpuLimit + label: "CPU Limit" + type: string + default: 500m + +- variable: beatworker.replicas + label: "Default Replica Count" + type: int + default: 1 + group: "Beat Worker Setup" + subquestions: + - variable: beatworker.memoryLimit + label: "Memory Limit" + type: string + default: 1000Mi + - variable: beatworker.cpuLimit + label: "CPU Limit" + type: string + default: 500m + +- variable: redis.local_setup + label: "Install Redis" + type: boolean + default: true + group: "Redis Setup" + subquestions: + - variable: redis.image + label: "Docker Image" + type: string + default: "redis:6.2.7-alpine" + show_if: "redis.local_setup=true" + - variable: redis.servicePort + label: Port + type: int + default: 6379 + show_if: "redis.local_setup=true" + - variable: redis.storageClass + label: "Storage Class" + type: string + default: "longhorn" + show_if: "redis.local_setup=true" + - variable: redis.volumeSize + label: "Volume Size" + type: string + default: "1Gi" + show_if: "redis.local_setup=true" + - variable: env.remote_redis_url + label: "Remote Redis URL" + type: string + default: "redis://" + show_if: "redis.local_setup=false" + +- variable: postgres.local_setup + label: "Install Postgres" + type: boolean + default: true + group: "Postgres Setup" + # show_subquestion_if: true + subquestions: + - variable: postgres.image + label: "Docker Image" + type: string + default: "postgres:15.2-alpine" + show_if: "postgres.local_setup=true" + - variable: postgres.servicePort + label: Service Port + type: int + default: 5432 + show_if: "postgres.local_setup=true" + - variable: postgres.cliConnectPort + label: CLI Connect Port + type: int + show_if: "postgres.local_setup=true" + - variable: postgres.storageClass + label: "Storage Class" + type: string + default: "longhorn" + show_if: "postgres.local_setup=true" + - variable: postgres.volumeSize + label: "Volume Size" + type: string + default: "5Gi" + show_if: "postgres.local_setup=true" + - variable: env.pgdb_username + label: "Username" + type: string + default: "plane" + show_if: "postgres.local_setup=true" + - variable: env.pgdb_password + label: "Password" + type: password + default: "plane" + show_if: "postgres.local_setup=true" + - variable: env.pgdb_name + label: "DB Name" + type: string + default: "plane" + show_if: "postgres.local_setup=true" + - variable: env.pgdb_remote_url + label: "Remote URL" + type: string + default: "postrgres://" + show_if: "postgres.local_setup=false" + +- variable: minio.local_setup + label: "Install Minio" + type: boolean + default: true + group: "Storage Setup" + subquestions: + - variable: minio.image + label: "Docker Image" + type: string + default: "minio/minio:RELEASE.2023-10-25T06-33-25Z" + show_if: "minio.local_setup=true" + - variable: minio.root_user + label: "Root User" + type: string + default: "admin" + show_if: "minio.local_setup=true" + - variable: minio.root_password + label: "Root Password" + type: password + default: "password" + show_if: "minio.local_setup=true" + - variable: minio.storageClass + label: "Storage Class" + type: string + default: "longhorn" + show_if: "minio.local_setup=true" + - variable: minio.volumeSize + label: "Volume Size" + type: string + default: "5Gi" + show_if: "minio.local_setup=true" + - variable: env.aws_access_key + label: "AWS Access Key" + type: string + default: "" + show_if: "minio.local_setup=false" + - variable: env.aws_secret_access_key + label: "AWS Secret Key" + type: password + default: "" + show_if: "minio.local_setup=false" + - variable: env.aws_region + label: "AWS Region" + type: string + default: "" + show_if: "minio.local_setup=false" + - variable: env.docstore_bucket + label: "Bucket Name" + type: string + default: "uploads" + - variable: env.doc_upload_size_limit + label: "FIle Upload Size Limit" + type: string + default: "5242880" + + +- variable: ingress.enabled + label: "Install Ingress" + type: boolean + default: true + required: true + group: "Ingress" + show_subquestion_if: true + subquestions: + - variable: ingress.appHost + label: "App. Host" + type: string + default: "plane.example.com" + required: true + - variable: ingress.minioHost + label: "Minio Host" + type: string + default: "plane-minio.example.com" + show_if: "minio.local_setup=true" + - variable: ingress.ingressClass + label: "Ingress Classname" + type: string + required: true + default: "nginx" + - variable: ingress.clientMaxBodySize + label: "Max Body Size" + type: string + required: true + default: "10m" + +- variable: ssl.createIssuer + label: "Create Issuer" + type: boolean + default: false + group: "Ingress" + show_if: "ingress.enabled=true" + show_subquestion_if: true + subquestions: + - variable: ssl.issuer + label: "SSL Issuer" + type: enum + options: + - "http" + - "cloudflare" + - "digitalocean" + default: "http" + - variable: ssl.server + label: "Let's Encrypt Server URL" + type: string + default: "https://acme-staging-v02.api.letsencrypt.org/directory" + - variable: ssl.email + label: "Let's Encrypt Reg. Email" + type: string + default: "plane@example.com" + - variable: ssl.token + label: "Provider API Token" + type: password + default: "" + description: "Not required for 'http' issuer" + - variable: ssl.generateCerts + label: "Enable to generate certificates" + type: boolean + default: false + +- variable: env.sentry_dsn + label: "Sentry DSN" + type: string + default: "" + group: "Misc." + subquestions: + - variable: env.sentry_environment + label: "Sentry Environment" + type: string + default: "Development" + - variable: env.secret_key + label: "Random Secret Key" + type: string + required: true + default: "60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5" diff --git a/charts/plane-ce/templates/_helpers.tpl b/charts/plane-ce/templates/_helpers.tpl new file mode 100644 index 0000000..b33a371 --- /dev/null +++ b/charts/plane-ce/templates/_helpers.tpl @@ -0,0 +1,3 @@ +{{- define "imagePullSecret" }} +{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\"}}}" .Values.dockerRegistry.host .Values.dockerRegistry.loginid .Values.dockerRegistry.password | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/plane-ce/templates/certs/cert-issuers.yaml b/charts/plane-ce/templates/certs/cert-issuers.yaml new file mode 100644 index 0000000..5b70cf8 --- /dev/null +++ b/charts/plane-ce/templates/certs/cert-issuers.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.ingress.enabled .Values.ssl.createIssuer }} + +apiVersion: v1 +kind: Secret +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-issuer-api-token-secret +type: Opaque +stringData: + api-token: {{ .Values.ssl.token | default "default-api-token" | quote }} + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-cert-issuer +spec: + acme: + email: {{ .Values.ssl.email }} + server: {{ .Values.ssl.server }} + privateKeySecretRef: + name: {{ .Release.Name }}-cert-issuer-key + solvers: + {{- if eq .Values.ssl.issuer "cloudflare" }} + - dns01: + cloudflare: + apiTokenSecretRef: + name: {{ .Release.Name }}-issuer-api-token-secret + key: api-token + {{- end }} + {{- if eq .Values.ssl.issuer "digitalocean" }} + - dns01: + digitalocean: + tokenSecretRef: + name: {{ .Release.Name }}-issuer-api-token-secret + key: api-token + {{- end }} + {{- if eq .Values.ssl.issuer "http" }} + - http01: + ingress: + ingressClassName: {{ .Values.ingress.ingressClass }} + {{- end }} + +--- +{{- end}} \ No newline at end of file diff --git a/charts/plane-ce/templates/certs/certs.yaml b/charts/plane-ce/templates/certs/certs.yaml new file mode 100644 index 0000000..bf6cfda --- /dev/null +++ b/charts/plane-ce/templates/certs/certs.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.ingress.enabled .Values.ssl.createIssuer .Values.ssl.generateCerts }} + +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-ssl-cert +spec: + dnsNames: + - {{ .Values.ingress.appHost | quote }} + {{- if and .Values.minio.local_setup .Values.ingress.minioHost }} + - {{ .Values.ingress.minioHost | quote }} + {{- end }} + issuerRef: + name: {{ .Release.Name }}-cert-issuer + secretName: {{ .Release.Name }}-ssl-cert + +{{- end}} diff --git a/charts/plane-ce/templates/config-secrets/app-env.yaml b/charts/plane-ce/templates/config-secrets/app-env.yaml new file mode 100644 index 0000000..b358e49 --- /dev/null +++ b/charts/plane-ce/templates/config-secrets/app-env.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-app-secrets +data: + SECRET_KEY: {{ .Values.env.secret_key | default "60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5" | b64enc | quote }} + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-app-vars +data: + SENTRY_DSN: {{ .Values.env.sentry_dsn | default "" | quote}} + SENTRY_ENVIRONMENT: {{ .Values.env.sentry_environment | default "" | quote}} + DEBUG: "0" + DOCKERIZED: "1" + GUNICORN_WORKERS: {{ .Values.env.gunicorn_api_workers | default 1 | quote }} + + {{- if and .Values.ingress.enabled .Values.ingress.appHost }} + WEB_URL: "http://{{ .Values.ingress.appHost }}" + {{- else }} + WEB_URL: "" + {{- end }} + + + {{- if eq .Values.env.cors_allowed_origins "*"}} + CORS_ALLOWED_ORIGINS: "*" + {{- else if and .Values.ingress.enabled .Values.ingress.appHost .Values.env.cors_allowed_origins }} + CORS_ALLOWED_ORIGINS: "http://{{ .Values.ingress.appHost }},https://{{ .Values.ingress.appHost }},{{ .Values.env.cors_allowed_origins }}" + {{- else if .Values.env.cors_allowed_origins }} + CORS_ALLOWED_ORIGINS: "{{ .Values.env.cors_allowed_origins }}" + {{- else if and .Values.ingress.enabled .Values.ingress.appHost}} + CORS_ALLOWED_ORIGINS: "http://{{ .Values.ingress.appHost }},https://{{ .Values.ingress.appHost }}" + {{- else }} + CORS_ALLOWED_ORIGINS: "" + {{- end }} + + {{- if .Values.redis.local_setup }} + REDIS_URL: "redis://{{ .Release.Name }}-redis.{{ .Release.Namespace }}.svc.cluster.local:6379/" + {{- else }} + REDIS_URL: {{ .Values.env.remote_redis_url | default "" | quote }} + {{- end }} + + {{ if .Values.postgres.local_setup }} + DATABASE_URL: "postgresql://{{ .Values.env.pgdb_username }}:{{ .Values.env.pgdb_password }}@{{ .Release.Name }}-pgdb.{{ .Release.Namespace }}.svc.cluster.local/{{ .Values.env.pgdb_name }}" + {{ else if .Values.env.pgdb_remote_url }} + DATABASE_URL: {{ .Values.env.pgdb_remote_url}} + {{ else }} + DATABASE_URL: "" + {{ end }} diff --git a/charts/plane-ce/templates/config-secrets/doc-strore.yaml b/charts/plane-ce/templates/config-secrets/doc-strore.yaml new file mode 100644 index 0000000..f40cc76 --- /dev/null +++ b/charts/plane-ce/templates/config-secrets/doc-strore.yaml @@ -0,0 +1,37 @@ + +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-doc-store-secrets +data: + {{ if .Values.minio.local_setup }} + MINIO_ROOT_PASSWORD: {{ .Values.minio.root_password | default "password" | b64enc | quote}} + AWS_SECRET_ACCESS_KEY: {{ .Values.minio.root_password | default "password" | b64enc | quote }} + {{ else }} + AWS_SECRET_ACCESS_KEY: {{ .Values.env.aws_secret_access_key | default "" | b64enc | quote }} + {{ end }} + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-doc-store-vars +data: + FILE_SIZE_LIMIT: {{ .Values.env.doc_upload_size_limit | default 5242880 | quote }} + AWS_S3_BUCKET_NAME: {{ .Values.env.docstore_bucket | default "" | quote }} + {{ if .Values.minio.local_setup }} + MINIO_ROOT_USER: {{ .Values.minio.root_user | default "admin" | quote }} + AWS_ACCESS_KEY_ID: {{ .Values.minio.root_user | default "admin" | quote }} + AWS_S3_ENDPOINT_URL: http://{{ .Release.Name }}-minio:9000 + USE_MINIO: "1" + {{ else }} + USE_MINIO: "0" + AWS_ACCESS_KEY_ID: {{ .Values.env.aws_access_key | default "" | quote }} + AWS_REGION: {{ .Values.env.aws_region | default "" | quote }} + # AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000} + {{ end }} +--- \ No newline at end of file diff --git a/charts/plane-ce/templates/config-secrets/docker-registry.yaml b/charts/plane-ce/templates/config-secrets/docker-registry.yaml new file mode 100644 index 0000000..14e6b3d --- /dev/null +++ b/charts/plane-ce/templates/config-secrets/docker-registry.yaml @@ -0,0 +1,12 @@ +{{- if .Values.dockerRegistry.enabled }} + +apiVersion: v1 +kind: Secret +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-docker-registry-credentials +data: + .dockerconfigjson: {{ include "imagePullSecret" .}} +type: kubernetes.io/dockerconfigjson + +{{- end }} \ No newline at end of file diff --git a/charts/plane-ce/templates/config-secrets/pgdb.yaml b/charts/plane-ce/templates/config-secrets/pgdb.yaml new file mode 100644 index 0000000..e8455bd --- /dev/null +++ b/charts/plane-ce/templates/config-secrets/pgdb.yaml @@ -0,0 +1,21 @@ +{{- if .Values.postgres.local_setup }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-pgdb-secrets +data: + POSTGRES_PASSWORD: {{ .Values.env.pgdb_password | default "plane" | b64enc | quote }} +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-pgdb-vars +data: + POSTGRES_DB: {{ .Values.env.pgdb_name | default "plane" | quote }} + POSTGRES_USER: {{ .Values.env.pgdb_username | default "plane" | quote }} +--- +{{- end}} \ No newline at end of file diff --git a/charts/plane-ce/templates/ingress.yaml b/charts/plane-ce/templates/ingress.yaml new file mode 100644 index 0000000..4942e2e --- /dev/null +++ b/charts/plane-ce/templates/ingress.yaml @@ -0,0 +1,83 @@ +{{- if and .Values.ingress.enabled .Values.ingress.appHost }} + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-ingress + annotations: + nginx.ingress.kubernetes.io/proxy-body-size: {{ .Values.ingress.clientMaxBodySize | default "5m" | quote}} +spec: + ingressClassName: {{ .Values.ingress.ingressClass }} + rules: + - host: {{ .Values.ingress.appHost }} + http: + paths: + - backend: + service: + port: + number: 3000 + name: {{ .Release.Name }}-web + path: / + pathType: Prefix + - backend: + service: + port: + number: 8000 + name: {{ .Release.Name }}-api + path: /api + pathType: Prefix + - backend: + service: + port: + number: 8000 + name: {{ .Release.Name }}-api + path: /auth + pathType: Prefix + - backend: + service: + port: + number: 3000 + name: {{ .Release.Name }}-space + path: /spaces + pathType: Prefix + - backend: + service: + port: + number: 3000 + name: {{ .Release.Name }}-admin + path: /god-mode + pathType: Prefix + {{- if and .Values.minio.local_setup .Values.env.docstore_bucket }} + - backend: + service: + port: + number: 9000 + name: {{ .Release.Name }}-minio + path: /{{ .Values.env.docstore_bucket }} + pathType: Prefix + {{- end }} + + {{- if and .Values.minio.local_setup .Values.ingress.minioHost }} + - host: {{ .Values.ingress.minioHost }} + http: + paths: + - backend: + service: + port: + number: 9090 + name: {{ .Release.Name }}-minio + path: / + pathType: Prefix + {{- end }} + {{- if .Values.ssl.generateCerts }} + tls: + - hosts: + - {{ .Values.ingress.appHost | quote }} + {{- if and .Values.minio.local_setup .Values.ingress.minioHost }} + - {{ .Values.ingress.minioHost | quote }} + {{ end }} + secretName: {{ .Release.Name }}-ssl-cert + {{- end }} + +{{- end }} \ No newline at end of file diff --git a/charts/plane-ce/templates/service-account.yaml b/charts/plane-ce/templates/service-account.yaml new file mode 100644 index 0000000..6eed2f5 --- /dev/null +++ b/charts/plane-ce/templates/service-account.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-srv-account +{{- if .Values.dockerRegistry.enabled }} +imagePullSecrets: + - name: {{ .Release.Name }}-docker-registry-credentials +{{- end}} \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/admin.deployment.yaml b/charts/plane-ce/templates/workloads/admin.deployment.yaml new file mode 100644 index 0000000..d17179a --- /dev/null +++ b/charts/plane-ce/templates/workloads/admin.deployment.yaml @@ -0,0 +1,60 @@ + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-admin + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-admin +spec: + clusterIP: None + ports: + - name: admin-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-admin + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-admin-wl +spec: + replicas: {{ .Values.admin.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-admin + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-admin + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-admin + imagePullPolicy: Always + image: {{ .Values.admin.image | default "makeplane/plane-frontend" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.admin.memoryLimit | default "1000Mi" | quote }} + cpu: {{ .Values.admin.cpuLimit | default "500m" | quote}} + command: + - node + args: + - admin/server.js + - admin + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + +--- \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/api.deployment.yaml b/charts/plane-ce/templates/workloads/api.deployment.yaml new file mode 100644 index 0000000..e1daa14 --- /dev/null +++ b/charts/plane-ce/templates/workloads/api.deployment.yaml @@ -0,0 +1,80 @@ + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-api + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-api +spec: + clusterIP: None + ports: + - name: api-8000 + port: 8000 + protocol: TCP + targetPort: 8000 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-api + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-api-wl +spec: + replicas: {{ .Values.api.replicas | default 1}} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-api + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-api + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-api + imagePullPolicy: Always + image: {{ .Values.api.image | default "makeplane/plane-backend" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.api.memoryLimit | default "1000Mi" | quote }} + cpu: {{ .Values.api.cpuLimit | default "500m" | quote}} + command: + - ./bin/docker-entrypoint-api.sh + envFrom: + - configMapRef: + name: {{ .Release.Name }}-app-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-app-secrets + optional: false + - configMapRef: + name: {{ .Release.Name }}-doc-store-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-doc-store-secrets + optional: false + readinessProbe: + failureThreshold: 30 + httpGet: + path: / + port: 8000 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + +--- \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/beat-worker.deployment.yaml b/charts/plane-ce/templates/workloads/beat-worker.deployment.yaml new file mode 100644 index 0000000..2966acd --- /dev/null +++ b/charts/plane-ce/templates/workloads/beat-worker.deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-beat-worker-wl +spec: + replicas: {{ .Values.beatworker.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-beat-worker + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-beat-worker + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-beat-worker + imagePullPolicy: Always + image: {{ .Values.beatworker.image | default "makeplane/plane-backend" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.beatworker.memoryLimit | default "1000Mi" | quote }} + cpu: {{ .Values.beatworker.cpuLimit | default "500m" | quote}} + command: + - ./bin/docker-entrypoint-beat.sh + envFrom: + - configMapRef: + name: {{ .Release.Name }}-app-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-app-secrets + optional: false + - configMapRef: + name: {{ .Release.Name }}-doc-store-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-doc-store-secrets + optional: false + + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + +--- \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/migrator.job.yaml b/charts/plane-ce/templates/workloads/migrator.job.yaml new file mode 100644 index 0000000..b6a2805 --- /dev/null +++ b/charts/plane-ce/templates/workloads/migrator.job.yaml @@ -0,0 +1,38 @@ + +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-api-migrate-{{ .Release.Revision }} +spec: + backoffLimit: 3 + template: + metadata: + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-api-migrate + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-api-migrate + image: {{ .Values.api.image | default "makeplane/plane-backend" }}:{{ .Values.planeVersion }} + command: + - ./bin/docker-entrypoint-migrator.sh + imagePullPolicy: Always + envFrom: + - configMapRef: + name: {{ .Release.Name }}-app-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-app-secrets + optional: false + - configMapRef: + name: {{ .Release.Name }}-doc-store-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-doc-store-secrets + optional: false + restartPolicy: OnFailure + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account +--- diff --git a/charts/plane-ce/templates/workloads/minio.stateful.yaml b/charts/plane-ce/templates/workloads/minio.stateful.yaml new file mode 100644 index 0000000..1dd7b14 --- /dev/null +++ b/charts/plane-ce/templates/workloads/minio.stateful.yaml @@ -0,0 +1,122 @@ +{{- if .Values.minio.local_setup }} + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-minio + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-minio +spec: + clusterIP: None + ports: + - name: minio-api-9000 + port: 9000 + protocol: TCP + targetPort: 9000 + - name: minio-console-9090 + port: 9090 + protocol: TCP + targetPort: 9090 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-minio +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-minio-wl +spec: + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-minio + serviceName: {{ .Release.Name }}-minio + template: + metadata: + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-minio + spec: + containers: + - image: {{ .Values.minio.image }} + imagePullPolicy: Always + name: {{ .Release.Name }}-minio + stdin: true + tty: true + # command: + args: + - server + - /data + - --console-address + - :9090 + envFrom: + - configMapRef: + name: {{ .Release.Name }}-doc-store-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-doc-store-secrets + optional: false + volumeMounts: + - mountPath: /data + name: pvc-{{ .Release.Name }}-minio-vol + subPath: '' + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + creationTimestamp: null + namespace: {{ .Release.Namespace }} + name: pvc-{{ .Release.Name }}-minio-vol + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.minio.volumeSize | default "5Gi" | quote }} + storageClassName: {{ .Values.minio.storageClass }} + volumeMode: Filesystem + +--- + +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-minio-bucket +spec: + backoffLimit: 6 + completionMode: NonIndexed + template: + metadata: + namespace: {{ .Release.Namespace }} + spec: + restartPolicy: OnFailure + initContainers: + - name: init + image: busybox + command: ['sh', '-c', "until nslookup {{ .Release.Name }}-minio.{{ .Release.Namespace }}.svc.cluster.local; do echo waiting for {{ .Release.Name }}-minio; sleep 2; done"] + containers: + - command: + - /bin/sh + args: + - '-c' + - >- + /usr/bin/mc config host add plane-app-minio + http://{{ .Release.Name }}-minio.{{ .Release.Namespace }}.svc.cluster.local:9000 "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY"; + /usr/bin/mc mb plane-app-minio/$AWS_S3_BUCKET_NAME; + /usr/bin/mc anonymous set download plane-app-minio/$AWS_S3_BUCKET_NAME; exit 0; + envFrom: + - configMapRef: + name: {{ .Release.Name }}-doc-store-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-doc-store-secrets + optional: false + image: minio/mc + imagePullPolicy: Always + name: {{ .Release.Name }}-minio-bucket + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + terminationGracePeriodSeconds: 120 +{{- end }} \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/postgres.stateful.yaml b/charts/plane-ce/templates/workloads/postgres.stateful.yaml new file mode 100644 index 0000000..ee30991 --- /dev/null +++ b/charts/plane-ce/templates/workloads/postgres.stateful.yaml @@ -0,0 +1,98 @@ +{{- if .Values.postgres.local_setup }} + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-pgdb + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-pgdb +spec: + clusterIP: None + ports: + - name: pg-{{ .Values.postgres.servicePort }} + port: {{ .Values.postgres.servicePort }} + protocol: TCP + targetPort: 5432 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-pgdb +--- +{{- if and .Values.postgres.cliConnectPort .Values.postgres.cliConnectPort | int }} +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-pgdb-cli-connect +spec: + externalTrafficPolicy: Cluster + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: pg-{{ .Values.postgres.cliConnectPort | default 30000 }} + nodePort: {{ .Values.postgres.cliConnectPort | default 30000 }} + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-pgdb + sessionAffinity: None + type: NodePort +--- +{{- end }} + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-pgdb-wl +spec: + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-pgdb + serviceName: {{ .Release.Name }}-pgdb + template: + metadata: + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-pgdb + spec: + containers: + - image: {{ .Values.postgres.image }} + imagePullPolicy: Always + name: {{ .Release.Name }}-pgdb + stdin: true + tty: true + env: + - name: PGDATA + value: /var/lib/postgresql/data/plane + envFrom: + - configMapRef: + name: {{ .Release.Name }}-pgdb-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-pgdb-secrets + optional: false + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: pvc-{{ .Release.Name }}-pgdb-vol + subPath: '' + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + creationTimestamp: null + namespace: {{ .Release.Namespace }} + name: pvc-{{ .Release.Name }}-pgdb-vol + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.postgres.volumeSize | default "5Gi" | quote }} + storageClassName: {{ .Values.postgres.storageClass }} + volumeMode: Filesystem + +{{- end }} \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/redis.stateful.yaml b/charts/plane-ce/templates/workloads/redis.stateful.yaml new file mode 100644 index 0000000..7eede7d --- /dev/null +++ b/charts/plane-ce/templates/workloads/redis.stateful.yaml @@ -0,0 +1,66 @@ +{{- if .Values.redis.local_setup }} + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-redis + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-redis +spec: + clusterIP: None + ports: + - name: redis-{{ .Values.redis.servicePort }} + port: {{ .Values.redis.servicePort }} + protocol: TCP + targetPort: 6379 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-redis +--- + +# REDIS WORKLOAD + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-redis-wl +spec: + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-redis + serviceName: {{ .Release.Name }}-redis + template: + metadata: + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-redis + spec: + containers: + - image: {{ .Values.redis.image }} + imagePullPolicy: Always + name: {{ .Release.Name }}-redis + stdin: true + tty: true + volumeMounts: + - mountPath: /data + name: pvc-{{ .Release.Name }}-redis-vol + subPath: '' + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + creationTimestamp: null + namespace: {{ .Release.Namespace }} + name: pvc-{{ .Release.Name }}-redis-vol + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.redis.volumeSize | default "1Gi" | quote }} + storageClassName: {{ .Values.redis.storageClass }} + volumeMode: Filesystem + +{{- end }} \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/space.deployment.yaml b/charts/plane-ce/templates/workloads/space.deployment.yaml new file mode 100644 index 0000000..a6a51d7 --- /dev/null +++ b/charts/plane-ce/templates/workloads/space.deployment.yaml @@ -0,0 +1,60 @@ + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-space + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-space +spec: + clusterIP: None + ports: + - name: space-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-space + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-space-wl +spec: + replicas: {{ .Values.space.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-space + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-space + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-space + imagePullPolicy: Always + image: {{ .Values.space.images | default "makeplane/plane-space" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.web.memoryLimit | default "1000Mi" | quote }} + cpu: {{ .Values.web.cpuLimit | default "500m" | quote}} + command: + - node + args: + - space/server.js + - space + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + +--- \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/web.deployment.yaml b/charts/plane-ce/templates/workloads/web.deployment.yaml new file mode 100644 index 0000000..2f65aaa --- /dev/null +++ b/charts/plane-ce/templates/workloads/web.deployment.yaml @@ -0,0 +1,60 @@ + +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-web + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-web +spec: + clusterIP: None + ports: + - name: web-3000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-web + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-web-wl +spec: + replicas: {{ .Values.web.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-web + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-web + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-web + imagePullPolicy: Always + image: {{ .Values.web.image | default "makeplane/plane-frontend" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.web.memoryLimit | default "1000Mi" | quote }} + cpu: {{ .Values.web.cpuLimit | default "500m" | quote}} + command: + - node + args: + - web/server.js + - web + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + +--- \ No newline at end of file diff --git a/charts/plane-ce/templates/workloads/worker.deployment.yaml b/charts/plane-ce/templates/workloads/worker.deployment.yaml new file mode 100644 index 0000000..42ca195 --- /dev/null +++ b/charts/plane-ce/templates/workloads/worker.deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-worker-wl +spec: + replicas: {{ .Values.worker.replicas | default 1 }} + selector: + matchLabels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-worker + template: + metadata: + namespace: {{ .Release.Namespace }} + labels: + app.name: {{ .Release.Namespace }}-{{ .Release.Name }}-worker + annotations: + timestamp: {{ now | quote }} + spec: + containers: + - name: {{ .Release.Name }}-worker + imagePullPolicy: Always + image: {{ .Values.worker.image | default "makeplane/plane-backend" }}:{{ .Values.planeVersion }} + stdin: true + tty: true + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: {{ .Values.worker.memoryLimit | default "1000Mi" | quote }} + cpu: {{ .Values.worker.cpuLimit | default "500m" | quote}} + command: + - ./bin/docker-entrypoint-worker.sh + envFrom: + - configMapRef: + name: {{ .Release.Name }}-app-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-app-secrets + optional: false + - configMapRef: + name: {{ .Release.Name }}-doc-store-vars + optional: false + - secretRef: + name: {{ .Release.Name }}-doc-store-secrets + optional: false + + serviceAccount: {{ .Release.Name }}-srv-account + serviceAccountName: {{ .Release.Name }}-srv-account + +--- \ No newline at end of file diff --git a/charts/plane-ce/values.yaml b/charts/plane-ce/values.yaml new file mode 100644 index 0000000..d1ec810 --- /dev/null +++ b/charts/plane-ce/values.yaml @@ -0,0 +1,112 @@ +planeVersion: stable + +dockerRegistry: + enabled: false + host: "index.docker.io/v1/" + loginid: makeplane + password: '' + +ingress: + enabled: true + appHost: 'plane.example.com' + minioHost: 'plane-minio.example.com' + ingressClass: 'nginx' + clientMaxBodySize: 10m + +# SSL Configuration - Valid only if ingress.enabled is true +ssl: + createIssuer: false + issuer: "http" # Allowed : cloudflare, digitalocean, http + token: "" # not required for http + server: https://acme-v02.api.letsencrypt.org/directory + email: plane@example.com + generateCerts: false + +redis: + local_setup: true + image: redis:7.2.4-alpine + servicePort: 6379 + storageClass: longhorn + volumeSize: 1Gi + +postgres: + local_setup: true + image: postgres:15.5-alpine + servicePort: 5432 + cliConnectPort: '' + storageClass: longhorn + volumeSize: 5Gi + +minio: + local_setup: true + image: minio/minio:latest + storageClass: longhorn + volumeSize: 5Gi + root_user: admin + root_password: password + +web: + replicas: 1 + memoryLimit: 1000Mi + cpuLimit: 500m + image: makeplane/plane-frontend + + +space: + replicas: 1 + memoryLimit: 1000Mi + cpuLimit: 500m + image: makeplane/plane-space + +admin: + replicas: 1 + memoryLimit: 1000Mi + cpuLimit: 500m + image: makeplane/plane-admin + +api: + replicas: 1 + memoryLimit: 1000Mi + cpuLimit: 500m + image: makeplane/plane-backend + +worker: + replicas: 1 + memoryLimit: 1000Mi + cpuLimit: 500m + image: makeplane/plane-backend + +beatworker: + replicas: 1 + memoryLimit: 1000Mi + cpuLimit: 500m + image: makeplane/plane-backend + +env: + pgdb_username: plane + pgdb_password: plane + pgdb_name: plane + pgdb_remote_url: "" #INCASE OF REMOTE PG DB URL ONLY + + # NEXT_PUBLIC_DEPLOY_URL: "" + # REDIS + remote_redis_url: "" #INCASE OF REMOTE REDIS ONLY + # POSTGRES DB VALUES + + # DATA STORE + docstore_bucket: "uploads" + doc_upload_size_limit: "5242880" # 5MB + + # REQUIRED IF MINIO LOCAL SETUP IS FALSE + aws_access_key: "" + aws_secret_access_key: "" + aws_region: "" + + secret_key: "60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5" + + sentry_dsn: "" + sentry_environment: "" + + gunicorn_api_workers: 1 + + cors_allowed_origins: "" diff --git a/content/config.md b/content/config.md new file mode 100644 index 0000000..76b7276 --- /dev/null +++ b/content/config.md @@ -0,0 +1,69 @@ +| Setting | Default | Required | Description | +|--- |:---: |:---: |--- | +| planeVersion | stable | Yes | | +| **Ingress Setup** | | | | +| ingress.appHost | 'plane.example.com' | Yes | | +| ingress.minioHost | 'plane-minio.example.com' | | (Optional) Required to open minio console interface | +| ingress.ingressClass | 'nginx' | Yes | can be any of the supported ingress controller class (eg. nginx, traefik, etc) | +| ingress.clientMaxBodySize | 5m | Yes | This is set at the ingress controller level to support max data from client. | +| **SSL Settings** | | | | +| ssl.createIssuer | false | | Set it to true to create Let's Encrypt Service based issuer | +| ssl.issuer | http | | (Yes, if createIssuer = true) Allowed - cloudflare, digitalocean, http | +| ssl.token | | | (Yes, if createIssuer = true) api token of dns provider, not required for http | +| ssl.server | https://acme-v02.api.letsencrypt.org/directory | | (Yes, if createIssuer = true)Lets Encrypt SSL Generation API. Staging: https://acme-staging-v02.api.letsencrypt.org/directory | +| ssl.email | plane-admin@example.com | | (Yes, if createIssuer = true) Required by Let's Encrypt. Change to a valid email id | +| ssl.generateCerts | false | | | +| **Redis Setup** | | | | +| redis.local_setup | true | | | +| redis.image | redis:6.2.7-alpine | | | +| redis.servicePort | 6379 | | Yes, if redis.local_setup=true | +| redis.storageClass | longhorn | | Yes, if redis.local_setup=true | +| redis.volumeSize | 1Gi | | Yes, if redis.local_setup=true | +| **Postgress DB Setup** | | | | +| postgres.local_setup | true | | | +| postgres.image | postgres:15.5-alpine | | Yes, if postgres.local_setup=true | +| postgres.servicePort | 5432 | | Yes, if postgres.local_setup=true | +| postgres.cliConnectPort | | | Provide if you want to expose the NODE PORT for local connectivity | +| postgres.storageClass | longhorn | | Yes, if postgres.local_setup=true | +| postgres.volumeSize | 5Gi | | Yes, if postgres.local_setup=true | +| **Doc Store (Minio) Setup** | | | | +| minio.local_setup | true | | In case this is false, AWS-S3 will settings will be required | +| minio.image | minio/minio:latest | | Yes, if minio.local_setup=true | +| minio.storageClass | longhorn | | Yes, if minio.local_setup=true | +| minio.volumeSize | 5Gi | | Yes, if minio.local_setup=true | +| minio.root_user | admin | | Yes, if minio.local_setup=true | +| minio.root_password | password | | Yes, if minio.local_setup=true | +| **Web Deployment** | | | | +| web.replicas | 1 | Yes | must be >=1 | +| web.memoryLimit | 1000Mi | | | +| web.cpuLimit | 500m | | | +| **Space Deployment** | | | | +| space.replicas | 1 | Yes | must be >=1 | +| space.memoryLimit | 1000Mi | | | +| space.cpuLimit | 500m | | | +| **API Deployment** | | | | +| api.replicas | 1 | Yes | must be >=1 | +| api.memoryLimit | 1000Mi | | | +| api.cpuLimit | 500m | | | +| **Worker Deployment** | | | | +| worker.replicas | 1 | Yes | must be >=1 | +| worker.memoryLimit | 1000Mi | | | +| worker.cpuLimit | 500m | | | +| **Beat Worker Deployment** | | | | +| beatworker.replicas | 1 | Yes | must be >=1 | +| beatworker.memoryLimit | 1000Mi | | | +| beatworker.cpuLimit | 500m | | | +| **Common Environment Settings** | | | | +| env.pgdb_username | plane | | Used for postgres.local_setup=true | +| env.pgdb_password | plane | | Used for postgres.local_setup=true | +| env.pgdb_name | plane | | Used for postgres.local_setup=true | +| env.pgdb_remote_url | '' | | Provided with Postgress Remote DB URI when postgres.local_setup=false | +| env.remote_redis_url | '' | | Provided with Remote Redis URI when redis.local_setup=false | +| env.docstore_bucket | 'uploads' | YES | Minio / AWS-S3 Bucket Name | +| env.doc_upload_size_limit | 5242880 | YES | Document Upload Size Limit (default to 5Mb) | +| env.aws_access_key | '' | | Required, in case minio.local_setup = false | +| env.aws_secret_access_key | '' | | Required, in case minio.local_setup = false | +| env.aws_region | '' | | Required, in case minio.local_setup = false | +| env.secret_key | '60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5' | | Random secret key for data encoding during transit. | +| env.sentry_dsn | '' | | Sentry DSN for error logging | +| env.sentry_environment | '' | | Sentry Environment Name | diff --git a/content/setup.md b/content/setup.md new file mode 100644 index 0000000..250595c --- /dev/null +++ b/content/setup.md @@ -0,0 +1,55 @@ +Follow below steps to setup **Plane** + +Add Helm Repo +``` +helm repo add makeplane https://helm.plane.so/ +``` + +You must refer the configuration variables before proceeding. This can be done by running the below command or visiting **Configuration** tab. +``` +helm show values plane-ce --repo https://helm.plane.so +``` + + +Basic Install +``` +helm install \ + --create-namespace \ + --namespace plane-ns \ + --set ingress.appHost="plane.example.com" \ + --set ingress.minioHost="plane-minio.example.com" \ + my-plane makeplane/plane-ce +``` + +Customise Remote Postgress URL +``` + --set postgres.local_setup=false \ + --set env.pgdb_remote_url="postgress://[username]:[password]@[pg-host]/[db-name]" \ +``` + +Customise Remote Redis URL +``` + --set redis.local_setup=false \ + --set env.remote_redis_url="redis://[redis-host]:[6379]" \ +``` + +Customise Document Store - Change from Minio to AWS S3 +``` + --set minio.local_setup=false \ + --set env.aws_access_key="xxxxxxx" \ + --set env.aws_secret_access_key="xxxxxxx" \ + --set env.aws_region="xxxxxxx" \ + --set env.docstore_bucket="xxxxxxx" \ +``` + +Customise with SSL + +_Before proceeding with SSL configuration, make sure you have followed the steps in "**SSL Certificate**" tab_ +``` + --set ssl.createIssuer=true \ + --set ssl.issuer=cloudflare \ + --set ssl.token=xxxxxxxx \ + --set ssl.email="plane-admin@example.com" \ + --set ssl.generateCerts=true \ + +``` \ No newline at end of file diff --git a/content/ssl.md b/content/ssl.md new file mode 100644 index 0000000..5f6b355 --- /dev/null +++ b/content/ssl.md @@ -0,0 +1,12 @@ + +If you are looking at generating Let's Encrypt SSL Certificate, preinstall Cert-Manager using below steps before moving to installing **Plane** +``` +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.1/cert-manager.crds.yaml + +helm repo add jetstack https://charts.jetstack.io + +helm install cert-manager --create-namespace --namespace cert-manager --version v1.13.1 jetstack/cert-manager --set startupapicheck.timeout=5m + +helm uninstall cert-manager -n cert-manager + +``` diff --git a/cr.yaml b/cr.yaml new file mode 100644 index 0000000..b67a65c --- /dev/null +++ b/cr.yaml @@ -0,0 +1,12 @@ +sign: false + +# Enable automatic generation of release notes using GitHubs release notes generator. +# see: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes +generate-release-notes: true + +# package-path: dist/packages +# index-path: dist/index.yaml +# skip-existing: true +git-base-url: https://api.github.com/ +git-upload-url: https://uploads.github.com/ + diff --git a/images/favicon.png b/images/favicon.png new file mode 100644 index 0000000..be1a753 Binary files /dev/null and b/images/favicon.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..d47aaa9 --- /dev/null +++ b/index.html @@ -0,0 +1,84 @@ + + + + + + + Plane Helm Charts + + + + + + + +
+
+
Plane Helm Chart Setup
+
+ + +
+
+
+ Plane is a simple, extensible, open source project and product management tool. + It allows users to start with a basic task tracking tool and gradually adopt various project management frameworks + like Agile, Waterfall, and many more. +
+ +
+
+ +
+ +
+ +
+
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/metadata/artifacthub-pkg.yml b/metadata/artifacthub-pkg.yml new file mode 100644 index 0000000..09f2152 --- /dev/null +++ b/metadata/artifacthub-pkg.yml @@ -0,0 +1,68 @@ +# # Artifact Hub package metadata file +# version: A SemVer 2 version (required) +# name: The name of the package (only alphanum, no spaces, dashes allowed) (required) +# alternativeName: Alternative name of the package (optional) +# category: Category of the package (optional) # One of: ai-machine-learning, database, integration-delivery, monitoring-logging, networking, security, storage, streaming-messaging or skip-prediction +# displayName: The name of the package nicely formatted (required) +# createdAt: The date this package was created (RFC3339 layout) (required) +# description: A short description of the package (required) +# logoPath: Path to the logo image file relative to the package directory (optional, but it improves package visibility) +# logoURL: The URL of the logo image (optional, an alternative to logoPath if the image is hosted somewhere else) +# digest: String that uniquely identifies this package version (optional) +# license: SPDX identifier of the package license (https://spdx.org/licenses/) (optional) +# homeURL: The URL of the project home page (optional) +# appVersion: The version of the app that this contains (optional) +# containersImages: # (optional) +# - name: Image identifier (optional) +# image: The format should match ${REGISTRYHOST}/${USERNAME}/${NAME}:${TAG} +# whitelisted: When set to true, this image won't be scanned for security vulnerabilities +# platforms: # (optional) +# - A list of platforms supported by this image (linux/amd64, etc) +# containsSecurityUpdates: Whether this package version contains security updates (optional, boolean) +# operator: Whether this package is an Operator (optional, boolean) +# deprecated: Whether this package is deprecated (optional, boolean) +# prerelease: Whether this package version is a pre-release (optional, boolean) +# keywords: # (optional) +# - A list of keywords about this package +# - Using one or more categories names as keywords will improve package visibility +# links: # (optional) +# - name: Title of the link (required for each link) +# url: URL of the link (required for each link) +# readme: | # (optional, can be provided from a README.md file as well) +# Package documentation in markdown format + +# Content added here will be rendered on Artifact Hub +# install: | # (optional) +# Brief install instructions in markdown format + +# Content added here will be displayed when the INSTALL button on the package details page is clicked. +# changes: # (optional - it is also possible to provide a list of strings with just the descriptions instead of using objects) +# - kind: added # Supported kinds are: added, changed, deprecated, removed, fixed and security +# description: cool feature +# links: +# - name: GitHub Issue +# url: https://github.com/issue-url +# - name: GitHub PR +# url: https://github.com/pr-url +# - kind: fixed +# description: minor bug +# links: +# - name: GitHub Issue +# url: https://github.com/issue-url +# maintainers: # (optional) +# - name: The maintainer name (required for each maintainer) +# email: The maintainer email (required for each maintainer) +# provider: # (optional) +# name: The name of the individual, company, or service that provides this package +# ignore: # (optional, used to ignore some falco rules or opa policies files in a package) +# - lib # Entries use .gitignore syntax) +# recommendations: # (optional, list of recommended packages) +# - url: https://artifacthub.io/packages/helm/artifact-hub/artifact-hub +# screenshots: # (optional, list of screenshots) +# - title: Sample screenshot 1 +# url: https://example.com/screenshot1.jpg +# - title: Sample screenshot 2 +# url: https://example.com/screenshot2.jpg +# annotations: # (optional, keys and values must be strings) +# key1: value1 +# key2: value2 \ No newline at end of file