diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..f4c6572 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,34 @@ +--- +name: Continuous integration + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + yamllint: + name: Yaml lint + uses: theautomation/github-actions/.github/workflows/yamllint.yaml@main + + build-and-push-image: + name: Build and Push Image + needs: [home-assistant, yamllint] + uses: theautomation/github-actions/.github/workflows/build-and-push.yaml@main + with: + publish: true + + dispatch-update-manifest: + name: Repository Dispatch to Update Manifest + runs-on: ubuntu-latest + steps: + - name: Repository Dispatch + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.PAT }} + repository: theautomation/gitops + event-type: update-manifest + client-payload: + '{"ref": "${{ github.ref }}", "repository": "${{ + github.repository}}", "registry": "ghcr.io", "sha": "${{ github.sha + }}"}' diff --git a/deploy/container/Containerfile b/Dockerfile similarity index 97% rename from deploy/container/Containerfile rename to Dockerfile index a935619..1f47eb3 100644 --- a/deploy/container/Containerfile +++ b/Dockerfile @@ -6,7 +6,6 @@ RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production COPY ./src/data/ /data/ -# INSTALL PACKAGES RUN npm install \ node-red-contrib-calc \ node-red-contrib-cron-plus \ diff --git a/cicd/.yamllint.yaml b/cicd/.yamllint.yaml deleted file mode 100644 index a415b3e..0000000 --- a/cicd/.yamllint.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -rules: - braces: enable - brackets: enable - colons: enable - commas: enable - comments: - level: warning - comments-indentation: - level: warning - document-end: disable - document-start: - level: warning - empty-lines: enable - empty-values: disable - hyphens: enable - indentation: enable - key-duplicates: enable - key-ordering: disable - line-length: - level: warning - max: 88 - new-line-at-end-of-file: enable - new-lines: enable - octal-values: disable - quoted-strings: disable - trailing-spaces: enable - truthy: - level: warning diff --git a/cicd/pipeline.yaml b/cicd/pipeline.yaml deleted file mode 100644 index bd052bb..0000000 --- a/cicd/pipeline.yaml +++ /dev/null @@ -1,149 +0,0 @@ ---- -kind: pipeline -type: docker -name: validate - -steps: - - name: yamllint - image: sdesbure/yamllint:latest - commands: - - yamllint -c ./cicd/.yamllint.yaml . - ---- -kind: pipeline -type: docker -name: build - -depends_on: - - validate - -steps: - - name: build and push image - image: quay.io/buildah/stable - privileged: true - network_mode: host - environment: - REGISTRY_HOST: "harbor.lan.theautomation.nl/k8s" - CONTAINERFILE: "./deploy/container/Containerfile" - STORAGE_DRIVER: "overlay" - FORMAT: "docker" - CONTEXT: "." - TLSVERIFY: "false" - USERNAME: "robot-drone" - PASSWORD: - from_secret: harbor_registry_drone_password - commands: - - | - echo "Build image..." - buildah --storage-driver=$${STORAGE_DRIVER} bud --format=$${FORMAT} \ - --tls-verify=$${TLSVERIFY} -f $${CONTAINERFILE} \ - -t $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:latest \ - -t $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER} \ - --layers=true $${CONTEXT} - - | - echo "Push image with latest tag..." - buildah push --creds=$${USERNAME}:$${PASSWORD} \ - --tls-verify=$${TLSVERIFY} \ - $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:latest \ - docker://$${REGISTRY_HOST}/$${DRONE_REPO_NAME}:latest - - | - echo "Push image with buildnumber tag..." - buildah push --creds=$${USERNAME}:$${PASSWORD} \ - --tls-verify=$${TLSVERIFY} \ - --digestfile=/tmp/image-digest \ - $${REGISTRY_HOST}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER} \ - docker://$${REGISTRY_HOST}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER} - ---- -kind: pipeline -type: docker -name: deploy - -depends_on: - - build - -steps: - - name: upgrade k8s manifest - image: alpine:3 - network_mode: host - environment: - REGISTRY_NAME: "k8s" - commands: - - sed -i -e - "s%/$${REGISTRY_NAME}/$${DRONE_REPO_NAME}:.*%/$${REGISTRY_NAME}/$${DRONE_REPO_NAME}:$${DRONE_BUILD_NUMBER}\"%1" - ./deploy/k8s/manifest.yaml - - - name: push k8s manifest - image: appleboy/drone-git-push:1-linux-amd64 - settings: - remote_name: "git@github.com:${DRONE_REPO}" - branch: ${DRONE_BRANCH} - force: false - commit: true - commit_message: "[bot] [skip ci] bump image tag" - author_name: ci-bot - ssh_key: - from_secret: github_ssh_key - - - name: apply k8s manifest - image: bitnami/kubectl - volumes: - - name: kubeconfig - path: /.kube - network_mode: host - commands: - - cat ./deploy/k8s/manifest.yaml - - kubectl apply -f ./deploy/k8s/manifest.yaml - -volumes: - - name: kubeconfig - host: - path: /var/lib/.kube - ---- -kind: pipeline -type: docker -name: notify - -depends_on: - - deploy - -trigger: - status: - - success - - failure - -steps: - - name: slack - image: plugins/slack - settings: - webhook: - from_secret: slack_webhook_url - channel: cicd - template: > - {{#success build.status}} - Build and deploy {{build.number}} of {{repo.name}} succeeded. - {{else}} - Build and deploy {{build.number}} of {{repo.name}} failed. - {{/success}} - ---- -kind: secret -name: harbor_registry_drone_password -get: - path: harbor-registry-drone-password - name: harbor-robot-password - ---- -kind: secret -name: github_ssh_key -get: - path: github-ssh-keys - name: id_rsa - ---- -kind: secret -name: slack_webhook_url -get: - path: slack-webhook-url - name: url diff --git a/deploy/k8s/manifest.yaml b/deploy/k8s/manifest.yaml deleted file mode 100644 index df7f027..0000000 --- a/deploy/k8s/manifest.yaml +++ /dev/null @@ -1,173 +0,0 @@ ---- -kind: SealedSecret -apiVersion: bitnami.com/v1alpha1 -metadata: - name: settings - namespace: home-automation -spec: - encryptedData: - adminAuth_password: AgDrunVqVva0KwWuS0TH4y4PVsBAf7BCQhmEDH4g/ZtVGEcV8raqMNpOJsc2wJcXQDVlGginpPpcoKssCd9P/od9cJ0Zqc9HKbdBsGz6TG33RxAd0y14SWSKwVDW76ebt3vVzVV01BoVAe6CmFxVwWlNvQakYwsEf65GyMV0MX2NPT+uIkUawzoagKfSRVDl91usgAFXfut0XHU09zqPsvVc/lX/BZGK2vkfBlAOlr6krCkFzFc3SluuaDsNDNm+QNOkBr6oDvGp62xZEwp8zlj679SYo9MD8ePuHv6JSRx3Ij2rc5wtBr/zZs5n52NvrCf+1glZDPut2VvcnmnUx6sQ7P6K8ye5foPb6qpjzWUZsW+VSb0poEhF3b/ys18S2oDKpfcyTOFHqiLOgtB0RIG+Ho9UqV0CANAj6HaihhG1V0RmbRXmWnp+1OpjmMa3wjuKscIM9ctlWHZzoUEyIMoHiCQdJXVHG8Kwx0OIunSz5NNsc2/Dv+Qn4JsF83ejrvNIqRJcEwb/hEJYy3wnDDji4amKod0ifSh3GmgrwKRHMAO8wMilOkuFx61enuAumpqUEbAOnlzAmICNgGdBfPbt4WgfdBfp/7ZHcNWmnhRyQ/b2BPmLdXSc5MbUZIjVMDymjBW/MyED0yedjZs7X591dFc5b+0YQCVcG1eaJqd9rysG/hN5mBQ1Nl4SzcuMNMRo2kOstZ23UEEDJUMoXa75NeJzXv+RInjLZdHHL27dVcIY4e1eA3xvr+u6U+wwlNxxt9bJgCHnXGkxwvc= - credentialSecret: AgA9chRLY7JomV6NQMjXmPVdKKXPhYAo1e62Z/ybEmBJy8bSnwy1rp6Tf84ExieG80a+E+Ripze6a3aDiwinxVXoq+a1zPd8YVji1SocKHxThz51cDx1f0aSuBPRgPI0+zscSc8lXJNuNISRZ9vlhvLV7zFlrFfIcOk3E8w02YZ1ef/BkA57fJIxuoC5YhWblFCw0/kTuq2nHzdzhjW12929+vVkLV4b0qfljSLjyMRXyb1X/9edbHfdPb5mWcZ/ivxm/qq6+ndH2sNRc6VtVbDwSc0H+LwpNmFnGBBACkx7bDeK8n2dbEDbq2ysz5r3ZMdlovg/77U7AnsNqqMrEsYi/g0t+EgvMzEDKeaW+UCt7dgBerpi4KXPQJypWd8HmdKACkXUKC2mpdEfn4aW1c6Srz9ai9tWiY2tIVoVea7/CbVUKktzYdLh+vZSAimPW5VSSZk6MOkOxgmBNU0gTjNKxbjKmSUXp7XdlNnVHFkDZ+ArOwzlFutyVRBD+UBYpKpNJ3c82gh3cJgdp+woxcYA9rm+hk8zdB98JNoiXNzU6fnkcRM/OoNfErAOw9d0Rn6gt13WrCJN8S5D87aqd+2RcJ/Dxb1BFNoL1tahuJhkj4MmInwrqZJ0pntzGpPQadc3DqrxK3YfKVgyM8+7a5z4wmXCYmHC3oVNerHtkQmFILIkoEJU+HzPP0pp4xLjODb4tivAdPKlMABJE90XabL8jz1kg+TlZg== - httpAuth: AgBEwm9YTjWVlBYAuWXemk/NUZvEmPh1SQinA4pFcmVoKLVxXFvrmSqc1GXtF/oatKZtcrSdPwwbTfFpbC1goaQF1HM18lnhnJcajMkSPmJ/tAZsQDi/XlrH6qasgguPZ0TBWXdX1gS+S7MpP/iAoXMa3gwRRrUHmeqYYg5mC74RM3e/AXXT8gPsTPj+ZzuostyZzHzrGC2AZiEMLhvfj5tOglLj3yfOjAcDlMbIPsfpUSysXwm8eNC/VWr9tso1NSgh7o2ZDO9RYYSvYuWv62T/2oKLLUSF6eqeI4Yznrk3HqUQDXMT4ZBYviKead5chW9WVfm2LxGAh1PPzX48iFN4stvQ9MefteE1gW8pB0p7+suDQgNLblMYF40W+oP94l/YE6Ywd/GNUIjmWz1ue5zU2opNprjpyamek1lWJ4MmooggNnejAuIg9jiPZx2YnI2MokFobp6GIqAQYjr02giqdmQT+LUK6OPCr4AHCPES7H8OPqY0/tYV8pGQ4lKgukUBjWl2JAAQ7HLhyH8E9kaGTK2DijN6NPcYzpSk44vBR1BKijNz+so8yUX4TnVov0VY47fQKMouupqNnAkq4CBxlHx9D57ky+0IDwFK7dX57HCBZPKstN1xGLDGzXDVLrILpWucDD2Q2H38hcsQPIGSxCAl2CtaRcqMDSI+apzOqwDGHoAnNpbnU+lGi+7YTpXxcXl0Nm9EXrocC/WngA+Q4B76XfnIBm1jsk0w9gg/6CYiAfW0XAYfCn5wko2sCbuchNq4wjAjkzv2U8A= - template: - data: - settings.js: |- - module.exports = { - flowFile: 'flows.json', - credentialSecret: "{{ index . "credentialSecret" }}", - flowFilePretty: true, - adminAuth: { - type: "credentials", - users: [{ - username: "admin", - password: "{{ index . "adminAuth_password" }}", - permissions: "*" - }] - }, - httpNodeAuth: {user:"nodered-endpoint",pass:"{{ index . "httpAuth" }}"}, - httpStaticAuth: {user:"nodered-endpoint",pass:"{{ index . "httpAuth" }}"}, - uiPort: process.env.PORT || 1880, - logging: { - console: { - level: "info", - metrics: false, - audit: false - } - }, - exportGlobalContextKeys: false, - externalModules: {}, - editorTheme: { - palette: {}, - projects: { - enabled: false, - workflow: { - mode: "manual" - } - }, - codeEditor: { - lib: "monaco", - } - }, - tours: false, - functionExternalModules: true, - functionGlobalContext: {}, - debugMaxLength: 1000, - mqttReconnectTime: 15000, - serialReconnectTime: 15000, - } - metadata: - name: settings - namespace: home-automation - labels: - app: node-red - ---- -kind: SealedSecret -apiVersion: bitnami.com/v1alpha1 -metadata: - name: spotify-api-credentials - namespace: home-automation -spec: - encryptedData: - SPOTIFY_API_CLIENT_ID: AgDEUeoaWFdyR760gPnYU5zFE2T0SGPwu0VRb/EHyFs+XlJvgvmeaq2BEhrlF04310NukPsvtaYg0cCcYRF3AFsWkMuIcXZ5XJs3Lj3C/xOuiEa5DhKzedRom/umMcJDJxokY9Zs+Clk0/A3Yy9f3FHqV5pQUxwFoENAzfphv380aZMxlzp1EB+IzrC5qdEa0LjhRNMdzxXhMmHVaFD0UcUijbIlCyMV22SS3t/o7HX/pWdXI9HkLhi1L/3v3ieW2dtjCylW6/6DnNy8yixqiwCjvXqKFZscCPKGQZy7YSuuSpA3SzUM7yoCqiDq1m8VsydyWQZI98oUEEExi7C7ILHrwXpwvUhoOEmeuWCX+84a3PaVxmOX4k37lYw0bvUUmmi6Xi+p4pz0K/ebG/+wYOlfyyPbPi6i5fP/4V3VmBshzXEwqSAPV9m/beVd2qMNA44OA1eSjzPWw2gkJwpJhoAwfXYyy/nktxUyaLepfaZ4MHI2uDvr8zAEwvZ35zsNRNm5xVoOCWyEN/Ck0M8nOct8O0XWnKESidqmGx8BDo64Jb2/7NX8+MZduBR9IBkbLyskwKhUwrnX6roWhT7Mi9SRcw21XMCIWsDlTPobG1GTQOhllZC5fS6SzUtyX6ajPU/SZDBzrvt/u1A0v071SOtmMOet59RCyoW2CVDMqonpVlCAppLVEE+sl2jDODxU6wc8GV/IK+ct/GVwKI/TZ0OqiNVf5ifVuzbsMZAdmj65Mw== - SPOTIFY_API_CLIENT_SECRET: AgA8Oxhk31tEI3wnkWhaY5LuY1v2FL/gkt2udQ3eBzJATukf67bWlJlop3UyF/duZf6AgjZur3ev/hDESi6B7/hs+BHbUbtfKjfSBs1s3KdjOByN/UkhA+48OkEIvbuO5jHKkASMsScA2Kw30vvwr3MR4q7UskR2aEITedoJ/bdGgXTCHA0IFbj2OvUN8fgv3YPcaYmRLb3YAq6eZyQIwotIGWeRaMXWfZ2dOS9T3Rd/IASkEfKwToANMfjXES5lkRTByrHwzbi/SAhLiGLG2dAgvuDsZjVpigga4SynB/sgCeAAXrlBUcFTQTYlLnoE+u8kRtDVLg8dzkuCE8FBdjeTVnIiLHe2tbkULe9LM9Q/1WR3xq7k7eU7FvIX06Lv97/dm8Jk/OOOY5nmZC8vWcuAWJ6BZ4SaJfJ2kc6cyIrX/uP5DVPoXRgZCNrPUCrRtAzhe2jX8VyWQAK1xDvQf0qdMOPE4KOsjgaT/jlilAaLouOVFka3khPt7tTzz9sFOAbAaukLHsFdmLoatmWnnw9yVj7cCZWQCay88H3lTd3riu6VXKq58TnTC6t8Dmuqx4TQDAuJazRQKP/fbTffKaBq/QfwVod7zEFZOkSKIqEngs01hHoOhu1AHjctiOEnityzcVSsa9rxDM/MV0aPzJnMiLXpgKsHdLqZjiWC2N9FqjrNl73DWx9E2OytEjCJTGWgtyHYLlqcSpsV3TnDati+zDg2NfsR05XZ2kzf6z69/w== - template: - metadata: - labels: - app.kubernetes.io/component: server - app.kubernetes.io/instance: production - app.kubernetes.io/name: node-red - app.kubernetes.io/part-of: node-red - name: spotify-api-credentials - namespace: home-automation - type: Opaque - ---- -kind: Deployment -apiVersion: apps/v1 -metadata: - name: node-red - namespace: home-automation - labels: - app: node-red -spec: - replicas: 1 - selector: - matchLabels: - app: node-red - template: - metadata: - labels: - app: node-red - spec: - containers: - - name: node-red - image: "harbor.lan.theautomation.nl/k8s/node-red:415" - imagePullPolicy: Always - resources: {} - ports: - - containerPort: 1880 - protocol: TCP - envFrom: - - secretRef: - name: spotify-api-credentials - optional: true - env: - - name: TZ - value: Europe/Amsterdam - - name: PGID - value: "1000" - - name: PUID - value: "1000" - volumeMounts: - - name: settings - mountPath: /data/settings.js - subPath: settings.js - volumes: - - name: settings - secret: - secretName: settings - imagePullSecrets: - - name: harbor-registry-creds - ---- -kind: Service -apiVersion: v1 -metadata: - name: node-red - namespace: home-automation - labels: - app: node-red -spec: - selector: - app: node-red - type: ClusterIP - ports: - - port: 1880 - protocol: TCP - targetPort: 1880 - sessionAffinity: None - ---- -kind: Ingress -apiVersion: networking.k8s.io/v1 -metadata: - name: node-red - namespace: home-automation - labels: - app: node-red - annotations: - nginx.ingress.kubernetes.io/force-ssl-redirect: "false" -spec: - ingressClassName: nginx-private - rules: - - host: node-red.lan.theautomation.nl - http: - paths: - - path: "/" - pathType: Prefix - backend: - service: - name: node-red - port: - number: 1880