├── .gitattributes ├── .github ├── release-drafter.yml └── workflows │ ├── build-push.yaml │ ├── codeql.yaml │ ├── helm-deploy.yaml │ ├── owasp-scan.yaml │ ├── pre-commit-check.yaml │ ├── release.yaml │ ├── sonar-scanner-mvn.yaml │ ├── sonar-scanner.yaml │ ├── testing.yaml │ ├── trivy-container.yaml │ ├── trivy-repo.yaml │ └── version.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── COMPLIANCE.yaml ├── LICENSE ├── README.md ├── _config.yml ├── demo ├── flask-web │ ├── Dockerfile │ ├── app.py │ ├── docker-build.yaml │ ├── helm │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── ingress.yaml │ │ │ ├── route.yaml │ │ │ ├── service.yaml │ │ │ ├── serviceaccount.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── requirements.txt │ ├── static │ │ ├── favicon.png │ │ ├── fontawesome-all.min.css │ │ ├── fonts │ │ │ ├── fa-brands-400.eot │ │ │ ├── fa-brands-400.svg │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-brands-400.woff │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.eot │ │ │ ├── fa-regular-400.svg │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.eot │ │ │ ├── fa-solid-900.svg │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-solid-900.woff │ │ │ └── fa-solid-900.woff2 │ │ ├── images │ │ │ └── banner.jpg │ │ ├── js │ │ │ ├── breakpoints.min.js │ │ │ ├── browser.min.js │ │ │ ├── demo.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.scrollex.min.js │ │ │ ├── jquery.scrolly.min.js │ │ │ ├── main.js │ │ │ └── util.js │ │ ├── main.css │ │ ├── noscript.css │ │ └── sass │ │ │ ├── base │ │ │ ├── _page.scss │ │ │ ├── _reset.scss │ │ │ └── _typography.scss │ │ │ ├── components │ │ │ ├── _actions.scss │ │ │ ├── _banner.scss │ │ │ ├── _box.scss │ │ │ ├── _button.scss │ │ │ ├── _form.scss │ │ │ ├── _gallery.scss │ │ │ ├── _icon.scss │ │ │ ├── _icons.scss │ │ │ ├── _image.scss │ │ │ ├── _index.scss │ │ │ ├── _items.scss │ │ │ ├── _list.scss │ │ │ ├── _row.scss │ │ │ ├── _section.scss │ │ │ ├── _spotlight.scss │ │ │ ├── _table.scss │ │ │ └── _wrapper.scss │ │ │ ├── layout │ │ │ └── _wrapper.scss │ │ │ ├── libs │ │ │ ├── _breakpoints.scss │ │ │ ├── _functions.scss │ │ │ ├── _html-grid.scss │ │ │ ├── _mixins.scss │ │ │ ├── _vars.scss │ │ │ └── _vendor.scss │ │ │ ├── main.scss │ │ │ └── noscript.scss │ └── templates │ │ └── index.html ├── maven-test │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── mycompany │ │ │ └── app │ │ │ └── App.java │ │ └── test │ │ └── java │ │ └── com │ │ └── mycompany │ │ └── app │ │ └── AppTest.java └── nginx │ ├── .helmignore │ ├── Chart.yaml │ ├── Dockerfile │ ├── LICENSE.txt │ ├── assets │ ├── css │ │ ├── fontawesome-all.min.css │ │ ├── main.css │ │ └── noscript.css │ ├── js │ │ ├── breakpoints.min.js │ │ ├── browser.min.js │ │ ├── demo.js │ │ ├── jquery.min.js │ │ ├── jquery.scrollex.min.js │ │ ├── jquery.scrolly.min.js │ │ ├── main.js │ │ └── util.js │ ├── sass │ │ ├── base │ │ │ ├── _page.scss │ │ │ ├── _reset.scss │ │ │ └── _typography.scss │ │ ├── components │ │ │ ├── _actions.scss │ │ │ ├── _banner.scss │ │ │ ├── _box.scss │ │ │ ├── _button.scss │ │ │ ├── _form.scss │ │ │ ├── _gallery.scss │ │ │ ├── _icon.scss │ │ │ ├── _icons.scss │ │ │ ├── _image.scss │ │ │ ├── _index.scss │ │ │ ├── _items.scss │ │ │ ├── _list.scss │ │ │ ├── _row.scss │ │ │ ├── _section.scss │ │ │ ├── _spotlight.scss │ │ │ ├── _table.scss │ │ │ └── _wrapper.scss │ │ ├── layout │ │ │ └── _wrapper.scss │ │ ├── libs │ │ │ ├── _breakpoints.scss │ │ │ ├── _functions.scss │ │ │ ├── _html-grid.scss │ │ │ ├── _mixins.scss │ │ │ ├── _vars.scss │ │ │ └── _vendor.scss │ │ ├── main.scss │ │ └── noscript.scss │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 │ ├── helm │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── deployment.yaml │ │ ├── hpa.yaml │ │ ├── ingress.yaml │ │ ├── service.yaml │ │ └── serviceaccount.yaml │ └── values.yaml │ ├── images │ ├── banner.jpg │ └── favicon.png │ ├── index.html │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ └── serviceaccount.yaml │ └── values.yaml ├── docs ├── github.md └── tekton.md ├── sonar-project.properties └── tekton ├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── base ├── pipelines │ ├── buildah.yaml │ ├── codeql.yaml │ ├── helm-build-deploy.yaml │ ├── kustomization.yaml │ ├── maven.yaml │ ├── owasp.yaml │ ├── react.yaml │ ├── sonar.yaml │ └── trivy.yaml ├── tasks │ ├── add-issue.yaml │ ├── buildah.yaml │ ├── codeql │ │ ├── Dockerfile │ │ ├── codeql.yaml │ │ └── kustomization.yaml │ ├── create-pr.yaml │ ├── deploy.yaml │ ├── generate-id.yaml │ ├── git-clone.yaml │ ├── helm-deploy.yaml │ ├── kustomization.yaml │ ├── mvn-build.yaml │ ├── mvn-sonar-scan.yaml │ ├── npm-sonar-scan.yaml │ ├── npm.yaml │ ├── owasp-scanner.yaml │ ├── react-deploy.yaml │ ├── react-update.yaml │ ├── react-workspace.yaml │ ├── sonar-scanner.yaml │ ├── trivy-scanner.yaml │ └── yq.yaml └── triggers │ ├── ingress.yaml │ ├── kustomization.yaml │ ├── rbac.yaml │ ├── trigger-flask-web.yaml │ ├── trigger-maven-build.yaml │ └── trigger-react-build.yaml ├── demo ├── flask-web │ ├── Dockerfile │ ├── app.py │ ├── docker-build.yaml │ ├── helm │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── ingress.yaml │ │ │ ├── route.yaml │ │ │ ├── service.yaml │ │ │ ├── serviceaccount.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── requirements.txt │ ├── static │ │ ├── favicon.png │ │ ├── fontawesome-all.min.css │ │ ├── fonts │ │ │ ├── fa-brands-400.eot │ │ │ ├── fa-brands-400.svg │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-brands-400.woff │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.eot │ │ │ ├── fa-regular-400.svg │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.eot │ │ │ ├── fa-solid-900.svg │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-solid-900.woff │ │ │ └── fa-solid-900.woff2 │ │ ├── images │ │ │ └── banner.jpg │ │ ├── js │ │ │ ├── breakpoints.min.js │ │ │ ├── browser.min.js │ │ │ ├── demo.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.scrollex.min.js │ │ │ ├── jquery.scrolly.min.js │ │ │ ├── main.js │ │ │ └── util.js │ │ ├── main.css │ │ ├── noscript.css │ │ └── sass │ │ │ ├── base │ │ │ ├── _page.scss │ │ │ ├── _reset.scss │ │ │ └── _typography.scss │ │ │ ├── components │ │ │ ├── _actions.scss │ │ │ ├── _banner.scss │ │ │ ├── _box.scss │ │ │ ├── _button.scss │ │ │ ├── _form.scss │ │ │ ├── _gallery.scss │ │ │ ├── _icon.scss │ │ │ ├── _icons.scss │ │ │ ├── _image.scss │ │ │ ├── _index.scss │ │ │ ├── _items.scss │ │ │ ├── _list.scss │ │ │ ├── _row.scss │ │ │ ├── _section.scss │ │ │ ├── _spotlight.scss │ │ │ ├── _table.scss │ │ │ └── _wrapper.scss │ │ │ ├── layout │ │ │ └── _wrapper.scss │ │ │ ├── libs │ │ │ ├── _breakpoints.scss │ │ │ ├── _functions.scss │ │ │ ├── _html-grid.scss │ │ │ ├── _mixins.scss │ │ │ ├── _vars.scss │ │ │ └── _vendor.scss │ │ │ ├── main.scss │ │ │ └── noscript.scss │ └── templates │ │ └── index.html ├── maven-test │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── mycompany │ │ │ └── app │ │ │ └── App.java │ │ └── test │ │ └── java │ │ └── com │ │ └── mycompany │ │ └── app │ │ └── AppTest.java └── simple-react │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ └── src │ ├── App.js │ ├── Checklist.js │ ├── Task.js │ ├── index.css │ └── index.js ├── overlays ├── apply │ └── kustomization.yaml └── secrets │ ├── main.py │ └── requirements.txt ├── package-lock.json ├── scripts └── install.sh └── tekton.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | ; To make sure windows user can process the script 2 | *.sh eol=lf 3 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION 🌈' 2 | tag-template: 'v$RESOLVED_VERSION' 3 | categories: 4 | - title: '🚀 Features' 5 | labels: 6 | - 'feature' 7 | - 'enhancement' 8 | - title: '🐛 Bug Fixes' 9 | labels: 10 | - 'fix' 11 | - 'bugfix' 12 | - 'bug' 13 | - title: '🧰 Maintenance' 14 | label: 'chore' 15 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 16 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 17 | version-resolver: 18 | major: 19 | labels: 20 | - 'major' 21 | minor: 22 | labels: 23 | - 'minor' 24 | patch: 25 | labels: 26 | - 'patch' 27 | default: patch 28 | template: | 29 | ## Changes 30 | 31 | $CHANGES 32 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yaml: -------------------------------------------------------------------------------- 1 | name: codeql-scan 2 | on: 3 | workflow_dispatch: 4 | workflow_call: 5 | jobs: 6 | codeql-scan: 7 | name: codeql-scan 8 | runs-on: ubuntu-latest 9 | permissions: 10 | actions: read 11 | contents: read 12 | security-events: write 13 | 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | language: [ 'python' ] 18 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 19 | # Learn more: 20 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 21 | 22 | steps: 23 | - name: Checkout repository 24 | uses: actions/checkout@v2 25 | 26 | # Initializes the CodeQL tools for scanning. 27 | - name: Initialize CodeQL 28 | uses: github/codeql-action/init@v1 29 | with: 30 | languages: ${{ matrix.language }} 31 | # If you wish to specify custom queries, you can do so here or in a config file. 32 | # By default, queries listed here will override any specified in a config file. 33 | # Prefix the list here with "+" to use these queries and those in the config file. 34 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 35 | 36 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 37 | # If this step fails, then you should remove it and run the build manually (see below) 38 | - name: Autobuild 39 | uses: github/codeql-action/autobuild@v1 40 | 41 | # ℹ️ Command-line programs to run using the OS shell. 42 | # 📚 https://git.io/JvXDl 43 | 44 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 45 | # and modify them (or add more) to build your code if your project 46 | # uses a compiled language 47 | 48 | #- run: | 49 | # make bootstrap 50 | # make release 51 | 52 | - name: Perform CodeQL Analysis 53 | uses: github/codeql-action/analyze@v1 54 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit-check.yaml: -------------------------------------------------------------------------------- 1 | name: pre-commit 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | pre-commit: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-python@v2 13 | - uses: terraform-linters/setup-tflint@v1 14 | with: 15 | tflint_version: latest 16 | - uses: pre-commit/action@v3.0.0 17 | - name: Analyze Kustomize Manifests 18 | run: | 19 | pwd 20 | ls -al 21 | curl https://get.datree.io | /bin/bash 22 | datree test tekton/base/pipelines/* --ignore-missing-schemas --no-record 23 | echo "scanning tasks..." 24 | datree test tekton/base/tasks/* --ignore-missing-schemas --no-record 25 | echo "scan triggers..." 26 | datree test tekton/base/triggers/* --ignore-missing-schemas --no-record 27 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: release-drafter 2 | on: 3 | # pull_request event is required only for autolabeler 4 | pull_request: 5 | # Only following types are handled by the action, but one can default to all as well 6 | types: [opened, reopened, synchronize] 7 | 8 | jobs: 9 | update_release_draft: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: release-drafter/release-drafter@v5 13 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml 14 | with: 15 | config-name: release-drafter.yml 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/sonar-scanner-mvn.yaml: -------------------------------------------------------------------------------- 1 | name: sonar-maven-scan 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | PROJECT_KEY: 7 | required: true 8 | type: string 9 | WORKDIR: 10 | required: true 11 | type: string 12 | secrets: 13 | SONAR_TOKEN: 14 | required: true 15 | jobs: 16 | sonar-maven-scan: 17 | name: sonar-maven-scan 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | with: 22 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 23 | - name: Set up JDK 11 24 | uses: actions/setup-java@v1 25 | with: 26 | java-version: 11 27 | - name: Cache SonarCloud Packages 28 | uses: actions/cache@v1 29 | with: 30 | path: ~/.sonar/cache 31 | key: ${{ runner.os }}-sonar 32 | restore-keys: ${{ runner.os }}-sonar 33 | - name: Cache Maven Packages 34 | uses: actions/cache@v1 35 | with: 36 | path: ~/.m2 37 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 38 | restore-keys: ${{ runner.os }}-m2 39 | - name: Build / Analyze 40 | working-directory: ${{ inputs.WORKDIR }} 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 43 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 44 | run: mvn verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=${{ inputs.PROJECT_KEY }} 45 | -------------------------------------------------------------------------------- /.github/workflows/sonar-scanner.yaml: -------------------------------------------------------------------------------- 1 | name: sonar-repo-scan 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | ORG: 7 | required: true 8 | type: string 9 | PROJECT_KEY: 10 | required: true 11 | type: string 12 | URL: 13 | required: true 14 | type: string 15 | secrets: 16 | SONAR_TOKEN: 17 | required: true 18 | jobs: 19 | sonar-repo-scan: 20 | name: sonar-repo-scan 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Setup 24 | uses: warchant/setup-sonar-scanner@v3 25 | - name: Run Sonar Scanner 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | run: sonar-scanner 29 | -Dsonar.login=${{ secrets.SONAR_TOKEN }} 30 | -Dsonar.organization=${{ inputs.ORG }} 31 | -Dsonar.host.url=${{ inputs.URL }} 32 | -Dsonar.projectKey=${{ inputs.PROJECT_KEY }} 33 | -Dsonar.exclusions=**/*.java 34 | -Dsonar.sourceEncoding=UTF-8 35 | -------------------------------------------------------------------------------- /.github/workflows/trivy-container.yaml: -------------------------------------------------------------------------------- 1 | name: trivy-image-scan 2 | on: 3 | workflow_call: 4 | inputs: 5 | TAG: 6 | required: true 7 | type: string 8 | IMAGE: 9 | required: true 10 | type: string 11 | jobs: 12 | trivy-image-scan: 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 60 15 | steps: 16 | - name: Trivy Vulnerability Scan 17 | uses: aquasecurity/trivy-action@master 18 | with: 19 | image-ref: ${{ inputs.IMAGE }}:${{ inputs.TAG }} 20 | format: table 21 | exit-code: '0' 22 | ignore-unfixed: true 23 | vuln-type: os,library 24 | severity: CRITICAL 25 | -------------------------------------------------------------------------------- /.github/workflows/trivy-repo.yaml: -------------------------------------------------------------------------------- 1 | name: trivy-repo-scan 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | workflow_call: 8 | jobs: 9 | tricy-repo-scan: 10 | name: trivy-repo-scan 11 | runs-on: ubuntu-20.04 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v2 15 | 16 | - name: Run Trivy vulnerability scanner in repo mode 17 | uses: aquasecurity/trivy-action@master 18 | with: 19 | scan-type: 'fs' 20 | ignore-unfixed: true 21 | format: 'template' 22 | template: '@/contrib/sarif.tpl' 23 | output: 'trivy-results.sarif' 24 | severity: 'CRITICAL' 25 | 26 | - name: Upload Trivy scan results to GitHub Security tab 27 | uses: github/codeql-action/upload-sarif@v1 28 | with: 29 | sarif_file: 'trivy-results.sarif' 30 | -------------------------------------------------------------------------------- /.github/workflows/version.yaml: -------------------------------------------------------------------------------- 1 | name: bump-version 2 | on: 3 | push: #Any push will trigger this action 4 | branches: [ mybranch ] 5 | pull_request: #Any Pull Request will trigger this action 6 | branches: [ mybranch ] 7 | workflow_dispatch: 8 | workflow_call: 9 | jobs: 10 | version_bump: 11 | name: Version Bump 12 | # needs: [branch-naming-rules, owasp-zap, sonarqube-scanning] 13 | # UPDATE WITH PUSH TO MASTER 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | with: 18 | fetch-depth: '0' 19 | - name: Bump version and push tag 20 | uses: anothrNick/github-tag-action@1.26.0 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | WITH_V: true 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.creds 2 | **/.DS_Store 3 | **/*.secrets 4 | **/*.ini 5 | **/*.venv 6 | overlays/secrets/kustomization.yaml 7 | overlays/secrets/kustomization.yml 8 | .DS_Store 9 | id_rsa 10 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.0.1 4 | hooks: 5 | - id: check-docstring-first 6 | - id: debug-statements 7 | - id: name-tests-test 8 | - id: check-executables-have-shebangs 9 | - id: end-of-file-fixer 10 | - id: trailing-whitespace 11 | - id: check-json 12 | - id: check-symlinks 13 | - id: check-merge-conflict 14 | - id: check-ast 15 | - id: detect-private-key 16 | - id: fix-byte-order-marker 17 | - id: pretty-format-json 18 | - id: check-added-large-files 19 | - id: check-symlinks 20 | - id: debug-statements 21 | - repo: https://github.com/asottile/setup-cfg-fmt 22 | rev: v1.19.0 23 | hooks: 24 | - id: setup-cfg-fmt 25 | - repo: https://github.com/asottile/add-trailing-comma 26 | rev: v2.2.0 27 | hooks: 28 | - id: add-trailing-comma 29 | args: [--py36-plus] 30 | -------------------------------------------------------------------------------- /COMPLIANCE.yaml: -------------------------------------------------------------------------------- 1 | name: compliance 2 | description: | 3 | This document is used to track a projects PIA and STRA 4 | compliance. 5 | spec: 6 | - name: PIA 7 | status: completed 8 | last-updated: '2023-02-05T17:04:42.679Z' 9 | - name: STRA 10 | status: completed 11 | last-updated: '2023-02-05T17:04:42.679Z' 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BCGov Pipeline Templates 2 | 3 | [![pre-commit](https://github.com/bcgov/pipeline-templates/actions/workflows/pre-commit-check.yaml/badge.svg)](https://github.com/bcgov/pipeline-templates/actions/workflows/pre-commit-check.yaml) [![testing](https://github.com/bcgov/pipeline-templates/actions/workflows/testing.yaml/badge.svg?branch=main)](https://github.com/bcgov/pipeline-templates/actions/workflows/testing.yaml) [![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=bcgov-pipeline-templates&metric=alert_status)](https://sonarcloud.io/dashboard?id=bcgov-pipeline-templates) [![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=bcgov-pipeline-templates&metric=security_rating)](https://sonarcloud.io/dashboard?id=bcgov-pipeline-templates) [![Lifecycle:Experimental](https://img.shields.io/badge/Lifecycle-Experimental-339999)]() 4 | 5 | This repo contains a catalog of pipeline templates to kickstart development among teams. 6 | 7 | ## Documentation 8 | 9 | - [Tekton Templates](https://github.com/bcgov/pipeline-templates/tree/main/tekton) 10 | - [GitHub Templates](docs/github.md) 11 | - [ZAP Scanning Report](https://github.com/bcgov/security-pipeline-templates/blob/zap-scan/README.md) 12 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | title: "Pipeline Templates" 3 | -------------------------------------------------------------------------------- /demo/flask-web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/python:3.7-alpine 2 | WORKDIR /app 3 | 4 | COPY . . 5 | 6 | ENV FLASK_APP=./app.py 7 | ENV FLASK_RUN_HOST=0.0.0.0 8 | ENV FLASK_RUN_PORT=80 9 | 10 | RUN apk add --no-cache gcc musl-dev linux-headers 11 | RUN pip install -r requirements.txt 12 | 13 | EXPOSE 80 14 | EXPOSE 5000 15 | CMD ["flask", "run"] 16 | -------------------------------------------------------------------------------- /demo/flask-web/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | import requests 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route("/") 7 | def index(): 8 | url = "https://api.quotable.io/random" 9 | data = requests.get(url) 10 | response = data.json() 11 | quote = response["content"] 12 | author = response["author"] 13 | return render_template("index.html", quote=quote, author=author) 14 | 15 | if __name__ == "__main__": 16 | app.run() 17 | -------------------------------------------------------------------------------- /demo/flask-web/docker-build.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: PipelineRun 3 | metadata: 4 | generateName: docker-build 5 | spec: 6 | pipelineRef: 7 | name: p-docker-build 8 | params: 9 | - name: appName 10 | value: flask-web 11 | - name: repoUrl 12 | value: git@github.com:gregnrobinson/tekton.git 13 | - name: branchName 14 | value: main 15 | - name: dockerfile 16 | value: ./Dockerfile 17 | - name: pathToContext 18 | value: ./demo/flask-web 19 | - name: pathToYamlFile 20 | value: /workspace/source/tasks/deploy-using-kubectl/deployment.yaml 21 | - name: imageUrl 22 | value: gregnrobinson/tkn-flask-web 23 | - name: imageTag 24 | value: latest 25 | workspaces: 26 | - name: shared-data 27 | volumeClaimTemplate: 28 | spec: 29 | accessModes: 30 | - ReadWriteOnce 31 | resources: 32 | requests: 33 | storage: 1Gi 34 | - name: docker-config 35 | secret: 36 | secretName: tkn-docker-credentials 37 | -------------------------------------------------------------------------------- /demo/flask-web/helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /demo/flask-web/helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: web 3 | description: A Helm chart for managing a web frontend. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mychart.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mychart.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mychart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mychart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "mychart.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "mychart.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "mychart.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "mychart.labels" -}} 37 | helm.sh/chart: {{ include "mychart.chart" . }} 38 | {{ include "mychart.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "mychart.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "mychart.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "mychart.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "mychart.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "mychart.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "mychart.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "mychart.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: 80 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "mychart.fullname" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "mychart.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "mychart.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "mychart.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/route.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.route.enabled -}} 2 | apiVersion: route.openshift.io/v1 3 | kind: Route 4 | metadata: 5 | name: {{ include "mychart.fullname" . }} 6 | spec: 7 | host: {{ .Values.route.host }} 8 | port: 9 | targetPort: {{ .Values.route.port }} 10 | to: 11 | kind: Service 12 | name: {{ include "mychart.fullname" . }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | {{- with .Values.service.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | spec: 12 | type: {{ .Values.service.type }} 13 | ports: 14 | - port: {{ .Values.service.port }} 15 | targetPort: http 16 | protocol: TCP 17 | name: http 18 | selector: 19 | {{- include "mychart.selectorLabels" . | nindent 4 }} 20 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "mychart.serviceAccountName" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /demo/flask-web/helm/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "mychart.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /demo/flask-web/helm/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for mychart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 4 6 | 7 | image: 8 | repository: gregnrobinson/tkn-flask-web 9 | pullPolicy: Always 10 | tag: latest 11 | 12 | imagePullSecrets: [name: docker-config-path] 13 | nameOverride: "" 14 | fullnameOverride: "" 15 | 16 | serviceAccount: 17 | create: true 18 | annotations: {} 19 | name: "" 20 | 21 | podAnnotations: {} 22 | 23 | podSecurityContext: {} 24 | # fsGroup: 2000 25 | 26 | securityContext: {} 27 | 28 | service: 29 | type: ClusterIP 30 | port: 80 31 | annotations: {} 32 | 33 | route: 34 | enabled: true 35 | host: flask.demo.local 36 | port: 80 37 | 38 | ingress: 39 | enabled: false 40 | className: "" 41 | annotations: 42 | kubernetes.io/ingress.class: nginx 43 | nginx.ingress.kubernetes.io/use-regex: "true" 44 | hosts: 45 | - host: flask.exmaple.com 46 | paths: 47 | - path: / 48 | pathType: Prefix 49 | tls: [] 50 | # - secretName: chart-example-tls 51 | # hosts: 52 | # - chart-example.local 53 | 54 | resources: {} 55 | # We usually recommend not to specify default resources and to leave this as a conscious 56 | # choice for the user. This also increases chances charts run on environments with little 57 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 58 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 59 | # limits: 60 | # cpu: 100m 61 | # memory: 128Mi 62 | # requests: 63 | # cpu: 100m 64 | # memory: 128Mi 65 | 66 | autoscaling: 67 | enabled: false 68 | minReplicas: 1 69 | maxReplicas: 100 70 | targetCPUUtilizationPercentage: 80 71 | targetMemoryUtilizationPercentage: 80 72 | 73 | nodeSelector: {} 74 | 75 | tolerations: [] 76 | 77 | affinity: {} 78 | -------------------------------------------------------------------------------- /demo/flask-web/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | requests 3 | -------------------------------------------------------------------------------- /demo/flask-web/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/favicon.png -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-brands-400.eot -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-brands-400.woff -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-regular-400.eot -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-regular-400.woff -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-solid-900.eot -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-solid-900.woff -------------------------------------------------------------------------------- /demo/flask-web/static/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /demo/flask-web/static/images/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/flask-web/static/images/banner.jpg -------------------------------------------------------------------------------- /demo/flask-web/static/js/browser.min.js: -------------------------------------------------------------------------------- 1 | /* browser.js v1.0 | @ajlkn | MIT licensed */ 2 | var browser=function(){"use strict";var e={name:null,version:null,os:null,osVersion:null,touch:null,mobile:null,_canUse:null,canUse:function(n){e._canUse||(e._canUse=document.createElement("div"));var o=e._canUse.style,r=n.charAt(0).toUpperCase()+n.slice(1);return n in o||"Moz"+r in o||"Webkit"+r in o||"O"+r in o||"ms"+r in o},init:function(){var n,o,r,i,t=navigator.userAgent;for(n="other",o=0,r=[["firefox",/Firefox\/([0-9\.]+)/],["bb",/BlackBerry.+Version\/([0-9\.]+)/],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/],["opera",/OPR\/([0-9\.]+)/],["opera",/Opera\/([0-9\.]+)/],["edge",/Edge\/([0-9\.]+)/],["safari",/Version\/([0-9\.]+).+Safari/],["chrome",/Chrome\/([0-9\.]+)/],["ie",/MSIE ([0-9]+)/],["ie",/Trident\/.+rv:([0-9]+)/]],i=0;i0:!!("ontouchstart"in window),e.mobile="wp"==e.os||"android"==e.os||"ios"==e.os||"bb"==e.os}};return e.init(),e}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser}); 3 | -------------------------------------------------------------------------------- /demo/flask-web/static/js/jquery.scrollex.min.js: -------------------------------------------------------------------------------- 1 | /* jquery.scrollex v0.2.1 | (c) @ajlkn | github.com/ajlkn/jquery.scrollex | MIT licensed */ 2 | !function(t){function e(t,e,n){return"string"==typeof t&&("%"==t.slice(-1)?t=parseInt(t.substring(0,t.length-1))/100*e:"vh"==t.slice(-2)?t=parseInt(t.substring(0,t.length-2))/100*n:"px"==t.slice(-2)&&(t=parseInt(t.substring(0,t.length-2)))),t}var n=t(window),i=1,o={};n.on("scroll",function(){var e=n.scrollTop();t.map(o,function(t){window.clearTimeout(t.timeoutId),t.timeoutId=window.setTimeout(function(){t.handler(e)},t.options.delay)})}).on("load",function(){n.trigger("scroll")}),jQuery.fn.scrollex=function(l){var s=t(this);if(0==this.length)return s;if(this.length>1){for(var r=0;r=i&&o>=t};break;case"bottom":h=function(t,e,n,i,o){return n>=i&&o>=n};break;case"middle":h=function(t,e,n,i,o){return e>=i&&o>=e};break;case"top-only":h=function(t,e,n,i,o){return i>=t&&n>=i};break;case"bottom-only":h=function(t,e,n,i,o){return n>=o&&o>=t};break;default:case"default":h=function(t,e,n,i,o){return n>=i&&o>=t}}return c=function(t){var i,o,l,s,r,a,u=this.state,h=!1,c=this.$element.offset();i=n.height(),o=t+i/2,l=t+i,s=this.$element.outerHeight(),r=c.top+e(this.options.top,s,i),a=c.top+s-e(this.options.bottom,s,i),h=this.test(t,o,l,r,a),h!=u&&(this.state=h,h?this.options.enter&&this.options.enter.apply(this.element):this.options.leave&&this.options.leave.apply(this.element)),this.options.scroll&&this.options.scroll.apply(this.element,[(o-r)/(a-r)])},p={id:a,options:u,test:h,handler:c,state:null,element:this,$element:s,timeoutId:null},o[a]=p,s.data("_scrollexId",p.id),p.options.initialize&&p.options.initialize.apply(this),s},jQuery.fn.unscrollex=function(){var e=t(this);if(0==this.length)return e;if(this.length>1){for(var n=0;n1){for(o=0;o=320px. 20 | @include breakpoint('<=xsmall') { 21 | html, body { 22 | min-width: 320px; 23 | } 24 | } 25 | 26 | // Set box model to border-box. 27 | // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice 28 | html { 29 | box-sizing: border-box; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: inherit; 34 | } 35 | 36 | body { 37 | background: _palette(bg); 38 | 39 | // Stops initial animations until page loads. 40 | &.is-preload { 41 | *, *:before, *:after { 42 | @include vendor('animation', 'none !important'); 43 | @include vendor('transition', 'none !important'); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | // Reset. 8 | // Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) 9 | 10 | html, body, div, span, applet, object, 11 | iframe, h1, h2, h3, h4, h5, h6, p, blockquote, 12 | pre, a, abbr, acronym, address, big, cite, 13 | code, del, dfn, em, img, ins, kbd, q, s, samp, 14 | small, strike, strong, sub, sup, tt, var, b, 15 | u, i, center, dl, dt, dd, ol, ul, li, fieldset, 16 | form, label, legend, table, caption, tbody, 17 | tfoot, thead, tr, th, td, article, aside, 18 | canvas, details, embed, figure, figcaption, 19 | footer, header, hgroup, menu, nav, output, ruby, 20 | section, summary, time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | vertical-align: baseline; 26 | } 27 | 28 | article, aside, details, figcaption, figure, 29 | footer, header, hgroup, menu, nav, section { 30 | display: block; 31 | } 32 | 33 | ol, ul { 34 | list-style:none; 35 | } 36 | 37 | blockquote, q { 38 | quotes: none; 39 | 40 | &:before, 41 | &:after { 42 | content: ''; 43 | content: none; 44 | } 45 | } 46 | 47 | table { 48 | border-collapse: collapse; 49 | border-spacing: 0; 50 | } 51 | 52 | body { 53 | line-height: 1; 54 | -webkit-text-size-adjust: none; 55 | } 56 | 57 | mark { 58 | background-color: transparent; 59 | color: inherit; 60 | } 61 | 62 | input::-moz-focus-inner { 63 | border: 0; 64 | padding: 0; 65 | } 66 | 67 | input, select, textarea { 68 | -moz-appearance: none; 69 | -webkit-appearance: none; 70 | -ms-appearance: none; 71 | appearance: none; 72 | } 73 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_actions.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Actions */ 8 | 9 | ul.actions { 10 | @include vendor('display', 'flex'); 11 | cursor: default; 12 | list-style: none; 13 | margin-left: (_size(element-margin) * -0.5); 14 | padding-left: 0; 15 | 16 | li { 17 | padding: 0 0 0 (_size(element-margin) * 0.5); 18 | vertical-align: middle; 19 | } 20 | 21 | &.special { 22 | @include vendor('justify-content', 'center'); 23 | width: 100%; 24 | margin-left: 0; 25 | 26 | li { 27 | &:first-child { 28 | padding-left: 0; 29 | } 30 | } 31 | } 32 | 33 | &.stacked { 34 | @include vendor('flex-direction', 'column'); 35 | margin-left: 0; 36 | 37 | li { 38 | padding: (_size(element-margin) * 0.65) 0 0 0; 39 | 40 | &:first-child { 41 | padding-top: 0; 42 | } 43 | } 44 | } 45 | 46 | &.fit { 47 | width: calc(100% + #{_size(element-margin) * 0.5}); 48 | 49 | li { 50 | @include vendor('flex-grow', '1'); 51 | @include vendor('flex-shrink', '1'); 52 | width: 100%; 53 | 54 | > * { 55 | width: 100%; 56 | } 57 | } 58 | 59 | &.stacked { 60 | width: 100%; 61 | } 62 | } 63 | 64 | @include breakpoint('<=xsmall') { 65 | &:not(.fixed) { 66 | @include vendor('flex-direction', 'column'); 67 | margin-left: 0; 68 | width: 100% !important; 69 | 70 | li { 71 | @include vendor('flex-grow', '1'); 72 | @include vendor('flex-shrink', '1'); 73 | padding: (_size(element-margin) * 0.5) 0 0 0; 74 | text-align: center; 75 | width: 100%; 76 | 77 | > * { 78 | width: 100%; 79 | } 80 | 81 | &:first-child { 82 | padding-top: 0; 83 | } 84 | 85 | input[type="submit"], 86 | input[type="reset"], 87 | input[type="button"], 88 | button, 89 | .button { 90 | width: 100%; 91 | 92 | &.icon { 93 | &:before { 94 | margin-left: -0.5rem; 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_box.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Box */ 8 | 9 | .box { 10 | border-radius: _size(border-radius); 11 | border: solid _size(border-width); 12 | margin-bottom: _size(element-margin); 13 | padding: 1.5rem; 14 | 15 | > :last-child, 16 | > :last-child > :last-child, 17 | > :last-child > :last-child > :last-child { 18 | margin-bottom: 0; 19 | } 20 | 21 | &.alt { 22 | border: 0; 23 | border-radius: 0; 24 | padding: 0; 25 | } 26 | } 27 | 28 | @mixin color-box($p: null) { 29 | .box { 30 | border-color: _palette($p, border); 31 | } 32 | } 33 | 34 | @include color-box; 35 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icon */ 8 | 9 | .icon { 10 | @include icon; 11 | border-bottom: none; 12 | position: relative; 13 | text-align: center; 14 | 15 | > .label { 16 | display: none; 17 | } 18 | 19 | &:before { 20 | line-height: inherit; 21 | } 22 | 23 | &.solid { 24 | &:before { 25 | font-weight: 900; 26 | } 27 | } 28 | 29 | &.brands { 30 | &:before { 31 | font-family: 'Font Awesome 5 Brands'; 32 | } 33 | } 34 | 35 | &.style2 { 36 | &:before { 37 | border-radius: 2.75em; 38 | display: inline-block; 39 | height: 2.75em; 40 | line-height: 2.75em; 41 | width: 2.75em; 42 | } 43 | } 44 | 45 | &.major { 46 | display: block; 47 | margin: 0 0 (_size(element-margin) * 0.5) 0; 48 | 49 | &:before { 50 | font-size: 1.25rem; 51 | } 52 | } 53 | } 54 | 55 | a.icon { 56 | &.style2 { 57 | &:before { 58 | @include vendor('transition', ( 59 | 'background-color #{_duration(transition)} ease-in-out', 60 | 'box-shadow #{_duration(transition)} ease-in-out', 61 | 'color #{_duration(transition)} ease-in-out' 62 | )); 63 | } 64 | } 65 | } 66 | 67 | @mixin color-icon($p: null) { 68 | .icon { 69 | &.style2 { 70 | &:before { 71 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, border); 72 | } 73 | } 74 | } 75 | 76 | a.icon { 77 | &.style2 { 78 | &:hover { 79 | &:before { 80 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, accent); 81 | color: _palette($p, accent); 82 | } 83 | } 84 | 85 | &:active { 86 | &:before { 87 | background-color: transparentize(_palette($p, accent), 0.9); 88 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, accent); 89 | color: _palette($p, accent); 90 | } 91 | } 92 | } 93 | } 94 | } 95 | 96 | @include color-icon; 97 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icons */ 8 | 9 | ul.icons { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding: 0 0.75rem 0 0; 17 | 18 | &:last-child { 19 | padding-right: 0; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_image.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Image */ 8 | 9 | .image { 10 | border: 0; 11 | border-radius: _size(border-radius); 12 | display: inline-block; 13 | position: relative; 14 | 15 | img { 16 | display: block; 17 | border-radius: _size(border-radius); 18 | } 19 | 20 | &.left, 21 | &.right { 22 | width: 40%; 23 | max-width: 10rem; 24 | 25 | img { 26 | width: 100%; 27 | } 28 | } 29 | 30 | &.left { 31 | float: left; 32 | margin: 0 1.5rem 1rem 0; 33 | top: 0.25rem; 34 | } 35 | 36 | &.right { 37 | float: right; 38 | margin: 0 0 1rem 1.5rem; 39 | top: 0.25rem; 40 | } 41 | 42 | &.fit { 43 | display: block; 44 | margin: 0 0 _size(element-margin) 0; 45 | width: 100%; 46 | 47 | img { 48 | width: 100%; 49 | } 50 | } 51 | 52 | &.main { 53 | display: block; 54 | margin: 0 0 (_size(element-margin) * 1.5) 0; 55 | width: 100%; 56 | 57 | img { 58 | width: 100%; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_index.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Index */ 8 | 9 | .index { 10 | > * { 11 | @include padding(3rem, 0); 12 | @include vendor('display', 'flex'); 13 | border-top: solid 1px; 14 | 15 | > header { 16 | @include vendor('flex-grow', '0'); 17 | @include vendor('flex-shrink', '0'); 18 | width: 15rem; 19 | } 20 | 21 | > .content { 22 | @include vendor('flex-grow', '1'); 23 | @include vendor('flex-shrink', '1'); 24 | } 25 | } 26 | 27 | > :first-child { 28 | border-top: 0; 29 | } 30 | 31 | @include breakpoint('<=medium') { 32 | > * { 33 | > header { 34 | width: 11rem; 35 | } 36 | } 37 | } 38 | 39 | @include breakpoint('<=small') { 40 | > * { 41 | > header { 42 | width: 10rem; 43 | } 44 | } 45 | } 46 | 47 | @include breakpoint('<=xsmall') { 48 | > * { 49 | @include vendor('flex-direction', 'column'); 50 | 51 | > header { 52 | width: 100%; 53 | } 54 | } 55 | } 56 | } 57 | 58 | @mixin color-index($p: null) { 59 | .index { 60 | > * { 61 | border-top-color: _palette($p, border); 62 | } 63 | } 64 | } 65 | 66 | @include color-index; 67 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* List */ 8 | 9 | ol { 10 | list-style: decimal; 11 | margin: 0 0 _size(element-margin) 0; 12 | padding-left: 1.25rem; 13 | 14 | li { 15 | padding-left: 0.25rem; 16 | } 17 | } 18 | 19 | ul { 20 | list-style: disc; 21 | margin: 0 0 _size(element-margin) 0; 22 | padding-left: 1rem; 23 | 24 | li { 25 | padding-left: 0.5rem; 26 | } 27 | 28 | &.alt { 29 | list-style: none; 30 | padding-left: 0; 31 | 32 | li { 33 | border-top: solid _size(border-width); 34 | padding: 0.5rem 0; 35 | 36 | &:first-child { 37 | border-top: 0; 38 | padding-top: 0; 39 | } 40 | } 41 | } 42 | } 43 | 44 | dl { 45 | margin: 0 0 _size(element-margin) 0; 46 | 47 | dt { 48 | display: block; 49 | font-weight: _font(weight-bold); 50 | margin: 0 0 (_size(element-margin) * 0.5) 0; 51 | } 52 | 53 | dd { 54 | margin-left: _size(element-margin); 55 | } 56 | 57 | &.style2 { 58 | dt { 59 | width: 25%; 60 | float: left; 61 | } 62 | 63 | dd { 64 | width: 70%; 65 | float: left; 66 | } 67 | 68 | &:after { 69 | content: ''; 70 | display: block; 71 | clear: both; 72 | } 73 | } 74 | } 75 | 76 | @mixin color-list($p: null) { 77 | ul { 78 | &.alt { 79 | li { 80 | border-top-color: _palette($p, border); 81 | } 82 | } 83 | } 84 | } 85 | 86 | @include color-list; 87 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_row.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Row */ 8 | 9 | .row { 10 | @include html-grid(2rem); 11 | 12 | @include breakpoint('<=xlarge') { 13 | @include html-grid(2rem, 'xlarge'); 14 | } 15 | 16 | @include breakpoint('<=large') { 17 | @include html-grid(2rem, 'large'); 18 | } 19 | 20 | @include breakpoint('<=medium') { 21 | @include html-grid(2rem, 'medium'); 22 | } 23 | 24 | @include breakpoint('<=small') { 25 | @include html-grid(2rem, 'small'); 26 | } 27 | 28 | @include breakpoint('<=xsmall') { 29 | @include html-grid(2rem, 'xsmall'); 30 | } 31 | 32 | @include breakpoint('<=xxsmall') { 33 | @include html-grid(2rem, 'xxsmall'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/components/_section.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Section/Article */ 8 | 9 | section, article { 10 | &.special { 11 | text-align: center; 12 | } 13 | } 14 | 15 | header { 16 | p { 17 | position: relative; 18 | margin: (_size(element-margin) * -0.325) 0 (_size(element-margin) * 0.75) 0; 19 | font-style: italic; 20 | } 21 | 22 | h1 + p { 23 | font-size: 1.375rem; 24 | } 25 | 26 | h2 + p { 27 | font-size: 1.25rem; 28 | } 29 | 30 | h3 + p { 31 | font-size: 1.1rem; 32 | } 33 | 34 | h4 + p, 35 | h5 + p, 36 | h6 + p { 37 | font-size: 0.9rem; 38 | } 39 | } 40 | 41 | @mixin color-section($p: null) { 42 | header { 43 | p { 44 | color: _palette($p, fg-light); 45 | } 46 | } 47 | } 48 | 49 | @include color-section; 50 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/layout/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Wrapper */ 8 | 9 | @mixin wrapper-color($n) { 10 | > .color#{$n} { 11 | background-color: _palette(color#{$n}); 12 | } 13 | } 14 | 15 | #wrapper { 16 | background-color: inherit; 17 | width: 100%; 18 | overflow-x: hidden; 19 | 20 | > .invert { 21 | @include color(invert); 22 | } 23 | 24 | @include wrapper-color(1); 25 | @include wrapper-color(2); 26 | @include wrapper-color(3); 27 | @include wrapper-color(4); 28 | @include wrapper-color(5); 29 | @include wrapper-color(6); 30 | @include wrapper-color(7); 31 | 32 | &.divided { 33 | > * { 34 | box-shadow: inset 0 1px 0 0 _palette(border-alt); 35 | 36 | &:first-child { 37 | box-shadow: none !important; 38 | } 39 | } 40 | 41 | > .invert { 42 | box-shadow: inset 0 1px 0 0 _palette(invert, border-alt); 43 | 44 | &:first-child { 45 | box-shadow: none !important; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/libs/_functions.scss: -------------------------------------------------------------------------------- 1 | /// Removes a specific item from a list. 2 | /// @author Hugo Giraudel 3 | /// @param {list} $list List. 4 | /// @param {integer} $index Index. 5 | /// @return {list} Updated list. 6 | @function remove-nth($list, $index) { 7 | 8 | $result: null; 9 | 10 | @if type-of($index) != number { 11 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 12 | } 13 | @else if $index == 0 { 14 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 15 | } 16 | @else if abs($index) > length($list) { 17 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 18 | } 19 | @else { 20 | 21 | $result: (); 22 | $index: if($index < 0, length($list) + $index + 1, $index); 23 | 24 | @for $i from 1 through length($list) { 25 | 26 | @if $i != $index { 27 | $result: append($result, nth($list, $i)); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | @return $result; 35 | 36 | } 37 | 38 | /// Gets a value from a map. 39 | /// @author Hugo Giraudel 40 | /// @param {map} $map Map. 41 | /// @param {string} $keys Key(s). 42 | /// @return {string} Value. 43 | @function val($map, $keys...) { 44 | 45 | @if nth($keys, 1) == null { 46 | $keys: remove-nth($keys, 1); 47 | } 48 | 49 | @each $key in $keys { 50 | $map: map-get($map, $key); 51 | } 52 | 53 | @return $map; 54 | 55 | } 56 | 57 | /// Gets a duration value. 58 | /// @param {string} $keys Key(s). 59 | /// @return {string} Value. 60 | @function _duration($keys...) { 61 | @return val($duration, $keys...); 62 | } 63 | 64 | /// Gets a font value. 65 | /// @param {string} $keys Key(s). 66 | /// @return {string} Value. 67 | @function _font($keys...) { 68 | @return val($font, $keys...); 69 | } 70 | 71 | /// Gets a misc value. 72 | /// @param {string} $keys Key(s). 73 | /// @return {string} Value. 74 | @function _misc($keys...) { 75 | @return val($misc, $keys...); 76 | } 77 | 78 | /// Gets a palette value. 79 | /// @param {string} $keys Key(s). 80 | /// @return {string} Value. 81 | @function _palette($keys...) { 82 | @return val($palette, $keys...); 83 | } 84 | 85 | /// Gets a size value. 86 | /// @param {string} $keys Key(s). 87 | /// @return {string} Value. 88 | @function _size($keys...) { 89 | @return val($size, $keys...); 90 | } 91 | -------------------------------------------------------------------------------- /demo/flask-web/static/sass/libs/_vars.scss: -------------------------------------------------------------------------------- 1 | // Misc. 2 | $misc: ( 3 | z-index-base: 10000, 4 | overlay-opacity: 0.5, 5 | lightbox-opacity: 0.75, 6 | gallery-limit: 32, 7 | items-limit: 16 8 | ); 9 | 10 | // Duration. 11 | $duration: ( 12 | menu: 0.5s, 13 | transition: 0.2s, 14 | gallery-lightbox: 0.5s, 15 | gallery-delay: 0.15s, 16 | items-delay: 0.15s, 17 | on-load: 0.75s, 18 | on-scroll: 0.75s 19 | ); 20 | 21 | // Size. 22 | $size: ( 23 | border-radius: 4px, 24 | border-radius-alt: 0.5rem, 25 | border-width: 1px, 26 | element-height: 2.75rem, 27 | element-margin: 2rem, 28 | gutter: 3.5rem, 29 | inner: 64rem, 30 | padding: ( 31 | default: 7rem, 32 | xlarge: 5rem, 33 | large: 4rem, 34 | medium: 3rem, 35 | small: 2rem 36 | ) 37 | ); 38 | 39 | // Font. 40 | $font: ( 41 | family: ('Source Sans Pro', Helvetica, sans-serif), 42 | family-fixed: ('Courier New', monospace), 43 | weight: 300, 44 | weight-bold: 400, 45 | kerning: -0.05em, 46 | kerning-alt: 0.125em 47 | ); 48 | 49 | // Palette. 50 | $palette: ( 51 | color1: #30363d, 52 | color2: #db8992, 53 | color3: #ab7aad, 54 | color4: #897cad, 55 | color5: #7794ce, 56 | color6: #64abb4, 57 | color7: #6ba78c, 58 | 59 | bg: #ffffff, 60 | bg-alt: #eeeeee, 61 | fg: #000000, 62 | fg-bold: #000000, 63 | fg-light: rgba(0,0,0,0.75), 64 | border: rgba(0,0,0,0.2), 65 | border-alt: rgba(0,0,0,0.075), 66 | border-bg: rgba(0,0,0,0.05), 67 | accent: #47D3E5, 68 | 69 | invert: ( 70 | bg: #000000, 71 | bg-alt: #222222, 72 | fg: #ffffff, 73 | fg-bold: #ffffff, 74 | fg-light: #ffffff, 75 | border: rgba(255,255,255,1.0), 76 | border-alt: rgba(255,255,255,0.125), 77 | border-bg: rgba(255,255,255,0.125), 78 | accent: #47D3E5 79 | ), 80 | ); 81 | -------------------------------------------------------------------------------- /demo/maven-test/src/main/java/com/mycompany/app/App.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.app; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/maven-test/src/test/java/com/mycompany/app/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.app; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | { 12 | /** 13 | * Rigorous Test :-) 14 | */ 15 | @Test 16 | public void shouldAnswerWithTrue() 17 | { 18 | assertTrue( true ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /demo/nginx/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /demo/nginx/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: web 3 | description: A Helm chart for managing a web frontend. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /demo/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx 2 | COPY . /usr/share/nginx/html 3 | -------------------------------------------------------------------------------- /demo/nginx/assets/js/breakpoints.min.js: -------------------------------------------------------------------------------- 1 | /* breakpoints.js v1.0 | @ajlkn | MIT licensed */ 2 | var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e0:!!("ontouchstart"in window),e.mobile="wp"==e.os||"android"==e.os||"ios"==e.os||"bb"==e.os}};return e.init(),e}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser}); 3 | -------------------------------------------------------------------------------- /demo/nginx/assets/js/jquery.scrollex.min.js: -------------------------------------------------------------------------------- 1 | /* jquery.scrollex v0.2.1 | (c) @ajlkn | github.com/ajlkn/jquery.scrollex | MIT licensed */ 2 | !function(t){function e(t,e,n){return"string"==typeof t&&("%"==t.slice(-1)?t=parseInt(t.substring(0,t.length-1))/100*e:"vh"==t.slice(-2)?t=parseInt(t.substring(0,t.length-2))/100*n:"px"==t.slice(-2)&&(t=parseInt(t.substring(0,t.length-2)))),t}var n=t(window),i=1,o={};n.on("scroll",function(){var e=n.scrollTop();t.map(o,function(t){window.clearTimeout(t.timeoutId),t.timeoutId=window.setTimeout(function(){t.handler(e)},t.options.delay)})}).on("load",function(){n.trigger("scroll")}),jQuery.fn.scrollex=function(l){var s=t(this);if(0==this.length)return s;if(this.length>1){for(var r=0;r=i&&o>=t};break;case"bottom":h=function(t,e,n,i,o){return n>=i&&o>=n};break;case"middle":h=function(t,e,n,i,o){return e>=i&&o>=e};break;case"top-only":h=function(t,e,n,i,o){return i>=t&&n>=i};break;case"bottom-only":h=function(t,e,n,i,o){return n>=o&&o>=t};break;default:case"default":h=function(t,e,n,i,o){return n>=i&&o>=t}}return c=function(t){var i,o,l,s,r,a,u=this.state,h=!1,c=this.$element.offset();i=n.height(),o=t+i/2,l=t+i,s=this.$element.outerHeight(),r=c.top+e(this.options.top,s,i),a=c.top+s-e(this.options.bottom,s,i),h=this.test(t,o,l,r,a),h!=u&&(this.state=h,h?this.options.enter&&this.options.enter.apply(this.element):this.options.leave&&this.options.leave.apply(this.element)),this.options.scroll&&this.options.scroll.apply(this.element,[(o-r)/(a-r)])},p={id:a,options:u,test:h,handler:c,state:null,element:this,$element:s,timeoutId:null},o[a]=p,s.data("_scrollexId",p.id),p.options.initialize&&p.options.initialize.apply(this),s},jQuery.fn.unscrollex=function(){var e=t(this);if(0==this.length)return e;if(this.length>1){for(var n=0;n1){for(o=0;o=320px. 20 | @include breakpoint('<=xsmall') { 21 | html, body { 22 | min-width: 320px; 23 | } 24 | } 25 | 26 | // Set box model to border-box. 27 | // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice 28 | html { 29 | box-sizing: border-box; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: inherit; 34 | } 35 | 36 | body { 37 | background: _palette(bg); 38 | 39 | // Stops initial animations until page loads. 40 | &.is-preload { 41 | *, *:before, *:after { 42 | @include vendor('animation', 'none !important'); 43 | @include vendor('transition', 'none !important'); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | // Reset. 8 | // Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) 9 | 10 | html, body, div, span, applet, object, 11 | iframe, h1, h2, h3, h4, h5, h6, p, blockquote, 12 | pre, a, abbr, acronym, address, big, cite, 13 | code, del, dfn, em, img, ins, kbd, q, s, samp, 14 | small, strike, strong, sub, sup, tt, var, b, 15 | u, i, center, dl, dt, dd, ol, ul, li, fieldset, 16 | form, label, legend, table, caption, tbody, 17 | tfoot, thead, tr, th, td, article, aside, 18 | canvas, details, embed, figure, figcaption, 19 | footer, header, hgroup, menu, nav, output, ruby, 20 | section, summary, time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | font: inherit; 26 | vertical-align: baseline; 27 | } 28 | 29 | article, aside, details, figcaption, figure, 30 | footer, header, hgroup, menu, nav, section { 31 | display: block; 32 | } 33 | 34 | body { 35 | line-height: 1; 36 | } 37 | 38 | ol, ul { 39 | list-style:none; 40 | } 41 | 42 | blockquote, q { 43 | quotes: none; 44 | 45 | &:before, 46 | &:after { 47 | content: ''; 48 | content: none; 49 | } 50 | } 51 | 52 | table { 53 | border-collapse: collapse; 54 | border-spacing: 0; 55 | } 56 | 57 | body { 58 | -webkit-text-size-adjust: none; 59 | } 60 | 61 | mark { 62 | background-color: transparent; 63 | color: inherit; 64 | } 65 | 66 | input::-moz-focus-inner { 67 | border: 0; 68 | padding: 0; 69 | } 70 | 71 | input, select, textarea { 72 | -moz-appearance: none; 73 | -webkit-appearance: none; 74 | -ms-appearance: none; 75 | appearance: none; 76 | } 77 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_actions.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Actions */ 8 | 9 | ul.actions { 10 | @include vendor('display', 'flex'); 11 | cursor: default; 12 | list-style: none; 13 | margin-left: (_size(element-margin) * -0.5); 14 | padding-left: 0; 15 | 16 | li { 17 | padding: 0 0 0 (_size(element-margin) * 0.5); 18 | vertical-align: middle; 19 | } 20 | 21 | &.special { 22 | @include vendor('justify-content', 'center'); 23 | width: 100%; 24 | margin-left: 0; 25 | 26 | li { 27 | &:first-child { 28 | padding-left: 0; 29 | } 30 | } 31 | } 32 | 33 | &.stacked { 34 | @include vendor('flex-direction', 'column'); 35 | margin-left: 0; 36 | 37 | li { 38 | padding: (_size(element-margin) * 0.65) 0 0 0; 39 | 40 | &:first-child { 41 | padding-top: 0; 42 | } 43 | } 44 | } 45 | 46 | &.fit { 47 | width: calc(100% + #{_size(element-margin) * 0.5}); 48 | 49 | li { 50 | @include vendor('flex-grow', '1'); 51 | @include vendor('flex-shrink', '1'); 52 | width: 100%; 53 | 54 | > * { 55 | width: 100%; 56 | } 57 | } 58 | 59 | &.stacked { 60 | width: 100%; 61 | } 62 | } 63 | 64 | @include breakpoint('<=xsmall') { 65 | &:not(.fixed) { 66 | @include vendor('flex-direction', 'column'); 67 | margin-left: 0; 68 | width: 100% !important; 69 | 70 | li { 71 | @include vendor('flex-grow', '1'); 72 | @include vendor('flex-shrink', '1'); 73 | padding: (_size(element-margin) * 0.5) 0 0 0; 74 | text-align: center; 75 | width: 100%; 76 | 77 | > * { 78 | width: 100%; 79 | } 80 | 81 | &:first-child { 82 | padding-top: 0; 83 | } 84 | 85 | input[type="submit"], 86 | input[type="reset"], 87 | input[type="button"], 88 | button, 89 | .button { 90 | width: 100%; 91 | 92 | &.icon { 93 | &:before { 94 | margin-left: -0.5rem; 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_box.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Box */ 8 | 9 | .box { 10 | border-radius: _size(border-radius); 11 | border: solid _size(border-width); 12 | margin-bottom: _size(element-margin); 13 | padding: 1.5rem; 14 | 15 | > :last-child, 16 | > :last-child > :last-child, 17 | > :last-child > :last-child > :last-child { 18 | margin-bottom: 0; 19 | } 20 | 21 | &.alt { 22 | border: 0; 23 | border-radius: 0; 24 | padding: 0; 25 | } 26 | } 27 | 28 | @mixin color-box($p: null) { 29 | .box { 30 | border-color: _palette($p, border); 31 | } 32 | } 33 | 34 | @include color-box; 35 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icon */ 8 | 9 | .icon { 10 | @include icon; 11 | border-bottom: none; 12 | position: relative; 13 | text-align: center; 14 | 15 | > .label { 16 | display: none; 17 | } 18 | 19 | &:before { 20 | line-height: inherit; 21 | } 22 | 23 | &.solid { 24 | &:before { 25 | font-weight: 900; 26 | } 27 | } 28 | 29 | &.brands { 30 | &:before { 31 | font-family: 'Font Awesome 5 Brands'; 32 | } 33 | } 34 | 35 | &.style2 { 36 | &:before { 37 | border-radius: 2.75em; 38 | display: inline-block; 39 | height: 2.75em; 40 | line-height: 2.75em; 41 | width: 2.75em; 42 | } 43 | } 44 | 45 | &.major { 46 | display: block; 47 | margin: 0 0 (_size(element-margin) * 0.5) 0; 48 | 49 | &:before { 50 | font-size: 1.25rem; 51 | } 52 | } 53 | } 54 | 55 | a.icon { 56 | &.style2 { 57 | &:before { 58 | @include vendor('transition', ( 59 | 'background-color #{_duration(transition)} ease-in-out', 60 | 'box-shadow #{_duration(transition)} ease-in-out', 61 | 'color #{_duration(transition)} ease-in-out' 62 | )); 63 | } 64 | } 65 | } 66 | 67 | @mixin color-icon($p: null) { 68 | .icon { 69 | &.style2 { 70 | &:before { 71 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, border); 72 | } 73 | } 74 | } 75 | 76 | a.icon { 77 | &.style2 { 78 | &:hover { 79 | &:before { 80 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, accent); 81 | color: _palette($p, accent); 82 | } 83 | } 84 | 85 | &:active { 86 | &:before { 87 | background-color: transparentize(_palette($p, accent), 0.9); 88 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, accent); 89 | color: _palette($p, accent); 90 | } 91 | } 92 | } 93 | } 94 | } 95 | 96 | @include color-icon; 97 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icons */ 8 | 9 | ul.icons { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding: 0 0.75rem 0 0; 17 | 18 | &:last-child { 19 | padding-right: 0; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_image.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Image */ 8 | 9 | .image { 10 | border: 0; 11 | border-radius: _size(border-radius); 12 | display: inline-block; 13 | position: relative; 14 | 15 | img { 16 | display: block; 17 | border-radius: _size(border-radius); 18 | } 19 | 20 | &.left, 21 | &.right { 22 | width: 40%; 23 | max-width: 10rem; 24 | 25 | img { 26 | width: 100%; 27 | } 28 | } 29 | 30 | &.left { 31 | float: left; 32 | margin: 0 1.5rem 1rem 0; 33 | top: 0.25rem; 34 | } 35 | 36 | &.right { 37 | float: right; 38 | margin: 0 0 1rem 1.5rem; 39 | top: 0.25rem; 40 | } 41 | 42 | &.fit { 43 | display: block; 44 | margin: 0 0 _size(element-margin) 0; 45 | width: 100%; 46 | 47 | img { 48 | width: 100%; 49 | } 50 | } 51 | 52 | &.main { 53 | display: block; 54 | margin: 0 0 (_size(element-margin) * 1.5) 0; 55 | width: 100%; 56 | 57 | img { 58 | width: 100%; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_index.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Index */ 8 | 9 | .index { 10 | > * { 11 | @include padding(3rem, 0); 12 | @include vendor('display', 'flex'); 13 | border-top: solid 1px; 14 | 15 | > header { 16 | @include vendor('flex-grow', '0'); 17 | @include vendor('flex-shrink', '0'); 18 | width: 15rem; 19 | } 20 | 21 | > .content { 22 | @include vendor('flex-grow', '1'); 23 | @include vendor('flex-shrink', '1'); 24 | } 25 | } 26 | 27 | > :first-child { 28 | border-top: 0; 29 | } 30 | 31 | @include breakpoint('<=medium') { 32 | > * { 33 | > header { 34 | width: 11rem; 35 | } 36 | } 37 | } 38 | 39 | @include breakpoint('<=small') { 40 | > * { 41 | > header { 42 | width: 10rem; 43 | } 44 | } 45 | } 46 | 47 | @include breakpoint('<=xsmall') { 48 | > * { 49 | @include vendor('flex-direction', 'column'); 50 | 51 | > header { 52 | width: 100%; 53 | } 54 | } 55 | } 56 | } 57 | 58 | @mixin color-index($p: null) { 59 | .index { 60 | > * { 61 | border-top-color: _palette($p, border); 62 | } 63 | } 64 | } 65 | 66 | @include color-index; 67 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* List */ 8 | 9 | ol { 10 | list-style: decimal; 11 | margin: 0 0 _size(element-margin) 0; 12 | padding-left: 1.25rem; 13 | 14 | li { 15 | padding-left: 0.25rem; 16 | } 17 | } 18 | 19 | ul { 20 | list-style: disc; 21 | margin: 0 0 _size(element-margin) 0; 22 | padding-left: 1rem; 23 | 24 | li { 25 | padding-left: 0.5rem; 26 | } 27 | 28 | &.alt { 29 | list-style: none; 30 | padding-left: 0; 31 | 32 | li { 33 | border-top: solid _size(border-width); 34 | padding: 0.5rem 0; 35 | 36 | &:first-child { 37 | border-top: 0; 38 | padding-top: 0; 39 | } 40 | } 41 | } 42 | } 43 | 44 | dl { 45 | margin: 0 0 _size(element-margin) 0; 46 | 47 | dt { 48 | display: block; 49 | font-weight: _font(weight-bold); 50 | margin: 0 0 (_size(element-margin) * 0.5) 0; 51 | } 52 | 53 | dd { 54 | margin-left: _size(element-margin); 55 | } 56 | 57 | &.style2 { 58 | dt { 59 | width: 25%; 60 | float: left; 61 | } 62 | 63 | dd { 64 | width: 70%; 65 | float: left; 66 | } 67 | 68 | &:after { 69 | content: ''; 70 | display: block; 71 | clear: both; 72 | } 73 | } 74 | } 75 | 76 | @mixin color-list($p: null) { 77 | ul { 78 | &.alt { 79 | li { 80 | border-top-color: _palette($p, border); 81 | } 82 | } 83 | } 84 | } 85 | 86 | @include color-list; 87 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_row.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Row */ 8 | 9 | .row { 10 | @include html-grid(2rem); 11 | 12 | @include breakpoint('<=xlarge') { 13 | @include html-grid(2rem, 'xlarge'); 14 | } 15 | 16 | @include breakpoint('<=large') { 17 | @include html-grid(2rem, 'large'); 18 | } 19 | 20 | @include breakpoint('<=medium') { 21 | @include html-grid(2rem, 'medium'); 22 | } 23 | 24 | @include breakpoint('<=small') { 25 | @include html-grid(2rem, 'small'); 26 | } 27 | 28 | @include breakpoint('<=xsmall') { 29 | @include html-grid(2rem, 'xsmall'); 30 | } 31 | 32 | @include breakpoint('<=xxsmall') { 33 | @include html-grid(2rem, 'xxsmall'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/components/_section.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Section/Article */ 8 | 9 | section, article { 10 | &.special { 11 | text-align: center; 12 | } 13 | } 14 | 15 | header { 16 | p { 17 | position: relative; 18 | margin: (_size(element-margin) * -0.325) 0 (_size(element-margin) * 0.75) 0; 19 | font-style: italic; 20 | } 21 | 22 | h1 + p { 23 | font-size: 1.375rem; 24 | } 25 | 26 | h2 + p { 27 | font-size: 1.25rem; 28 | } 29 | 30 | h3 + p { 31 | font-size: 1.1rem; 32 | } 33 | 34 | h4 + p, 35 | h5 + p, 36 | h6 + p { 37 | font-size: 0.9rem; 38 | } 39 | } 40 | 41 | @mixin color-section($p: null) { 42 | header { 43 | p { 44 | color: _palette($p, fg-light); 45 | } 46 | } 47 | } 48 | 49 | @include color-section; 50 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/layout/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Wrapper */ 8 | 9 | @mixin wrapper-color($n) { 10 | > .color#{$n} { 11 | background-color: _palette(color#{$n}); 12 | } 13 | } 14 | 15 | #wrapper { 16 | background-color: inherit; 17 | width: 100%; 18 | overflow-x: hidden; 19 | 20 | > .invert { 21 | @include color(invert); 22 | } 23 | 24 | @include wrapper-color(1); 25 | @include wrapper-color(2); 26 | @include wrapper-color(3); 27 | @include wrapper-color(4); 28 | @include wrapper-color(5); 29 | @include wrapper-color(6); 30 | @include wrapper-color(7); 31 | 32 | &.divided { 33 | > * { 34 | box-shadow: inset 0 1px 0 0 _palette(border-alt); 35 | 36 | &:first-child { 37 | box-shadow: none !important; 38 | } 39 | } 40 | 41 | > .invert { 42 | box-shadow: inset 0 1px 0 0 _palette(invert, border-alt); 43 | 44 | &:first-child { 45 | box-shadow: none !important; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/libs/_functions.scss: -------------------------------------------------------------------------------- 1 | /// Removes a specific item from a list. 2 | /// @author Hugo Giraudel 3 | /// @param {list} $list List. 4 | /// @param {integer} $index Index. 5 | /// @return {list} Updated list. 6 | @function remove-nth($list, $index) { 7 | 8 | $result: null; 9 | 10 | @if type-of($index) != number { 11 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 12 | } 13 | @else if $index == 0 { 14 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 15 | } 16 | @else if abs($index) > length($list) { 17 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 18 | } 19 | @else { 20 | 21 | $result: (); 22 | $index: if($index < 0, length($list) + $index + 1, $index); 23 | 24 | @for $i from 1 through length($list) { 25 | 26 | @if $i != $index { 27 | $result: append($result, nth($list, $i)); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | @return $result; 35 | 36 | } 37 | 38 | /// Gets a value from a map. 39 | /// @author Hugo Giraudel 40 | /// @param {map} $map Map. 41 | /// @param {string} $keys Key(s). 42 | /// @return {string} Value. 43 | @function val($map, $keys...) { 44 | 45 | @if nth($keys, 1) == null { 46 | $keys: remove-nth($keys, 1); 47 | } 48 | 49 | @each $key in $keys { 50 | $map: map-get($map, $key); 51 | } 52 | 53 | @return $map; 54 | 55 | } 56 | 57 | /// Gets a duration value. 58 | /// @param {string} $keys Key(s). 59 | /// @return {string} Value. 60 | @function _duration($keys...) { 61 | @return val($duration, $keys...); 62 | } 63 | 64 | /// Gets a font value. 65 | /// @param {string} $keys Key(s). 66 | /// @return {string} Value. 67 | @function _font($keys...) { 68 | @return val($font, $keys...); 69 | } 70 | 71 | /// Gets a misc value. 72 | /// @param {string} $keys Key(s). 73 | /// @return {string} Value. 74 | @function _misc($keys...) { 75 | @return val($misc, $keys...); 76 | } 77 | 78 | /// Gets a palette value. 79 | /// @param {string} $keys Key(s). 80 | /// @return {string} Value. 81 | @function _palette($keys...) { 82 | @return val($palette, $keys...); 83 | } 84 | 85 | /// Gets a size value. 86 | /// @param {string} $keys Key(s). 87 | /// @return {string} Value. 88 | @function _size($keys...) { 89 | @return val($size, $keys...); 90 | } 91 | -------------------------------------------------------------------------------- /demo/nginx/assets/sass/libs/_vars.scss: -------------------------------------------------------------------------------- 1 | // Misc. 2 | $misc: ( 3 | z-index-base: 10000, 4 | overlay-opacity: 0.5, 5 | lightbox-opacity: 0.75, 6 | gallery-limit: 32, 7 | items-limit: 16 8 | ); 9 | 10 | // Duration. 11 | $duration: ( 12 | menu: 0.5s, 13 | transition: 0.2s, 14 | gallery-lightbox: 0.5s, 15 | gallery-delay: 0.15s, 16 | items-delay: 0.15s, 17 | on-load: 0.75s, 18 | on-scroll: 0.75s 19 | ); 20 | 21 | // Size. 22 | $size: ( 23 | border-radius: 4px, 24 | border-radius-alt: 0.5rem, 25 | border-width: 1px, 26 | element-height: 2.75rem, 27 | element-margin: 2rem, 28 | gutter: 3.5rem, 29 | inner: 64rem, 30 | padding: ( 31 | default: 7rem, 32 | xlarge: 5rem, 33 | large: 4rem, 34 | medium: 3rem, 35 | small: 2rem 36 | ) 37 | ); 38 | 39 | // Font. 40 | $font: ( 41 | family: ('Source Sans Pro', Helvetica, sans-serif), 42 | family-fixed: ('Courier New', monospace), 43 | weight: 300, 44 | weight-bold: 400, 45 | kerning: -0.05em, 46 | kerning-alt: 0.125em 47 | ); 48 | 49 | // Palette. 50 | $palette: ( 51 | color1: #30363d, 52 | color2: #db8992, 53 | color3: #ab7aad, 54 | color4: #897cad, 55 | color5: #7794ce, 56 | color6: #64abb4, 57 | color7: #6ba78c, 58 | 59 | bg: #ffffff, 60 | bg-alt: #eeeeee, 61 | fg: #000000, 62 | fg-bold: #000000, 63 | fg-light: rgba(0,0,0,0.75), 64 | border: rgba(0,0,0,0.2), 65 | border-alt: rgba(0,0,0,0.075), 66 | border-bg: rgba(0,0,0,0.05), 67 | accent: #47D3E5, 68 | 69 | invert: ( 70 | bg: #000000, 71 | bg-alt: #222222, 72 | fg: #ffffff, 73 | fg-bold: #ffffff, 74 | fg-light: #ffffff, 75 | border: rgba(255,255,255,1.0), 76 | border-alt: rgba(255,255,255,0.125), 77 | border-bg: rgba(255,255,255,0.125), 78 | accent: #47D3E5 79 | ), 80 | ); 81 | -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /demo/nginx/assets/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/assets/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /demo/nginx/helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /demo/nginx/helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: web 3 | description: A Helm chart for managing a web frontend. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mychart.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mychart.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mychart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mychart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "mychart.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "mychart.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "mychart.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "mychart.labels" -}} 37 | helm.sh/chart: {{ include "mychart.chart" . }} 38 | {{ include "mychart.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "mychart.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "mychart.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "mychart.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "mychart.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "mychart.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "mychart.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "mychart.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: 80 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "mychart.fullname" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "mychart.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "mychart.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "mychart.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "mychart.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /demo/nginx/helm/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "mychart.serviceAccountName" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /demo/nginx/helm/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for mychart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 3 6 | 7 | image: 8 | repository: gregnrobinson/bcgov-nginx-demo 9 | pullPolicy: Always 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: latest 12 | 13 | imagePullSecrets: [name: regcred] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: LoadBalancer 41 | port: 80 42 | 43 | ingress: 44 | enabled: false 45 | # className: "" 46 | # annotations: 47 | # kubernetes.io/ingress.class: nginx 48 | # nginx.ingress.kubernetes.io/use-regex: "true" 49 | # # kubernetes.io/tls-acme: "true" 50 | # hosts: 51 | # - host: tkndemo.gregrobinson.ca 52 | # paths: 53 | # - path: /.* 54 | # pathType: Prefix 55 | # tls: [] 56 | # - secretName: chart-example-tls 57 | # hosts: 58 | # - chart-example.local 59 | 60 | resources: {} 61 | # We usually recommend not to specify default resources and to leave this as a conscious 62 | # choice for the user. This also increases chances charts run on environments with little 63 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 64 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 65 | # limits: 66 | # cpu: 100m 67 | # memory: 128Mi 68 | # requests: 69 | # cpu: 100m 70 | # memory: 128Mi 71 | 72 | autoscaling: 73 | enabled: false 74 | minReplicas: 1 75 | maxReplicas: 100 76 | targetCPUUtilizationPercentage: 80 77 | # targetMemoryUtilizationPercentage: 80 78 | 79 | nodeSelector: {} 80 | 81 | tolerations: [] 82 | 83 | affinity: {} 84 | -------------------------------------------------------------------------------- /demo/nginx/images/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/images/banner.jpg -------------------------------------------------------------------------------- /demo/nginx/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/demo/nginx/images/favicon.png -------------------------------------------------------------------------------- /demo/nginx/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mychart.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mychart.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mychart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mychart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /demo/nginx/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "mychart.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "mychart.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "mychart.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "mychart.labels" -}} 37 | helm.sh/chart: {{ include "mychart.chart" . }} 38 | {{ include "mychart.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "mychart.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "mychart.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "mychart.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "mychart.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /demo/nginx/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "mychart.fullname" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "mychart.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /demo/nginx/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "mychart.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "mychart.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /demo/nginx/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "mychart.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /demo/nginx/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "mychart.serviceAccountName" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /demo/nginx/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for mychart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 3 6 | 7 | image: 8 | repository: gregnrobinson/helm-ansible-demo 9 | pullPolicy: Always 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: v1.0.5 12 | 13 | imagePullSecrets: [name: regcred] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: LoadBalancer 41 | port: 80 42 | 43 | ingress: 44 | enabled: true 45 | className: "" 46 | annotations: 47 | kubernetes.io/ingress.class: nginx 48 | nginx.ingress.kubernetes.io/use-regex: "true" 49 | # kubernetes.io/tls-acme: "true" 50 | hosts: 51 | - host: demo.gregrobinson.ca 52 | paths: 53 | - path: /.* 54 | pathType: Exact 55 | tls: [] 56 | # - secretName: chart-example-tls 57 | # hosts: 58 | # - chart-example.local 59 | 60 | resources: 61 | # We usually recommend not to specify default resources and to leave this as a conscious 62 | # choice for the user. This also increases chances charts run on environments with little 63 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 64 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 65 | limits: 66 | cpu: 100m 67 | memory: 128Mi 68 | requests: 69 | cpu: 100m 70 | memory: 128Mi 71 | 72 | autoscaling: 73 | enabled: false 74 | minReplicas: 1 75 | maxReplicas: 100 76 | targetCPUUtilizationPercentage: 80 77 | # targetMemoryUtilizationPercentage: 80 78 | 79 | nodeSelector: {} 80 | 81 | tolerations: [] 82 | 83 | affinity: {} 84 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.organization=ci-testing 2 | sonar.projectKey=bcgov-pipeline-templates 3 | sonar.host.url=https://sonarcloud.io 4 | sonar.exclusions=**/*.java 5 | -------------------------------------------------------------------------------- /tekton/.dockerignore: -------------------------------------------------------------------------------- 1 | # */*/secrets.ini 2 | .venv 3 | -------------------------------------------------------------------------------- /tekton/.gitignore: -------------------------------------------------------------------------------- 1 | **/.env 2 | **/opaque.secrets 3 | overlays/secrets/kustomization.yml 4 | **/.DS_Store 5 | yq 6 | .DS_Store 7 | **/*.ini 8 | -------------------------------------------------------------------------------- /tekton/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | RUN mkdir /var/opt/tekton 4 | 5 | WORKDIR /var/opt/ 6 | 7 | # Get the kubectl binary. 8 | RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl 9 | # Make the kubectl binary executable. 10 | RUN chmod +x ./kubectl 11 | RUN mv ./kubectl /usr/local/bin/kubectl 12 | 13 | # Install OC command 14 | RUN curl -o oc.tar https://downloads-openshift-console.apps.silver.devops.gov.bc.ca/amd64/linux/oc.tar 15 | RUN tar -xvf oc.tar 16 | RUN chmod +x ./oc 17 | RUN mv ./oc /usr/local/bin/oc 18 | 19 | 20 | WORKDIR /var/opt/tekton 21 | # ADD ./id_rsa /var/opt/tekton/id_rsa 22 | COPY . . 23 | 24 | # clean up this form 25 | RUN sed -i 's/sonar-token=.*/sonar-token=/g ; s/ssh-key-path=.*/ssh-key-path=/g ; s/github-pat-token=.*/github-pat-token=/g' ./overlays/secrets/secrets.ini 26 | 27 | # RUN sed -i 's/ssh-key-path=/ssh-key-path=\/var\/opt\/tekton\/id_rsa/g' ./overlays/secrets/secrets.ini 28 | RUN echo $CONTEXT 29 | 30 | COPY ./scripts/install.sh /docker-entrypoint-installTekton.sh 31 | RUN chmod +x /docker-entrypoint-installTekton.sh 32 | 33 | ENTRYPOINT [ "/docker-entrypoint-installTekton.sh" ] 34 | 35 | 36 | -------------------------------------------------------------------------------- /tekton/base/pipelines/codeql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: codeql 5 | spec: 6 | workspaces: 7 | - name: shared-data 8 | description: | 9 | This workspace will receive the cloned git repo and be passed 10 | to the next Task for the repo's README.md file to be read. 11 | params: 12 | - name: buildImageUrl 13 | type: string 14 | description: Name of App that will be deployed. 15 | - name: repoUrl 16 | type: string 17 | description: The git repository URL to clone from. 18 | - name: repo 19 | type: string 20 | description: The git repository name. 21 | - name: branchName 22 | type: string 23 | description: The git branch to clone. 24 | - name: pathToContext 25 | type: string 26 | description: Set current directory. 27 | - name: githubToken 28 | type: string 29 | description: Reference to the secret name storing the github PAT. 30 | - name: language 31 | type: string 32 | description: Language for CodeQL to scan. 33 | tasks: 34 | - name: fetch-repository 35 | taskRef: 36 | name: t-git-clone 37 | workspaces: 38 | - name: output 39 | workspace: shared-data 40 | params: 41 | - name: url 42 | value: $(params.repoUrl) 43 | - name: deleteExisting 44 | value: "true" 45 | - name: revision 46 | value: $(params.branchName) 47 | - name: codeql-scan 48 | taskRef: 49 | name: t-codeql 50 | runAfter: 51 | - fetch-repository 52 | params: 53 | - name: BUILD_IMAGE 54 | value: $(params.buildImageUrl) 55 | - name: CONTEXT 56 | value: $(params.pathToContext) 57 | - name: GITHUB_TOKEN 58 | value: $(params.githubToken) 59 | - name: REPO 60 | value: $(params.repo) 61 | - name: REPO_URL 62 | value: $(params.repoUrl) 63 | - name: LANGUAGE 64 | value: $(params.language) 65 | workspaces: 66 | - name: source 67 | workspace: shared-data 68 | -------------------------------------------------------------------------------- /tekton/base/pipelines/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: tekon-security-pipline 5 | namePrefix: p- 6 | 7 | resources: 8 | - buildah.yaml 9 | - maven.yaml 10 | - react.yaml 11 | - codeql.yaml 12 | - sonar.yaml 13 | - trivy.yaml 14 | - owasp.yaml 15 | - helm-build-deploy.yaml 16 | -------------------------------------------------------------------------------- /tekton/base/pipelines/sonar.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: sonar 5 | spec: 6 | workspaces: 7 | - name: shared-data 8 | description: | 9 | This workspace will receive the cloned git repo and be passed 10 | to the next Task for the repo's README.md file to be read. 11 | - name: sonar-settings 12 | params: 13 | - name: repoUrl 14 | type: string 15 | - name: branchName 16 | type: string 17 | - name: sonarHostUrl 18 | type: string 19 | - name: sonarProject 20 | type: string 21 | - name: sonarTokenSecret 22 | type: string 23 | tasks: 24 | - name: fetch-repository 25 | taskRef: 26 | name: t-git-clone 27 | workspaces: 28 | - name: output 29 | workspace: shared-data 30 | params: 31 | - name: url 32 | value: $(params.repoUrl) 33 | - name: deleteExisting 34 | value: "true" 35 | - name: revision 36 | value: $(params.branchName) 37 | - name: code-analysis 38 | taskRef: 39 | name: t-sonar-scanner 40 | runAfter: 41 | - fetch-repository 42 | params: 43 | - name: SONAR_HOST_URL 44 | value: $(params.sonarHostUrl) 45 | - name: SONAR_PROJECT_KEY 46 | value: $(params.sonarProject) 47 | - name: SONAR_TOKEN_SECRET 48 | value: $(params.sonarTokenSecret) 49 | workspaces: 50 | - name: source 51 | workspace: shared-data 52 | - name: sonar-settings 53 | workspace: sonar-settings 54 | -------------------------------------------------------------------------------- /tekton/base/pipelines/trivy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: trivy 5 | spec: 6 | workspaces: 7 | - name: shared-data 8 | description: | 9 | This workspace will receive the cloned git repo and be passed 10 | to the next Task for the repo's README.md file to be read. 11 | params: 12 | - name: targetImage 13 | type: string 14 | description: The URL of the image to be Scanned. 15 | - name: imageRegistryUser 16 | type: string 17 | description: The secret name of the secret holding the username. 18 | - name: imageRegistryPass 19 | type: string 20 | description: The secret name of the secret holding the password. 21 | tasks: 22 | - name: trivy-scan 23 | taskRef: 24 | name: t-trivy-scanner 25 | params: 26 | - name: TARGET_IMAGE 27 | value: $(params.targetImage) 28 | - name: IMAGE_REGISTRY_USER 29 | value: $(params.imageRegistryUser) 30 | - name: IMAGE_REGISTRY_PASS 31 | value: $(params.imageRegistryPass) 32 | workspaces: 33 | - name: source 34 | workspace: shared-data 35 | -------------------------------------------------------------------------------- /tekton/base/tasks/add-issue.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: add-issue 5 | spec: 6 | workspaces: 7 | - name: source 8 | - name: owasp-settings 9 | optional: true 10 | mountPath: /zap/wrk 11 | params: 12 | - name: title 13 | type: string 14 | description: Issue Title 15 | - name: body 16 | type: string 17 | default: '' 18 | description: The body of the Issue - Zap Scan Result 19 | - name: github-secret 20 | type: string 21 | default: 'github' 22 | description: "The name of the secret that has your github username and token" 23 | steps: 24 | - name: run-commands 25 | image: docker.io/michaelin/github-cli:latest 26 | script: | 27 | #!/usr/bin/env bash 28 | # git login 29 | #echo "GH CLI Auth" 30 | #echo $(params.github-secret) 31 | #echo $SECRET > token.txt 32 | #gh auth login --with-token < token.txt 33 | #rm token.txt 34 | # git create issue 35 | echo "GH Creat issue" 36 | #echo $GITHUB_USER 37 | #echo $GITHUB_EMAIL 38 | #gh issue create -t "$(params.title)" -b "$(params.body)" 39 | result=$(< /zap/wrk/owasp-quick-results.md) 40 | echo "echo" 41 | echo "$result" 42 | gh issue create -t "Tekton Zap Scan Result" -b "$result" 43 | workingDir: $(workspaces.source.path) 44 | env: 45 | - name: SECRET 46 | valueFrom: 47 | secretKeyRef: 48 | name: $(params.github-secret) 49 | key: github-token 50 | - name: GITHUB_TOKEN 51 | valueFrom: 52 | secretKeyRef: 53 | name: $(params.github-secret) 54 | key: password 55 | - name: GITHUB_USER 56 | valueFrom: 57 | secretKeyRef: 58 | name: $(params.github-secret) 59 | key: username 60 | - name: GITHUB_EMAIL 61 | valueFrom: 62 | secretKeyRef: 63 | name: $(params.github-secret) 64 | key: email 65 | -------------------------------------------------------------------------------- /tekton/base/tasks/codeql/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | # tzdata install needs to be non-interactive 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | 6 | # install/update basics and python 7 | RUN apt update 8 | 9 | RUN apt-get install -y \ 10 | software-properties-common \ 11 | vim \ 12 | curl \ 13 | wget \ 14 | git \ 15 | build-essential \ 16 | unzip \ 17 | apt-transport-https \ 18 | python3.8 \ 19 | python3-venv \ 20 | python3-pip \ 21 | python3-setuptools \ 22 | python3-dev \ 23 | gnupg \ 24 | g++ \ 25 | make \ 26 | gcc \ 27 | apt-utils \ 28 | rsync \ 29 | file \ 30 | dos2unix \ 31 | gettext && \ 32 | apt-get clean && \ 33 | rm -f /usr/bin/python /usr/bin/pip && \ 34 | ln -s /usr/bin/python3.8 /usr/bin/python && \ 35 | ln -s /usr/bin/pip3 /usr/bin/pip 36 | 37 | # Install latest codeQL 38 | ENV CODEQL_HOME /usr/local/codeql-home 39 | RUN mkdir -p ${CODEQL_HOME} 40 | 41 | RUN wget -O codeql-bundle.tar.gz https://github.com/github/codeql-action/releases/download/codeql-bundle-20211025/codeql-bundle.tar.gz &&\ 42 | tar -xvzf codeql-bundle.tar.gz &&\ 43 | cp -R ./codeql ${CODEQL_HOME} 44 | 45 | ENV PATH="${CODEQL_HOME}/codeql:${PATH}" 46 | 47 | ENV PYTHONIOENCODING=utf-8 48 | ENTRYPOINT ["codeql"] 49 | -------------------------------------------------------------------------------- /tekton/base/tasks/codeql/codeql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: codeql 5 | spec: 6 | params: 7 | - name: BUILD_IMAGE 8 | default: docker.io/gregnrobinson/codeql-cli:latest 9 | description: Reference of the image buildah will produce. 10 | - name: CONTEXT 11 | description: Path to codeql source code. 12 | default: . 13 | - name: GITHUB_TOKEN 14 | description: A Github PAT with repo access. 15 | default: github-token 16 | - name: REPO 17 | description: Repo short form name. 18 | - name: REPO_URL 19 | description: Full clone Url. 20 | - name: LANGUAGE 21 | description: CodeQL language to scan. 22 | default: javascript 23 | workspaces: 24 | - name: source 25 | description: | 26 | Shared workspace including the repo source code. 27 | steps: 28 | - name: codeql-resolve-packs 29 | image: $(params.BUILD_IMAGE) 30 | workingDir: $(workspaces.source.path) 31 | script: | 32 | codeql resolve languages &&\ 33 | codeql resolve qlpacks 34 | - name: codeql-create-db 35 | resources: 36 | requests: 37 | memory: 2Gi 38 | cpu: 600m 39 | limits: 40 | memory: 4Gi 41 | cpu: 900m 42 | image: $(params.BUILD_IMAGE) 43 | workingDir: $(workspaces.source.path) 44 | script: | 45 | codeql database create \ 46 | --language=$(params.LANGUAGE) /workspace/source/$(params.LANGUAGE)-db 47 | - name: codeql-analyze-db 48 | resources: 49 | requests: 50 | memory: 2Gi 51 | cpu: 800m 52 | limits: 53 | memory: 4Gi 54 | cpu: 900m 55 | image: $(params.BUILD_IMAGE) 56 | workingDir: $(workspaces.source.path) 57 | script: | 58 | codeql database analyze /workspace/source/$(params.LANGUAGE)-db --format=sarif-latest --output=/workspace/source/$(params.LANGUAGE)-results 59 | codeql github upload-results --repository=$(params.REPO) --ref=refs/heads/main --sarif=/workspace/source/$(params.LANGUAGE)-results 60 | env: 61 | - name: GITHUB_TOKEN 62 | valueFrom: 63 | secretKeyRef: 64 | name: $(params.GITHUB_TOKEN) 65 | key: secretToken 66 | -------------------------------------------------------------------------------- /tekton/base/tasks/codeql/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - codeql.yaml 6 | -------------------------------------------------------------------------------- /tekton/base/tasks/create-pr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: task-create-pr 5 | spec: 6 | workspaces: 7 | - name: source 8 | params: 9 | - name: title 10 | type: string 11 | description: PR Title 12 | - name: body 13 | type: string 14 | default: "" 15 | description: The body of the PR request 16 | - name: github-secret 17 | type: string 18 | default: github 19 | description: "The name of the secret that has your github username and token" 20 | steps: 21 | - name: run-commands 22 | image: docker.io/michaelin/github-cli:latest 23 | script: | 24 | #!/usr/bin/env bash 25 | 26 | # git create PR 27 | gh pr create -t "$(params.title)" -b "$(params.body)" 28 | workingDir: $(workspaces.source.path) 29 | env: 30 | - name: GITHUB_TOKEN 31 | valueFrom: 32 | secretKeyRef: 33 | name: $(params.github-secret) 34 | key: password 35 | - name: GITHUB_USER 36 | valueFrom: 37 | secretKeyRef: 38 | name: $(params.github-secret) 39 | key: username 40 | - name: GITHUB_EMAIL 41 | valueFrom: 42 | secretKeyRef: 43 | name: $(params.github-secret) 44 | key: email 45 | -------------------------------------------------------------------------------- /tekton/base/tasks/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: deploy 5 | spec: 6 | params: 7 | - name: NAME 8 | type: string 9 | - name: NAMESPACE 10 | type: string 11 | steps: 12 | - name: run-commands 13 | image: quay.io/openshift/origin-cli:latest 14 | script: | 15 | #!/usr/bin/env bash 16 | 17 | oc rollout restart deployment/$(inputs.params.NAME) -n $(inputs.params.NAMESPACE) 18 | oc rollout status deploy/$(inputs.params.NAME) -n $(inputs.params.NAMESPACE) -------------------------------------------------------------------------------- /tekton/base/tasks/generate-id.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: generate-id 5 | spec: 6 | workspaces: 7 | - name: source 8 | results: 9 | - description: The short commit SHA that was fetched by this Task 10 | name: short-commit 11 | - description: Unique build identifier 12 | name: build-uid 13 | steps: 14 | - name: generate 15 | workingDir: $(workspaces.source.path) 16 | image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.12.1 17 | script: | 18 | #!/usr/bin/env sh 19 | 20 | # Get short commit 21 | export SHORT_SHA=$(git rev-parse --short HEAD) 22 | echo -n "$SHORT_SHA" > $(results.short-commit.path) 23 | 24 | # Generate uinque UID 25 | export BUILD_UID=$(printf '%s ' $(date) | cksum | cut -f -1 -d ' ') 26 | echo -n "$BUILD_UID" > $(results.build-uid.path) 27 | 28 | echo "Generated ID $SHORT_SHA-$BUILD_UID" 29 | -------------------------------------------------------------------------------- /tekton/base/tasks/helm-deploy.yaml: -------------------------------------------------------------------------------- 1 | # This Task will do a helm upgrade based on the given helm repo and chart 2 | apiVersion: tekton.dev/v1beta1 3 | kind: Task 4 | metadata: 5 | name: helm-deploy 6 | labels: 7 | app.kubernetes.io/version: "0.2" 8 | annotations: 9 | tekton.dev/categories: Deployment 10 | tekton.dev/pipelines.minVersion: "0.12.1" 11 | tekton.dev/tags: helm 12 | tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le,linux/arm64" 13 | spec: 14 | description: >- 15 | These tasks will install / upgrade a helm chart into your Kubernetes / 16 | OpenShift Cluster using Helm 17 | workspaces: 18 | - name: source 19 | params: 20 | - name: HELM_DIR 21 | description: The directory where the helm chart is located. 22 | - name: HELM_VALUES 23 | description: The values file relative to helmDir. 24 | - name: HELM_RELEASE 25 | description: The release name that will be used to identify the deployment. 26 | - name: IMAGE 27 | description: Name of App that will be deployed. 28 | - name: IMAGE_TAG 29 | description: Name of image tag. 30 | - name: HELM_IMAGE 31 | description: "Specify a specific helm image" 32 | default: "docker.io/lachlanevenson/k8s-helm@sha256:5c792f29950b388de24e7448d378881f68b3df73a7b30769a6aa861061fd08ae" #tag: v3.6.0 33 | steps: 34 | - name: helm-deploy 35 | workingDir: $(workspaces.source.path) 36 | image: $(params.HELM_IMAGE) 37 | script: | 38 | helm upgrade --install $(params.HELM_RELEASE) --set image.tag=$(params.IMAGE_TAG) -f $(params.HELM_DIR)/$(params.HELM_VALUES) $(params.HELM_DIR) 39 | -------------------------------------------------------------------------------- /tekton/base/tasks/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: tekon-tasks 5 | namePrefix: t- 6 | 7 | resources: 8 | - buildah.yaml 9 | - git-clone.yaml 10 | - react-workspace.yaml 11 | - react-deploy.yaml 12 | - react-update.yaml 13 | - mvn-build.yaml 14 | - mvn-sonar-scan.yaml 15 | - npm-sonar-scan.yaml 16 | - sonar-scanner.yaml 17 | - trivy-scanner.yaml 18 | - owasp-scanner.yaml 19 | - create-pr.yaml 20 | - deploy.yaml 21 | - generate-id.yaml 22 | - helm-deploy.yaml 23 | - yq.yaml 24 | - ./codeql 25 | - add-issue.yaml 26 | -------------------------------------------------------------------------------- /tekton/base/tasks/npm-sonar-scan.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: npm-sonar-scan 5 | spec: 6 | workspaces: 7 | - name: source 8 | params: 9 | - name: SONAR_SERVER_URL 10 | default: "http://sonarqube.dev-tools:9000" 11 | description: The location of sonarqube, passed as an environment variable SONAR_SERVER_URL 12 | steps: 13 | - name: quality 14 | image: registry.redhat.io/ubi8/nodejs-14:latest 15 | command: 16 | - /bin/sh 17 | - -c 18 | args: 19 | - |- 20 | echo "Performing quality check" 21 | mkdir -p coverage 22 | mkdir -p reports/dependency-check 23 | dependency-check.sh --format ALL -s . --out reports/dependency-check --project "product-catalog-client" 24 | npm run sonar 25 | echo "Quality check complete, see results in sonarqube" 26 | env: 27 | - name: SONAR_SERVER_URL 28 | value: $(params.SONAR_SERVER_URL) 29 | workingDir: $(workspaces.source.path) 30 | volumeMounts: 31 | - name: dependency-cache 32 | mountPath: /opt/dependency-check/data 33 | volumes: 34 | - name: dependency-cache 35 | persistentVolumeClaim: 36 | claimName: dependency-cache 37 | -------------------------------------------------------------------------------- /tekton/base/tasks/npm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: npm 5 | spec: 6 | workspaces: 7 | - name: source 8 | steps: 9 | - name: npm-install 10 | image: registry.redhat.io/ubi8/nodejs-14:latest 11 | command: 12 | - /bin/sh 13 | - -c 14 | args: 15 | - npm install --package-lock 16 | workingDir: $(workspaces.source.path) 17 | - name: build 18 | image: registry.redhat.io/ubi8/nodejs-14:latest 19 | command: 20 | - /bin/sh 21 | - -c 22 | args: 23 | - npm run build 24 | workingDir: $(workspaces.source.path) 25 | - name: copy-dist 26 | image: registry.redhat.io/ubi8/nodejs-14:latest 27 | command: 28 | - /bin/sh 29 | - -c 30 | args: 31 | - cp -R ./dist/* $(workspaces.source.path) 32 | workingDir: $(workspaces.source.path) 33 | - name: save-commit-sha 34 | image: docker.io/maven:3.6.3-jdk-8 35 | command: 36 | - '/bin/bash' 37 | - '-c' 38 | args: 39 | - |- 40 | mkdir -p $(workspaces.source.path)/git-sha 41 | git rev-parse --short HEAD | tee $(workspaces.source.path)/git-sha/commit-id 42 | workingDir: $(workspaces.source.path) 43 | -------------------------------------------------------------------------------- /tekton/base/tasks/owasp-scanner.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: owasp-scanner 5 | labels: 6 | app.kubernetes.io/version: "0.1" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/categories: Security 10 | tekton.dev/tags: security 11 | tekton.dev/displayName: "owasp zap scanner" 12 | tekton.dev/platforms: "linux/amd64" 13 | spec: 14 | description: >- 15 | The worlds most widely used web app scanner. Free and open source. 16 | Actively maintained by a dedicated international team of volunteers. 17 | 18 | workspaces: 19 | - name: source 20 | - name: owasp-settings 21 | optional: true 22 | mountPath: /zap/wrk 23 | params: 24 | - name: TARGET_URL 25 | description: Host URL where the sonarqube server is running 26 | default: "https://example.com" 27 | - name: SCAN_TYPE 28 | description: Options include quick or full. 29 | default: "quick" 30 | - name: SCAN_DURATION 31 | description: The duration of the OWASP scan. 32 | default: "1" 33 | steps: 34 | - name: owasp-scan 35 | image: owasp/zap2docker-stable 36 | workingDir: $(workspaces.owasp-settings.path) 37 | script: | 38 | #!/bin/bash 39 | 40 | if [ $(params.SCAN_TYPE) = "quick" ] 41 | then 42 | echo "performing quick scan" 43 | zap-baseline.py -t $(params.TARGET_URL) -d -g gen.conf -J owasp-quick-results.json -m $(params.SCAN_DURATION) -I 44 | cat $(workspaces.owasp-settings.path)/owasp-quick-results.json 45 | elif [ $(params.SCAN_TYPE) = "full" ] 46 | then 47 | echo "performing full scan" 48 | zap-full-scan.py -t $(params.TARGET_URL) -d -g gen.conf -J owasp-full-results.json -m $(params.SCAN_DURATION) -I 49 | cat $(workspaces.owasp-settings.path)/owasp-full-results.json 50 | else 51 | echo "ERROR: Scan type must be set to quick or full." 52 | exit 1 53 | fi 54 | -------------------------------------------------------------------------------- /tekton/base/tasks/react-deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: react-deploy 5 | labels: 6 | app.kubernetes.io/version: "0.2" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/categories: Build Tools 10 | tekton.dev/tags: build-tool 11 | tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le" 12 | spec: 13 | params: 14 | - name: APP_NAME 15 | type: string 16 | - name: TAG 17 | type: string 18 | description: Image tag of the imagestream 19 | - name: NAMESPACE 20 | type: string 21 | description: Namespace tobe deploy 22 | steps: 23 | - name: deploy 24 | args: 25 | - new-app 26 | - $(params.APP_NAME):$(params.TAG) 27 | - '--name=$(params.APP_NAME)' 28 | - '--namespace=$(params.NAMESPACE)' 29 | command: 30 | - oc 31 | image: openshift/origin-cli:latest 32 | resources: {} 33 | - name: patch-port 34 | args: 35 | - patch 36 | - service 37 | - $(params.APP_NAME) 38 | - '--patch' 39 | - | 40 | { 41 | "spec": { 42 | "ports": [ 43 | { 44 | "name": "$(params.APP_NAME)", 45 | "port": 8080, 46 | "targetPort": 3000 47 | } 48 | ] 49 | } 50 | } 51 | ## the default port created by s2i is 8080, while react runs on port 3000 52 | command: 53 | - oc 54 | image: openshift/origin-cli:latest 55 | resources: {} 56 | - name: expose 57 | args: 58 | - create 59 | - route 60 | - edge 61 | - $(params.APP_NAME) 62 | - '--service=$(params.APP_NAME)' 63 | - '--port=3000' 64 | command: 65 | - oc 66 | image: openshift/origin-cli:latest 67 | resources: {} 68 | -------------------------------------------------------------------------------- /tekton/base/tasks/react-update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: react-update 5 | labels: 6 | app.kubernetes.io/version: "0.2" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/categories: Build Tools 10 | tekton.dev/tags: build-tool 11 | tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le" 12 | spec: 13 | params: 14 | - name: APP_NAME 15 | type: string 16 | - name: TAG 17 | type: string 18 | description: Image tag of the imagestream 19 | - name: NAMESPACE 20 | type: string 21 | description: Namespace tobe deploy 22 | steps: 23 | - name: deploy 24 | args: 25 | - set 26 | - image 27 | - deploymentconfig/$(params.APP_NAME) 28 | - $(params.APP_NAME)=$(params.APP_NAME):$(params.TAG) 29 | - '--namespace=$(params.NAMESPACE)' 30 | command: 31 | - oc 32 | image: openshift/origin-cli:latest 33 | resources: {} 34 | -------------------------------------------------------------------------------- /tekton/base/tasks/react-workspace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: react-workspace 5 | labels: 6 | app.kubernetes.io/version: "0.2" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/categories: Build Tools 10 | tekton.dev/tags: build-tool 11 | tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le" 12 | spec: 13 | params: 14 | - description: 'path to context, to be moved to the root directory' 15 | name: CONTEXT_DIR 16 | type: string 17 | steps: 18 | - args: 19 | - | 20 | cp -r /workspace/source/$(params.CONTEXT_DIR)/* /workspace/source 21 | command: 22 | - sh 23 | - '-c' 24 | image: registry.redhat.io/ubi8/ubi-minimal:latest 25 | name: adjust-workspace 26 | resources: {} 27 | workspaces: 28 | - description: workspace of clone repo 29 | name: source 30 | -------------------------------------------------------------------------------- /tekton/base/tasks/trivy-scanner.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: trivy-scanner 5 | labels: 6 | app.kubernetes.io/version: "0.1" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/categories: Security 10 | tekton.dev/tags: security 11 | tekton.dev/displayName: "trivy scanner" 12 | tekton.dev/platforms: "linux/amd64" 13 | spec: 14 | description: >- 15 | Trivy (tri pronounced like trigger, vy pronounced like envy) is a simple and comprehensive scanner 16 | for vulnerabilities in container images, file systems, and Git repositories, as well as for configuration 17 | issues. Trivy detects vulnerabilities of OS packages (Alpine, RHEL, CentOS, etc.) and language-specific 18 | packages (Bundler, Composer, npm, yarn, etc.). In addition, Trivy scans Infrastructure as Code (IaC) files 19 | such as Terraform, Dockerfile and Kubernetes, to detect potential configuration issues that expose your 20 | deployments to the risk of attack. Trivy is easy to use. Just install the binary and you're ready to scan. 21 | 22 | workspaces: 23 | - name: source 24 | params: 25 | - name: TARGET_IMAGE 26 | description: Image to scan against. 27 | default: "python:3.4-alpine" 28 | - name: IMAGE_REGISTRY_USER 29 | description: The secret name of the secret holding the username. 30 | default: image-registry-username 31 | - name: IMAGE_REGISTRY_PASS 32 | description: The secret name of the secret holding the password. 33 | default: image-registry-password 34 | steps: 35 | - name: scan-image-vulnerbilities 36 | image: docker.io/aquasec/trivy 37 | workingDir: $(workspaces.source.path) 38 | script: | 39 | trivy image $(params.TARGET_IMAGE) 40 | env: 41 | - name: TRIVY_USERNAME 42 | valueFrom: 43 | secretKeyRef: 44 | name: $(params.IMAGE_REGISTRY_USER) 45 | key: $(params.IMAGE_REGISTRY_USER) 46 | - name: TRIVY_PASSWORD 47 | valueFrom: 48 | secretKeyRef: 49 | name: $(params.IMAGE_REGISTRY_PASS) 50 | key: $(params.IMAGE_REGISTRY_PASS) 51 | -------------------------------------------------------------------------------- /tekton/base/tasks/yq.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: yq 5 | spec: 6 | workspaces: 7 | - name: source 8 | params: 9 | - name: commands 10 | type: string 11 | description: The set of commands to run 12 | steps: 13 | - name: yq 14 | workingDir: $(workspaces.source.path) 15 | image: mikefarah/yq:3.3.2 16 | script: | 17 | #!/usr/bin/env sh 18 | echo "Running: '$(params.commands)'" 19 | $(params.commands) 20 | -------------------------------------------------------------------------------- /tekton/base/triggers/ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: el-build-push-image-listener-ingress 5 | annotations: 6 | kubernetes.io/ingress.class: nginx 7 | nginx.ingress.kubernetes.io/use-regex: "true" 8 | nginx.ingress.kubernetes.io/ssl-redirect: "false" 9 | spec: 10 | rules: 11 | - host: tekton-pipelines.gregrobinson.ca 12 | http: 13 | paths: 14 | - path: /.* 15 | pathType: Prefix 16 | backend: 17 | service: 18 | name: el-build-push-image-tekton-trigger-listener 19 | port: 20 | number: 8080 21 | -------------------------------------------------------------------------------- /tekton/base/triggers/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: tekon-triggers 5 | resources: 6 | - ingress.yaml 7 | # switch to use the default serviceAccount/pipeline 8 | - rbac.yaml 9 | - trigger-react-build.yaml 10 | - trigger-flask-web.yaml 11 | - trigger-maven-build.yaml 12 | -------------------------------------------------------------------------------- /tekton/base/triggers/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: service-tekton-triggers-sa 5 | --- 6 | apiVersion: rbac.authorization.k8s.io/v1 7 | kind: Role 8 | metadata: 9 | name: tekton-triggers-example-minimal 10 | rules: 11 | # EventListeners need to be able to fetch all namespaced resources 12 | - apiGroups: ["triggers.tekton.dev"] 13 | resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] 14 | verbs: ["get", "list", "watch"] 15 | - apiGroups: [""] 16 | # configmaps is needed for updating logging config 17 | resources: ["configmaps"] 18 | verbs: ["get", "list", "watch"] 19 | # Permissions to create resources in associated TriggerTemplates 20 | - apiGroups: ["tekton.dev"] 21 | resources: ["pipelineruns", "taskruns"] 22 | verbs: ["create"] 23 | - apiGroups: [""] 24 | resources: ["serviceaccounts"] 25 | verbs: ["get", "watch", "list"] 26 | --- 27 | apiVersion: rbac.authorization.k8s.io/v1 28 | kind: RoleBinding 29 | # automountServiceAccountToken: false 30 | metadata: 31 | name: tekton-triggers-example-binding 32 | subjects: 33 | - kind: ServiceAccount 34 | name: service-tekton-triggers-sa 35 | roleRef: 36 | apiGroup: rbac.authorization.k8s.io 37 | kind: Role 38 | name: tekton-triggers-example-minimal 39 | -------------------------------------------------------------------------------- /tekton/base/triggers/trigger-react-build.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: triggers.tekton.dev/v1alpha1 2 | kind: TriggerTemplate 3 | metadata: 4 | name: react-build-trigger 5 | spec: 6 | params: 7 | - name: appName 8 | default: simple-react 9 | - name: repoUrl 10 | default: https://github.com/bcgov/pipeline-templates.git 11 | - name: branchName 12 | default: main 13 | - name: pathToContext 14 | default: ./tekton/demo/simple-react 15 | - name: imageTag 16 | default: v1 17 | resourcetemplates: 18 | - apiVersion: tekton.dev/v1beta1 19 | kind: PipelineRun 20 | metadata: 21 | generateName: react-build-run- 22 | spec: 23 | pipelineRef: 24 | name: p-react-build 25 | params: 26 | - name: appName 27 | value: $(tt.params.appName) 28 | - name: repoUrl 29 | value: $(tt.params.repoUrl) 30 | - name: branchName 31 | value: $(tt.params.branchName) 32 | - name: pathToContext 33 | value: $(tt.params.pathToContext) 34 | - name: imageTag 35 | value: $(tt.params.imageTag) 36 | workspaces: 37 | - name: shared-data 38 | volumeClaimTemplate: 39 | spec: 40 | accessModes: 41 | - ReadWriteOnce 42 | resources: 43 | requests: 44 | storage: 100Mi 45 | --- 46 | apiVersion: triggers.tekton.dev/v1alpha1 47 | kind: EventListener 48 | metadata: 49 | name: react-build-event-listener 50 | spec: 51 | serviceAccountName: pipeline 52 | triggers: 53 | - name: github-listener 54 | interceptors: 55 | - github: 56 | secretRef: 57 | secretName: github-webhook-secret 58 | secretKey: secretToken 59 | eventTypes: 60 | - pull_request 61 | - push 62 | bindings: 63 | - ref: react-build-trigger-binding 64 | template: 65 | ref: react-build-trigger 66 | --- 67 | apiVersion: triggers.tekton.dev/v1alpha1 68 | kind: TriggerBinding 69 | metadata: 70 | name: react-build-trigger-binding 71 | spec: 72 | params: 73 | - name: branchName 74 | value: $(body.ref) 75 | - name: repoUrl 76 | value: $(body.repository.url) 77 | - name: contenttype 78 | value: $(header.Content-Type) 79 | - name: imageTag 80 | value: $(body.head_commit.message) 81 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/python:3.7-alpine 2 | WORKDIR /app 3 | 4 | COPY . . 5 | 6 | ENV FLASK_APP=./app.py 7 | ENV FLASK_RUN_HOST=0.0.0.0 8 | ENV FLASK_RUN_PORT=80 9 | 10 | RUN apk add --no-cache gcc musl-dev linux-headers 11 | RUN pip install -r requirements.txt 12 | 13 | EXPOSE 80 14 | EXPOSE 5000 15 | CMD ["flask", "run"] 16 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | import requests 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route("/") 7 | def index(): 8 | url = "https://api.quotable.io/random" 9 | data = requests.get(url) 10 | response = data.json() 11 | quote = response["content"] 12 | author = response["author"] 13 | return render_template("index.html", quote=quote, author=author) 14 | 15 | if __name__ == "__main__": 16 | app.run() 17 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/docker-build.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: PipelineRun 3 | metadata: 4 | generateName: docker-build 5 | spec: 6 | pipelineRef: 7 | name: p-docker-build 8 | params: 9 | - name: appName 10 | value: flask-web 11 | - name: repoUrl 12 | value: git@github.com:gregnrobinson/tekton.git 13 | - name: branchName 14 | value: main 15 | - name: dockerfile 16 | value: ./Dockerfile 17 | - name: pathToContext 18 | value: ./demo/flask-web 19 | - name: pathToYamlFile 20 | value: /workspace/source/tasks/deploy-using-kubectl/deployment.yaml 21 | - name: imageUrl 22 | value: gregnrobinson/tkn-flask-web 23 | - name: imageTag 24 | value: latest 25 | workspaces: 26 | - name: shared-data 27 | volumeClaimTemplate: 28 | spec: 29 | accessModes: 30 | - ReadWriteOnce 31 | resources: 32 | requests: 33 | storage: 1Gi 34 | - name: docker-config 35 | secret: 36 | secretName: tkn-docker-credentials 37 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: web 3 | description: A Helm chart for managing a web frontend. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mychart.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mychart.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mychart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mychart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "mychart.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "mychart.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "mychart.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "mychart.labels" -}} 37 | helm.sh/chart: {{ include "mychart.chart" . }} 38 | {{ include "mychart.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "mychart.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "mychart.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "mychart.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "mychart.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | selector: 12 | matchLabels: 13 | {{- include "mychart.selectorLabels" . | nindent 6 }} 14 | template: 15 | metadata: 16 | {{- with .Values.podAnnotations }} 17 | annotations: 18 | {{- toYaml . | nindent 8 }} 19 | {{- end }} 20 | labels: 21 | {{- include "mychart.selectorLabels" . | nindent 8 }} 22 | spec: 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "mychart.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | ports: 37 | - name: http 38 | containerPort: 80 39 | protocol: TCP 40 | livenessProbe: 41 | httpGet: 42 | path: / 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: / 47 | port: http 48 | resources: 49 | {{- toYaml .Values.resources | nindent 12 }} 50 | {{- with .Values.nodeSelector }} 51 | nodeSelector: 52 | {{- toYaml . | nindent 8 }} 53 | {{- end }} 54 | {{- with .Values.affinity }} 55 | affinity: 56 | {{- toYaml . | nindent 8 }} 57 | {{- end }} 58 | {{- with .Values.tolerations }} 59 | tolerations: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "mychart.fullname" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "mychart.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "mychart.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "mychart.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/route.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.route.enabled -}} 2 | apiVersion: route.openshift.io/v1 3 | kind: Route 4 | metadata: 5 | name: {{ include "mychart.fullname" . }} 6 | spec: 7 | host: {{ .Values.route.host }} 8 | port: 9 | targetPort: {{ .Values.route.port }} 10 | to: 11 | kind: Service 12 | name: {{ include "mychart.fullname" . }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "mychart.fullname" . }} 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | {{- with .Values.service.annotations }} 8 | annotations: 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | spec: 12 | type: {{ .Values.service.type }} 13 | ports: 14 | - port: {{ .Values.service.port }} 15 | targetPort: http 16 | protocol: TCP 17 | name: http 18 | selector: 19 | {{- include "mychart.selectorLabels" . | nindent 4 }} 20 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "mychart.serviceAccountName" . }} 6 | labels: 7 | {{- include "mychart.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "mychart.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "mychart.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/helm/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for mychart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 4 6 | 7 | image: 8 | repository: gregnrobinson/tkn-flask-web 9 | pullPolicy: Always 10 | tag: latest 11 | 12 | imagePullSecrets: [name: docker-config-path] 13 | nameOverride: "" 14 | fullnameOverride: "" 15 | 16 | serviceAccount: 17 | create: true 18 | annotations: {} 19 | name: "" 20 | 21 | podAnnotations: {} 22 | 23 | podSecurityContext: {} 24 | # fsGroup: 2000 25 | 26 | securityContext: {} 27 | 28 | service: 29 | type: ClusterIP 30 | port: 80 31 | annotations: {} 32 | 33 | route: 34 | enabled: true 35 | host: flask.demo.local 36 | port: 80 37 | 38 | ingress: 39 | enabled: false 40 | className: "" 41 | annotations: 42 | kubernetes.io/ingress.class: nginx 43 | nginx.ingress.kubernetes.io/use-regex: "true" 44 | hosts: 45 | - host: flask.exmaple.com 46 | paths: 47 | - path: / 48 | pathType: Prefix 49 | tls: [] 50 | # - secretName: chart-example-tls 51 | # hosts: 52 | # - chart-example.local 53 | 54 | resources: {} 55 | # We usually recommend not to specify default resources and to leave this as a conscious 56 | # choice for the user. This also increases chances charts run on environments with little 57 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 58 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 59 | # limits: 60 | # cpu: 100m 61 | # memory: 128Mi 62 | # requests: 63 | # cpu: 100m 64 | # memory: 128Mi 65 | 66 | autoscaling: 67 | enabled: false 68 | minReplicas: 1 69 | maxReplicas: 100 70 | targetCPUUtilizationPercentage: 80 71 | targetMemoryUtilizationPercentage: 80 72 | 73 | nodeSelector: {} 74 | 75 | tolerations: [] 76 | 77 | affinity: {} 78 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | requests 3 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/favicon.png -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-brands-400.eot -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-brands-400.woff -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-regular-400.eot -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-regular-400.woff -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-solid-900.eot -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-solid-900.woff -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/images/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/flask-web/static/images/banner.jpg -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/js/browser.min.js: -------------------------------------------------------------------------------- 1 | /* browser.js v1.0 | @ajlkn | MIT licensed */ 2 | var browser=function(){"use strict";var e={name:null,version:null,os:null,osVersion:null,touch:null,mobile:null,_canUse:null,canUse:function(n){e._canUse||(e._canUse=document.createElement("div"));var o=e._canUse.style,r=n.charAt(0).toUpperCase()+n.slice(1);return n in o||"Moz"+r in o||"Webkit"+r in o||"O"+r in o||"ms"+r in o},init:function(){var n,o,r,i,t=navigator.userAgent;for(n="other",o=0,r=[["firefox",/Firefox\/([0-9\.]+)/],["bb",/BlackBerry.+Version\/([0-9\.]+)/],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/],["opera",/OPR\/([0-9\.]+)/],["opera",/Opera\/([0-9\.]+)/],["edge",/Edge\/([0-9\.]+)/],["safari",/Version\/([0-9\.]+).+Safari/],["chrome",/Chrome\/([0-9\.]+)/],["ie",/MSIE ([0-9]+)/],["ie",/Trident\/.+rv:([0-9]+)/]],i=0;i0:!!("ontouchstart"in window),e.mobile="wp"==e.os||"android"==e.os||"ios"==e.os||"bb"==e.os}};return e.init(),e}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser}); 3 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/js/jquery.scrollex.min.js: -------------------------------------------------------------------------------- 1 | /* jquery.scrollex v0.2.1 | (c) @ajlkn | github.com/ajlkn/jquery.scrollex | MIT licensed */ 2 | !function(t){function e(t,e,n){return"string"==typeof t&&("%"==t.slice(-1)?t=parseInt(t.substring(0,t.length-1))/100*e:"vh"==t.slice(-2)?t=parseInt(t.substring(0,t.length-2))/100*n:"px"==t.slice(-2)&&(t=parseInt(t.substring(0,t.length-2)))),t}var n=t(window),i=1,o={};n.on("scroll",function(){var e=n.scrollTop();t.map(o,function(t){window.clearTimeout(t.timeoutId),t.timeoutId=window.setTimeout(function(){t.handler(e)},t.options.delay)})}).on("load",function(){n.trigger("scroll")}),jQuery.fn.scrollex=function(l){var s=t(this);if(0==this.length)return s;if(this.length>1){for(var r=0;r=i&&o>=t};break;case"bottom":h=function(t,e,n,i,o){return n>=i&&o>=n};break;case"middle":h=function(t,e,n,i,o){return e>=i&&o>=e};break;case"top-only":h=function(t,e,n,i,o){return i>=t&&n>=i};break;case"bottom-only":h=function(t,e,n,i,o){return n>=o&&o>=t};break;default:case"default":h=function(t,e,n,i,o){return n>=i&&o>=t}}return c=function(t){var i,o,l,s,r,a,u=this.state,h=!1,c=this.$element.offset();i=n.height(),o=t+i/2,l=t+i,s=this.$element.outerHeight(),r=c.top+e(this.options.top,s,i),a=c.top+s-e(this.options.bottom,s,i),h=this.test(t,o,l,r,a),h!=u&&(this.state=h,h?this.options.enter&&this.options.enter.apply(this.element):this.options.leave&&this.options.leave.apply(this.element)),this.options.scroll&&this.options.scroll.apply(this.element,[(o-r)/(a-r)])},p={id:a,options:u,test:h,handler:c,state:null,element:this,$element:s,timeoutId:null},o[a]=p,s.data("_scrollexId",p.id),p.options.initialize&&p.options.initialize.apply(this),s},jQuery.fn.unscrollex=function(){var e=t(this);if(0==this.length)return e;if(this.length>1){for(var n=0;n1){for(o=0;o=320px. 20 | @include breakpoint('<=xsmall') { 21 | html, body { 22 | min-width: 320px; 23 | } 24 | } 25 | 26 | // Set box model to border-box. 27 | // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice 28 | html { 29 | box-sizing: border-box; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: inherit; 34 | } 35 | 36 | body { 37 | background: _palette(bg); 38 | 39 | // Stops initial animations until page loads. 40 | &.is-preload { 41 | *, *:before, *:after { 42 | @include vendor('animation', 'none !important'); 43 | @include vendor('transition', 'none !important'); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | // Reset. 8 | // Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) 9 | 10 | html, body, div, span, applet, object, 11 | iframe, h1, h2, h3, h4, h5, h6, p, blockquote, 12 | pre, a, abbr, acronym, address, big, cite, 13 | code, del, dfn, em, img, ins, kbd, q, s, samp, 14 | small, strike, strong, sub, sup, tt, var, b, 15 | u, i, center, dl, dt, dd, ol, ul, li, fieldset, 16 | form, label, legend, table, caption, tbody, 17 | tfoot, thead, tr, th, td, article, aside, 18 | canvas, details, embed, figure, figcaption, 19 | footer, header, hgroup, menu, nav, output, ruby, 20 | section, summary, time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | vertical-align: baseline; 26 | } 27 | 28 | article, aside, details, figcaption, figure, 29 | footer, header, hgroup, menu, nav, section { 30 | display: block; 31 | } 32 | 33 | ol, ul { 34 | list-style:none; 35 | } 36 | 37 | blockquote, q { 38 | quotes: none; 39 | 40 | &:before, 41 | &:after { 42 | content: ''; 43 | content: none; 44 | } 45 | } 46 | 47 | table { 48 | border-collapse: collapse; 49 | border-spacing: 0; 50 | } 51 | 52 | body { 53 | line-height: 1; 54 | -webkit-text-size-adjust: none; 55 | } 56 | 57 | mark { 58 | background-color: transparent; 59 | color: inherit; 60 | } 61 | 62 | input::-moz-focus-inner { 63 | border: 0; 64 | padding: 0; 65 | } 66 | 67 | input, select, textarea { 68 | -moz-appearance: none; 69 | -webkit-appearance: none; 70 | -ms-appearance: none; 71 | appearance: none; 72 | } 73 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_actions.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Actions */ 8 | 9 | ul.actions { 10 | @include vendor('display', 'flex'); 11 | cursor: default; 12 | list-style: none; 13 | margin-left: (_size(element-margin) * -0.5); 14 | padding-left: 0; 15 | 16 | li { 17 | padding: 0 0 0 (_size(element-margin) * 0.5); 18 | vertical-align: middle; 19 | } 20 | 21 | &.special { 22 | @include vendor('justify-content', 'center'); 23 | width: 100%; 24 | margin-left: 0; 25 | 26 | li { 27 | &:first-child { 28 | padding-left: 0; 29 | } 30 | } 31 | } 32 | 33 | &.stacked { 34 | @include vendor('flex-direction', 'column'); 35 | margin-left: 0; 36 | 37 | li { 38 | padding: (_size(element-margin) * 0.65) 0 0 0; 39 | 40 | &:first-child { 41 | padding-top: 0; 42 | } 43 | } 44 | } 45 | 46 | &.fit { 47 | width: calc(100% + #{_size(element-margin) * 0.5}); 48 | 49 | li { 50 | @include vendor('flex-grow', '1'); 51 | @include vendor('flex-shrink', '1'); 52 | width: 100%; 53 | 54 | > * { 55 | width: 100%; 56 | } 57 | } 58 | 59 | &.stacked { 60 | width: 100%; 61 | } 62 | } 63 | 64 | @include breakpoint('<=xsmall') { 65 | &:not(.fixed) { 66 | @include vendor('flex-direction', 'column'); 67 | margin-left: 0; 68 | width: 100% !important; 69 | 70 | li { 71 | @include vendor('flex-grow', '1'); 72 | @include vendor('flex-shrink', '1'); 73 | padding: (_size(element-margin) * 0.5) 0 0 0; 74 | text-align: center; 75 | width: 100%; 76 | 77 | > * { 78 | width: 100%; 79 | } 80 | 81 | &:first-child { 82 | padding-top: 0; 83 | } 84 | 85 | input[type="submit"], 86 | input[type="reset"], 87 | input[type="button"], 88 | button, 89 | .button { 90 | width: 100%; 91 | 92 | &.icon { 93 | &:before { 94 | margin-left: -0.5rem; 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_box.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Box */ 8 | 9 | .box { 10 | border-radius: _size(border-radius); 11 | border: solid _size(border-width); 12 | margin-bottom: _size(element-margin); 13 | padding: 1.5rem; 14 | 15 | > :last-child, 16 | > :last-child > :last-child, 17 | > :last-child > :last-child > :last-child { 18 | margin-bottom: 0; 19 | } 20 | 21 | &.alt { 22 | border: 0; 23 | border-radius: 0; 24 | padding: 0; 25 | } 26 | } 27 | 28 | @mixin color-box($p: null) { 29 | .box { 30 | border-color: _palette($p, border); 31 | } 32 | } 33 | 34 | @include color-box; 35 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icon */ 8 | 9 | .icon { 10 | @include icon; 11 | border-bottom: none; 12 | position: relative; 13 | text-align: center; 14 | 15 | > .label { 16 | display: none; 17 | } 18 | 19 | &:before { 20 | line-height: inherit; 21 | } 22 | 23 | &.solid { 24 | &:before { 25 | font-weight: 900; 26 | } 27 | } 28 | 29 | &.brands { 30 | &:before { 31 | font-family: 'Font Awesome 5 Brands'; 32 | } 33 | } 34 | 35 | &.style2 { 36 | &:before { 37 | border-radius: 2.75em; 38 | display: inline-block; 39 | height: 2.75em; 40 | line-height: 2.75em; 41 | width: 2.75em; 42 | } 43 | } 44 | 45 | &.major { 46 | display: block; 47 | margin: 0 0 (_size(element-margin) * 0.5) 0; 48 | 49 | &:before { 50 | font-size: 1.25rem; 51 | } 52 | } 53 | } 54 | 55 | a.icon { 56 | &.style2 { 57 | &:before { 58 | @include vendor('transition', ( 59 | 'background-color #{_duration(transition)} ease-in-out', 60 | 'box-shadow #{_duration(transition)} ease-in-out', 61 | 'color #{_duration(transition)} ease-in-out' 62 | )); 63 | } 64 | } 65 | } 66 | 67 | @mixin color-icon($p: null) { 68 | .icon { 69 | &.style2 { 70 | &:before { 71 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, border); 72 | } 73 | } 74 | } 75 | 76 | a.icon { 77 | &.style2 { 78 | &:hover { 79 | &:before { 80 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, accent); 81 | color: _palette($p, accent); 82 | } 83 | } 84 | 85 | &:active { 86 | &:before { 87 | background-color: transparentize(_palette($p, accent), 0.9); 88 | box-shadow: inset 0 0 0 _size(border-width) _palette($p, accent); 89 | color: _palette($p, accent); 90 | } 91 | } 92 | } 93 | } 94 | } 95 | 96 | @include color-icon; 97 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icons */ 8 | 9 | ul.icons { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding: 0 0.75rem 0 0; 17 | 18 | &:last-child { 19 | padding-right: 0; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_image.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Image */ 8 | 9 | .image { 10 | border: 0; 11 | border-radius: _size(border-radius); 12 | display: inline-block; 13 | position: relative; 14 | 15 | img { 16 | display: block; 17 | border-radius: _size(border-radius); 18 | } 19 | 20 | &.left, 21 | &.right { 22 | width: 40%; 23 | max-width: 10rem; 24 | 25 | img { 26 | width: 100%; 27 | } 28 | } 29 | 30 | &.left { 31 | float: left; 32 | margin: 0 1.5rem 1rem 0; 33 | top: 0.25rem; 34 | } 35 | 36 | &.right { 37 | float: right; 38 | margin: 0 0 1rem 1.5rem; 39 | top: 0.25rem; 40 | } 41 | 42 | &.fit { 43 | display: block; 44 | margin: 0 0 _size(element-margin) 0; 45 | width: 100%; 46 | 47 | img { 48 | width: 100%; 49 | } 50 | } 51 | 52 | &.main { 53 | display: block; 54 | margin: 0 0 (_size(element-margin) * 1.5) 0; 55 | width: 100%; 56 | 57 | img { 58 | width: 100%; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_index.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Index */ 8 | 9 | .index { 10 | > * { 11 | @include padding(3rem, 0); 12 | @include vendor('display', 'flex'); 13 | border-top: solid 1px; 14 | 15 | > header { 16 | @include vendor('flex-grow', '0'); 17 | @include vendor('flex-shrink', '0'); 18 | width: 15rem; 19 | } 20 | 21 | > .content { 22 | @include vendor('flex-grow', '1'); 23 | @include vendor('flex-shrink', '1'); 24 | } 25 | } 26 | 27 | > :first-child { 28 | border-top: 0; 29 | } 30 | 31 | @include breakpoint('<=medium') { 32 | > * { 33 | > header { 34 | width: 11rem; 35 | } 36 | } 37 | } 38 | 39 | @include breakpoint('<=small') { 40 | > * { 41 | > header { 42 | width: 10rem; 43 | } 44 | } 45 | } 46 | 47 | @include breakpoint('<=xsmall') { 48 | > * { 49 | @include vendor('flex-direction', 'column'); 50 | 51 | > header { 52 | width: 100%; 53 | } 54 | } 55 | } 56 | } 57 | 58 | @mixin color-index($p: null) { 59 | .index { 60 | > * { 61 | border-top-color: _palette($p, border); 62 | } 63 | } 64 | } 65 | 66 | @include color-index; 67 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* List */ 8 | 9 | ol { 10 | list-style: decimal; 11 | margin: 0 0 _size(element-margin) 0; 12 | padding-left: 1.25rem; 13 | 14 | li { 15 | padding-left: 0.25rem; 16 | } 17 | } 18 | 19 | ul { 20 | list-style: disc; 21 | margin: 0 0 _size(element-margin) 0; 22 | padding-left: 1rem; 23 | 24 | li { 25 | padding-left: 0.5rem; 26 | } 27 | 28 | &.alt { 29 | list-style: none; 30 | padding-left: 0; 31 | 32 | li { 33 | border-top: solid _size(border-width); 34 | padding: 0.5rem 0; 35 | 36 | &:first-child { 37 | border-top: 0; 38 | padding-top: 0; 39 | } 40 | } 41 | } 42 | } 43 | 44 | dl { 45 | margin: 0 0 _size(element-margin) 0; 46 | 47 | dt { 48 | display: block; 49 | font-weight: _font(weight-bold); 50 | margin: 0 0 (_size(element-margin) * 0.5) 0; 51 | } 52 | 53 | dd { 54 | margin-left: _size(element-margin); 55 | } 56 | 57 | &.style2 { 58 | dt { 59 | width: 25%; 60 | float: left; 61 | } 62 | 63 | dd { 64 | width: 70%; 65 | float: left; 66 | } 67 | 68 | &:after { 69 | content: ''; 70 | display: block; 71 | clear: both; 72 | } 73 | } 74 | } 75 | 76 | @mixin color-list($p: null) { 77 | ul { 78 | &.alt { 79 | li { 80 | border-top-color: _palette($p, border); 81 | } 82 | } 83 | } 84 | } 85 | 86 | @include color-list; 87 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_row.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Row */ 8 | 9 | .row { 10 | @include html-grid(2rem); 11 | 12 | @include breakpoint('<=xlarge') { 13 | @include html-grid(2rem, 'xlarge'); 14 | } 15 | 16 | @include breakpoint('<=large') { 17 | @include html-grid(2rem, 'large'); 18 | } 19 | 20 | @include breakpoint('<=medium') { 21 | @include html-grid(2rem, 'medium'); 22 | } 23 | 24 | @include breakpoint('<=small') { 25 | @include html-grid(2rem, 'small'); 26 | } 27 | 28 | @include breakpoint('<=xsmall') { 29 | @include html-grid(2rem, 'xsmall'); 30 | } 31 | 32 | @include breakpoint('<=xxsmall') { 33 | @include html-grid(2rem, 'xxsmall'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/components/_section.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Section/Article */ 8 | 9 | section, article { 10 | &.special { 11 | text-align: center; 12 | } 13 | } 14 | 15 | header { 16 | p { 17 | position: relative; 18 | margin: (_size(element-margin) * -0.325) 0 (_size(element-margin) * 0.75) 0; 19 | font-style: italic; 20 | } 21 | 22 | h1 + p { 23 | font-size: 1.375rem; 24 | } 25 | 26 | h2 + p { 27 | font-size: 1.25rem; 28 | } 29 | 30 | h3 + p { 31 | font-size: 1.1rem; 32 | } 33 | 34 | h4 + p, 35 | h5 + p, 36 | h6 + p { 37 | font-size: 0.9rem; 38 | } 39 | } 40 | 41 | @mixin color-section($p: null) { 42 | header { 43 | p { 44 | color: _palette($p, fg-light); 45 | } 46 | } 47 | } 48 | 49 | @include color-section; 50 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/layout/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Story by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Wrapper */ 8 | 9 | @mixin wrapper-color($n) { 10 | > .color#{$n} { 11 | background-color: _palette(color#{$n}); 12 | } 13 | } 14 | 15 | #wrapper { 16 | background-color: inherit; 17 | width: 100%; 18 | overflow-x: hidden; 19 | 20 | > .invert { 21 | @include color(invert); 22 | } 23 | 24 | @include wrapper-color(1); 25 | @include wrapper-color(2); 26 | @include wrapper-color(3); 27 | @include wrapper-color(4); 28 | @include wrapper-color(5); 29 | @include wrapper-color(6); 30 | @include wrapper-color(7); 31 | 32 | &.divided { 33 | > * { 34 | box-shadow: inset 0 1px 0 0 _palette(border-alt); 35 | 36 | &:first-child { 37 | box-shadow: none !important; 38 | } 39 | } 40 | 41 | > .invert { 42 | box-shadow: inset 0 1px 0 0 _palette(invert, border-alt); 43 | 44 | &:first-child { 45 | box-shadow: none !important; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/libs/_functions.scss: -------------------------------------------------------------------------------- 1 | /// Removes a specific item from a list. 2 | /// @author Hugo Giraudel 3 | /// @param {list} $list List. 4 | /// @param {integer} $index Index. 5 | /// @return {list} Updated list. 6 | @function remove-nth($list, $index) { 7 | 8 | $result: null; 9 | 10 | @if type-of($index) != number { 11 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 12 | } 13 | @else if $index == 0 { 14 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 15 | } 16 | @else if abs($index) > length($list) { 17 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 18 | } 19 | @else { 20 | 21 | $result: (); 22 | $index: if($index < 0, length($list) + $index + 1, $index); 23 | 24 | @for $i from 1 through length($list) { 25 | 26 | @if $i != $index { 27 | $result: append($result, nth($list, $i)); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | @return $result; 35 | 36 | } 37 | 38 | /// Gets a value from a map. 39 | /// @author Hugo Giraudel 40 | /// @param {map} $map Map. 41 | /// @param {string} $keys Key(s). 42 | /// @return {string} Value. 43 | @function val($map, $keys...) { 44 | 45 | @if nth($keys, 1) == null { 46 | $keys: remove-nth($keys, 1); 47 | } 48 | 49 | @each $key in $keys { 50 | $map: map-get($map, $key); 51 | } 52 | 53 | @return $map; 54 | 55 | } 56 | 57 | /// Gets a duration value. 58 | /// @param {string} $keys Key(s). 59 | /// @return {string} Value. 60 | @function _duration($keys...) { 61 | @return val($duration, $keys...); 62 | } 63 | 64 | /// Gets a font value. 65 | /// @param {string} $keys Key(s). 66 | /// @return {string} Value. 67 | @function _font($keys...) { 68 | @return val($font, $keys...); 69 | } 70 | 71 | /// Gets a misc value. 72 | /// @param {string} $keys Key(s). 73 | /// @return {string} Value. 74 | @function _misc($keys...) { 75 | @return val($misc, $keys...); 76 | } 77 | 78 | /// Gets a palette value. 79 | /// @param {string} $keys Key(s). 80 | /// @return {string} Value. 81 | @function _palette($keys...) { 82 | @return val($palette, $keys...); 83 | } 84 | 85 | /// Gets a size value. 86 | /// @param {string} $keys Key(s). 87 | /// @return {string} Value. 88 | @function _size($keys...) { 89 | @return val($size, $keys...); 90 | } 91 | -------------------------------------------------------------------------------- /tekton/demo/flask-web/static/sass/libs/_vars.scss: -------------------------------------------------------------------------------- 1 | // Misc. 2 | $misc: ( 3 | z-index-base: 10000, 4 | overlay-opacity: 0.5, 5 | lightbox-opacity: 0.75, 6 | gallery-limit: 32, 7 | items-limit: 16 8 | ); 9 | 10 | // Duration. 11 | $duration: ( 12 | menu: 0.5s, 13 | transition: 0.2s, 14 | gallery-lightbox: 0.5s, 15 | gallery-delay: 0.15s, 16 | items-delay: 0.15s, 17 | on-load: 0.75s, 18 | on-scroll: 0.75s 19 | ); 20 | 21 | // Size. 22 | $size: ( 23 | border-radius: 4px, 24 | border-radius-alt: 0.5rem, 25 | border-width: 1px, 26 | element-height: 2.75rem, 27 | element-margin: 2rem, 28 | gutter: 3.5rem, 29 | inner: 64rem, 30 | padding: ( 31 | default: 7rem, 32 | xlarge: 5rem, 33 | large: 4rem, 34 | medium: 3rem, 35 | small: 2rem 36 | ) 37 | ); 38 | 39 | // Font. 40 | $font: ( 41 | family: ('Source Sans Pro', Helvetica, sans-serif), 42 | family-fixed: ('Courier New', monospace), 43 | weight: 300, 44 | weight-bold: 400, 45 | kerning: -0.05em, 46 | kerning-alt: 0.125em 47 | ); 48 | 49 | // Palette. 50 | $palette: ( 51 | color1: #30363d, 52 | color2: #db8992, 53 | color3: #ab7aad, 54 | color4: #897cad, 55 | color5: #7794ce, 56 | color6: #64abb4, 57 | color7: #6ba78c, 58 | 59 | bg: #ffffff, 60 | bg-alt: #eeeeee, 61 | fg: #000000, 62 | fg-bold: #000000, 63 | fg-light: rgba(0,0,0,0.75), 64 | border: rgba(0,0,0,0.2), 65 | border-alt: rgba(0,0,0,0.075), 66 | border-bg: rgba(0,0,0,0.05), 67 | accent: #47D3E5, 68 | 69 | invert: ( 70 | bg: #000000, 71 | bg-alt: #222222, 72 | fg: #ffffff, 73 | fg-bold: #ffffff, 74 | fg-light: #ffffff, 75 | border: rgba(255,255,255,1.0), 76 | border-alt: rgba(255,255,255,0.125), 77 | border-bg: rgba(255,255,255,0.125), 78 | accent: #47D3E5 79 | ), 80 | ); 81 | -------------------------------------------------------------------------------- /tekton/demo/maven-test/src/main/java/com/mycompany/app/App.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.app; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tekton/demo/maven-test/src/test/java/com/mycompany/app/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.app; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | { 12 | /** 13 | * Rigorous Test :-) 14 | */ 15 | @Test 16 | public void shouldAnswerWithTrue() 17 | { 18 | assertTrue( true ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "npm-check": "^6.0.1", 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-scripts": "5.0.1", 13 | "uuid": "^9.0.0", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/simple-react/public/favicon.ico -------------------------------------------------------------------------------- /tekton/demo/simple-react/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/simple-react/public/logo192.png -------------------------------------------------------------------------------- /tekton/demo/simple-react/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcgov/pipeline-templates/68812a8857193f550516a690d2bf924141d7e608/tekton/demo/simple-react/public/logo512.png -------------------------------------------------------------------------------- /tekton/demo/simple-react/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/src/App.js: -------------------------------------------------------------------------------- 1 | import {useState, useRef, useEffect} from 'react' 2 | import Checklist from './Checklist' 3 | 4 | const LOCAL_STORAGE_KEY = 'checklist' 5 | 6 | function App() { 7 | const [tasks, setTasks] = useState([]) 8 | const taskRef = useRef() 9 | 10 | useEffect(() => { 11 | const storedTask = JSON.parse(localStorage.getItem 12 | (LOCAL_STORAGE_KEY)) 13 | if (storedTask) setTasks(storedTask) 14 | }, []) 15 | 16 | useEffect (() => { 17 | localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(tasks)) 18 | }, [tasks]) 19 | 20 | function toggleTask(id) { 21 | const copyTasks = [...tasks] 22 | const task = copyTasks.find(task => task.id === id) 23 | task.complete = !task.complete 24 | setTasks(copyTasks) 25 | } 26 | 27 | 28 | function addTask(e){ 29 | const name = taskRef.current.value 30 | const uuid = require('uuid') 31 | if (name === '') return 32 | setTasks(prevTask => { 33 | return [...prevTask, {id: uuid.v4(), name: name, complete:false}] 34 | }) 35 | taskRef.current.value = null 36 | } 37 | 38 | function clearTask(){ 39 | const copyTask = tasks.filter(task => !task.complete) 40 | setTasks(copyTask) 41 | } 42 | 43 | return ( 44 |
45 |

