diff --git a/.github/workflows/publish-helm-chart.yml b/.github/workflows/publish-helm-chart.yml new file mode 100644 index 0000000..d9a2a7b --- /dev/null +++ b/.github/workflows/publish-helm-chart.yml @@ -0,0 +1,34 @@ +name: Release Charts + +on: + push: + branches: + - master + +jobs: + release: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write + runs-on: ubuntu-latest + 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.2.0 + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 + with: + charts_dir: Helm + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" \ No newline at end of file diff --git a/Docker/PlexAniSync/run/runsync.sh b/Docker/PlexAniSync/run/runsync.sh index 9766488..7d5a8ad 100755 --- a/Docker/PlexAniSync/run/runsync.sh +++ b/Docker/PlexAniSync/run/runsync.sh @@ -23,4 +23,3 @@ else echo "Using custom config: "${SETTINGS_FILE} run fi - diff --git a/Helm/plexanisync/Chart.yaml b/Helm/plexanisync/Chart.yaml new file mode 100644 index 0000000..87b437a --- /dev/null +++ b/Helm/plexanisync/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: plexanisync +version: 0.1.0 +description: Plex AniSync helm chart +type: "application" +maintainers: + - name: Brad Holland + email: hollanbm@gmail.com + url: https://www.github.com/hollanbm diff --git a/Helm/plexanisync/README.md b/Helm/plexanisync/README.md new file mode 100644 index 0000000..e26996d --- /dev/null +++ b/Helm/plexanisync/README.md @@ -0,0 +1,57 @@ +# plexanisync helm chart + +## Values + +| Name | Description | Default Value | Example | +| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `nameOverride` | String to partially override plexanisync.fullname template (will maintain the release name) | `""` | | +| `fullnameOverride` | String to fully override plexanisync.fullname template | `""` | | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | | +| `custom_mappings` | Contents of custom_mappings.yaml recomended multiline yaml string. | `""` |
custom_mappings: \|| +| `envVars` | Additional EnvVars to define in the plexanisync container | `[]` |
remote-urls:
- https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/series-tvdb.en.yaml
- https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/movies-tmdb.en.yaml
EnvVars:| +| `image` | container image to use | `ghcr.io/rickdb/plexanisync:latest` | | +| `resources` | plexanisync container resource requests/limits |
- name: KEY
value: "VALUE"
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '100m'
memory: 256Mi | | +| `settings` | [plexanisync environment variable settings](https://github.com/RickDB/PlexAniSync/tree/master/Docker/PlexAniSync#environment-variables) |settings:|
plex_section: Anime\|Anime Movies
plex_url:
ani_username:
plex_episode_count_priority:
sync_ratings:
skip_list_update:
schedule:settings:| +| `settings.schedule` | Cron schedule, see [crontab.guru](https://crontab.guru/#*_*/1_*_*_*) for more information | `'* */1 * * *'` | +| `tokens` | plex and anilist tokens |
plex_section: Anime\|Anime Movies
plex_url: https://plex.tld.org
ani_username: username
plex_episode_count_priority: true
sync_ratings: false
skip_list_update: true
schedule: "* */1 * * *"tokens:|
ani:
plex:tokens:| +| `podSecurityContext` | [pod security context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#securitycontext-v1-core) | `{}` | | +| `containerSecurityContext` | [container security context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#securitycontext-v1-core) | `{}` | | +| `volumes` | Additional [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) to define in the pod | `[]` | | +| `volumeMounts` | volumeMounts for additional volumes | `[]` | | +| `cronjob` | CronJob configuration, most users will most likely omit these, as the defaults should be sufficient |
ani: ani-token
plex: plex-tokencronjob:| +### Settings + +* If an optional setting is not defined, the environment variable will not be set. This will then use the plexanisync container image default for that particular setting + +* This chart does not provide *native* support for the following plexanisync settings. + * SETTINGS_FILE + * LOG_FAILED_MATCHES + + * It is possible to enable these features using a combination of the envVars, volumes, and volumeMounts + +#### Example values.yaml + +```yaml +custom_mappings: | + remote-urls: + - https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/series-tvdb.en.yaml + entries: + - title: The Rising of the Shield Hero + seasons: + - season: 1 + anilist-id: 99263 + +settings: + plex_section: Anime|Anime Movies + plex_url: https://plex.tld.org + ani_username: UserName + plex_episode_count_priority: true + sync_ratings: false + skip_list_update: true + schedule: "* */1 * * *" + +tokens: + ani: ani-token + plex: plex-token + +``` diff --git a/Helm/plexanisync/templates/_commom.tpl b/Helm/plexanisync/templates/_commom.tpl new file mode 100644 index 0000000..14341dc --- /dev/null +++ b/Helm/plexanisync/templates/_commom.tpl @@ -0,0 +1,62 @@ +{{/* +Not using enough of the bitnami common library chart, to warrant a full chart dependency +https://github.dev/bitnami/charts/blob/main/bitnami/common +*/}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Kubernetes standard labels +{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}} +*/}} +{{- define "common.labels.standard" -}} +app.kubernetes.io/name: {{ include "common.names.name" . | quote }} +helm.sh/chart: {{ include "common.names.chart" . | quote }} +app.kubernetes.io/instance: {{ .Release.Name | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +{{- end -}} + +{{/* +Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector +*/}} +{{- define "common.labels.matchLabels" -}} +app.kubernetes.io/name: {{ include "common.names.name" . | quote }} +app.kubernetes.io/instance: {{ .Release.Name | quote }} +{{- end -}} diff --git a/Helm/plexanisync/templates/configmap.yaml b/Helm/plexanisync/templates/configmap.yaml new file mode 100644 index 0000000..bafb1d3 --- /dev/null +++ b/Helm/plexanisync/templates/configmap.yaml @@ -0,0 +1,11 @@ +{{- if .Values.custom_mappings }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . }} + labels: {{- include "common.labels.standard" . | nindent 4}} +data: + custom_mappings.yaml: | + {{- .Values.custom_mappings | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/Helm/plexanisync/templates/cronjob.yaml b/Helm/plexanisync/templates/cronjob.yaml new file mode 100644 index 0000000..2c5ab61 --- /dev/null +++ b/Helm/plexanisync/templates/cronjob.yaml @@ -0,0 +1,91 @@ +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{- include "common.labels.standard" . | nindent 4}} +spec: + concurrencyPolicy: {{ .Values.cronjob.concurrencyPolicy }} + failedJobsHistoryLimit: {{ .Values.cronjob.failedJobsHistoryLimit }} + schedule: {{ .Values.settings.schedule | quote }} + startingDeadlineSeconds: {{ .Values.cronjob.startingDeadlineSeconds }} + successfulJobsHistoryLimit: {{ .Values.cronjob.successfulJobsHistoryLimit }} + metadata: + labels: {{- include "common.labels.standard" . | nindent 6 }} + jobTemplate: + spec: + template: + spec: + metadata: + labels: {{- include "common.labels.standard" . | nindent 14 }} + {{- with .Values.podSecurityContext }} + securityContext: {{ toYaml . | nindent 8 -}} + {{ end }} + restartPolicy: Never + containers: + - name: {{ include "common.names.name" . }} + image: {{ .Values.image }} + {{- with .Values.containerSecurityContext }} + securityContext: {{ toYaml . | nindent 14 -}} + {{ end }} + env: + - name: INTERVAL + value: "0" + - name: PLEX_SECTION + value: {{ .Values.settings.plex_section | quote }} + - name: PLEX_URL + value: {{ .Values.settings.plex_url | required ".Values.settings.plex_url is required" | quote }} + - name: ANI_USERNAME + value: {{ .Values.settings.ani_username | required ".Values.settings.ani_username is required" | quote }} + - name: PLEX_TOKEN + valueFrom: + secretKeyRef: + key: plex-token + name: {{ include "common.names.fullname" . }} + - name: ANI_TOKEN + valueFrom: + secretKeyRef: + key: ani-token + name: {{ include "common.names.fullname" . }} + {{- if .Values.settings.plex_episode_count_priority }} + - name: PLEX_EPISODE_COUNT_PRIORITY + value: {{ .Values.settings.plex_episode_count_priority | quote }} + {{- end }} + {{- if .Values.settings.sync_ratings }} + - name: SYNC_RATINGS + value: {{ .Values.settings.sync_ratings | quote }} + {{- end }} + {{- if .Values.settings.skip_list_update }} + - name: SKIP_LIST_UPDATE + value: {{ .Values.settings.skip_list_update | quote }} + {{- end }} + {{- with .Values.envVars }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{ with .Values.resources -}} + resources: {{- toYaml . | nindent 16 }} + {{- end }} + {{- if or .Values.custom_mappings .Values.volumeMounts }} + volumeMounts: + {{- if .Values.custom_mappings }} + - mountPath: /plexanisync/custom_mappings.yaml + name: {{ include "common.names.fullname" . }} + subPath: custom_mappings.yaml + {{- end }} + {{- if .Values.volumeMounts }} + {{- toYaml .Values.volumeMounts | nindent 2 -}} + {{- end }} + {{- end }} + {{- if or .Values.custom_mappings .Values.volumes }} + volumes: + {{- if .Values.custom_mappings }} + - configMap: + defaultMode: 0777 + name: {{ include "common.names.fullname" . }} + name: {{ include "common.names.fullname" . }} + {{- end }} + {{- if .Values.volumes }} + {{- toYaml .Values.volumes | nindent 2 }} + {{- end }} + {{- end }} diff --git a/Helm/plexanisync/templates/secret.yaml b/Helm/plexanisync/templates/secret.yaml new file mode 100644 index 0000000..fe0acd5 --- /dev/null +++ b/Helm/plexanisync/templates/secret.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ include "common.names.namespace" . | quote }} + labels: {{ include "common.labels.standard" . | nindent 4}} +type: Opaque +stringData: + plex-token: {{ .Values.tokens.plex | required ".Values.tokens.plex is required" }} + ani-token: {{ .Values.tokens.ani | required ".Values.tokens.ani is required" }} diff --git a/Helm/plexanisync/values.yaml b/Helm/plexanisync/values.yaml new file mode 100644 index 0000000..9395207 --- /dev/null +++ b/Helm/plexanisync/values.yaml @@ -0,0 +1,43 @@ +nameOverride: +fullnameOverride: +namespaceOverride: + +custom_mappings: + +envVars: [] + +cronjob: + concurrencyPolicy: Forbid + failedJobsHistoryLimit: 2 + startingDeadlineSeconds: 300 + successfulJobsHistoryLimit: 1 + +image: ghcr.io/rickdb/plexanisync:latest + +resources: + limits: + cpu: '1' + memory: 1Gi + requests: + cpu: 100m + memory: 256Mi + +settings: + plex_section: Anime|Anime Movies + plex_url: + ani_username: + plex_episode_count_priority: + sync_ratings: + skip_list_update: + schedule: "* */1 * * *" + +containerSecurityContext: + +podSecurityContext: + +tokens: + ani: + plex: + +volumes: [] +volumeMounts: [] \ No newline at end of file
concurrencyPolicy: Forbid
failedJobsHistoryLimit: 2
startingDeadlineSeconds: 300
successfulJobsHistoryLimit: 1