Checklist

46 |

Your tasks

47 | 48 |
{tasks.filter(task => !task.complete).length} remaining tasks
49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 |
57 | ); 58 | } 59 | 60 | export default App; 61 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/src/Checklist.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Task from './Task' 3 | 4 | export default function Checklist( {tasks, toggleTask} ) { 5 | return ( 6 | tasks.map(task => { 7 | return 8 | }) 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/src/Task.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default function Task( { task, toggleTask } ) { 4 | function handleTask(){ 5 | toggleTask(task.id) 6 | } 7 | return ( 8 |
9 | 14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /tekton/demo/simple-react/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById('root')); 7 | root.render( 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /tekton/overlays/apply/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - ../../base/pipelines 5 | - ../../base/tasks 6 | - ../../base/triggers 7 | -------------------------------------------------------------------------------- /tekton/overlays/secrets/main.py: -------------------------------------------------------------------------------- 1 | import pystache 2 | import sys 3 | import os 4 | import shutil 5 | import configparser 6 | from collections import OrderedDict 7 | 8 | os.chdir("overlays/secrets") 9 | 10 | Config = configparser.ConfigParser() 11 | try: 12 | Config.read("secrets.ini") 13 | except Exception: 14 | pass 15 | 16 | # Order the content of DEFAULT section alphabetically 17 | Config._defaults = OrderedDict( 18 | sorted(Config._defaults.items(), key=lambda t: t[0])) 19 | 20 | # Order the content of each section alphabetically 21 | for section in Config._sections: 22 | Config._sections[section] = OrderedDict( 23 | sorted(Config._sections[section].items(), key=lambda t: t[0])) 24 | 25 | # Order all sections alphabetically 26 | Config._sections = OrderedDict( 27 | sorted(Config._sections.items(), key=lambda t: t[0])) 28 | 29 | # ssh = Config._sections['ssh'] 30 | literals = Config._sections['literals'] 31 | 32 | # try: 33 | # os.makedirs(".secrets") 34 | # except FileExistsError: 35 | # pass 36 | # for key, value in ssh.items(): 37 | # if value: 38 | # new_path = shutil.copy(value, '.secrets') 39 | # ssh[key] = new_path 40 | 41 | input = """apiVersion: kustomize.config.k8s.io/v1beta1 42 | kind: Kustomization 43 | generatorOptions: 44 | disableNameSuffixHash: true 45 | secretGenerator: 46 | {{#literals}} 47 | - name: {{k}} 48 | type: Opaque 49 | literals: 50 | - {{k}}={{v}} 51 | {{/literals}} 52 | # {{#ssh}} 53 | # - name: {{k}} 54 | # files: 55 | # - {{v}} 56 | # {{/ssh}} 57 | """ 58 | 59 | literals = [{"k": k, "v": v} for k, v in literals.items()] 60 | # ssh = [{"k": k, "v": v} for k, v in ssh.items()] 61 | 62 | 63 | class bcolors: 64 | HEADER = '\033[95m' 65 | OKBLUE = '\033[94m' 66 | OKCYAN = '\033[96m' 67 | OKGREEN = '\033[92m' 68 | WARNING = '\033[93m' 69 | FAIL = '\033[91m' 70 | ENDC = '\033[0m' 71 | BOLD = '\033[1m' 72 | UNDERLINE = '\033[4m' 73 | 74 | 75 | print(bcolors.OKCYAN + "Writing secrets to Kustomize..." + bcolors.ENDC) 76 | 77 | original_stdout = sys.stdout 78 | 79 | with open('kustomization.yaml', 'w') as f: 80 | sys.stdout = f 81 | print(pystache.render(input, {"literals": literals})) 82 | sys.stdout = original_stdout 83 | 84 | print(bcolors.OKGREEN + "Completed..." + bcolors.ENDC) 85 | -------------------------------------------------------------------------------- /tekton/overlays/secrets/requirements.txt: -------------------------------------------------------------------------------- 1 | pystache 2 | -------------------------------------------------------------------------------- /tekton/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tekton", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | --------------------------------------------------------------------------------