From d8943e6bb90ca9873873c1e3599455d3abc66880 Mon Sep 17 00:00:00 2001 From: Steven Quan <70890758+stevenquanheycar@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:32:21 +0000 Subject: [PATCH] Initial commit --- .github/CODEOWNERS | 1 + .github/settings.yml | 100 ++++++++++++++++++++++++++++ .github/workflows/pr-title.yml | 36 ++++++++++ .github/workflows/pre-commit.yml | 22 ++++++ .github/workflows/release.yml | 29 ++++++++ .gitignore | 37 +++++++++++ .pre-commit-config.yaml | 19 ++++++ .releaserc | 44 ++++++++++++ CONTRIBUTING.md | 23 +++++++ Dockerfile | 21 ++++++ README.md | 3 + action.yml | 39 +++++++++++ scripts/script.sh | 25 +++++++ scripts/utils.sh | 111 +++++++++++++++++++++++++++++++ 14 files changed, 510 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/settings.yml create mode 100644 .github/workflows/pr-title.yml create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .releaserc create mode 100644 CONTRIBUTING.md create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 action.yml create mode 100755 scripts/script.sh create mode 100755 scripts/utils.sh diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..957fc72 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @hey-car/infra diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 0000000..e95b4e2 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,100 @@ +--- +repository: + name: actions-template + description: | + A Github template repo for public Gh Actions + topics: github, actions, ci, scripts + default_branch: master + + private: true + has_projects: false + has_wiki: false + has_downloads: false + + allow_squash_merge: true + allow_merge_commit: false + allow_rebase_merge: false + delete_branch_on_merge: true + +teams: + - name: infra + permission: admin + +labels: + - name: "help wanted" + color: "#008672" + description: "Extra attention is needed" + - name: "priority: critical" + color: "#b60205" + description: "" + - name: "priority: high" + color: "#d93f0b" + description: "" + - name: "priority: low" + color: "#0e8a16" + description: "" + - name: "priority: medium" + color: "#fbca04" + description: "" + - name: "status: can't reproduce" + color: "#fec1c1" + description: "" + - name: "status: confirmed" + color: "#215cea" + description: "" + - name: "status: duplicate" + color: "#cfd3d7" + description: "This issue or pull request already exists" + - name: "status: needs information" + color: "#fef2c0" + description: "" + - name: "status: wont do/fix" + color: "#eeeeee" + description: "This will not be worked on" + - name: "type: bug" + color: "#d73a4a" + description: "Something isn't working" + - name: "type: discussion" + color: "#d4c5f9" + description: "" + - name: "type: documentation" + color: "#006b75" + description: "" + - name: "type: enhancement" + color: "#84b6eb" + description: "" + - name: "type: epic" + color: "#3E4B9E" + description: "A theme of work that contain sub-tasks" + - name: "type: feature request" + color: "#fbca04" + description: "New feature or request" + - name: "type: question" + color: "#d876e3" + description: "Further information is requested" + +branches: + - name: master + protection: + required_pull_request_reviews: + required_approving_review_count: 2 + dismiss_stale_reviews: true + require_code_owner_reviews: true + bypass_pull_request_allowances: + users: + - supcar + teams: [] + apps: [] + dismissal_restrictions: + users: + - supcar + teams: [] + apps: [] + required_status_checks: null + enforce_admins: true + required_linear_history: true + restrictions: + users: + - supcar + teams: [] + apps: [] diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml new file mode 100644 index 0000000..27038c5 --- /dev/null +++ b/.github/workflows/pr-title.yml @@ -0,0 +1,36 @@ +--- +name: Validate PR title + +on: + pull_request: + types: + - opened + - synchronize + - edited + - ready_for_review + +jobs: + validate: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5.4.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + fix + feat + docs + ci + chore + test + refactor + requireScope: false + subjectPattern: ^[A-z].+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + starts with an uppercase character. + wip: true + validateSingleCommit: true diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..15ba7a9 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,22 @@ +name: Pre-Commit + +on: + pull_request: + types: + - opened + - synchronize + - edited + - ready_for_review + +jobs: + pre-commit: + name: Pre-Commit + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + - name: Run pre-commit hooks + uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f54d8ab --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +--- +name: Release + +on: + push: + branches: + - master + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Release + uses: cycjimmy/semantic-release-action@v4 + with: + semantic_version: 18.0.0 + extra_plugins: | + @semantic-release/changelog@6.0.0 + @semantic-release/git@10.0.0 + conventional-changelog-conventionalcommits@4.6.3 + env: + GITHUB_TOKEN: ${{ secrets.VERSIONING_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92a43e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# General files for the project +pkg/* +*.pyc +bin/* +.project +/.bin +/_test/secrets/*.json + +# OSX leaves these everywhere on SMB shares +._* + +# OSX trash +.DS_Store + +# Files generated by JetBrains IDEs, e.g. IntelliJ IDEA +.idea/ +*.iml + +# Vscode files +.vscode + +# Emacs save files +*~ +\#*\# +.\#* + +# Vim-related files +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist + +# Chart dependencies +**/charts/*.tgz + +.history diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b53c58e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +--- +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-yaml + - id: check-merge-conflict + - id: end-of-file-fixer + - repo: https://github.com/hadolint/hadolint + rev: v2.12.0 + hooks: + - id: hadolint-docker + args: + - --failure-threshold + - warning + - repo: https://github.com/gitleaks/gitleaks + rev: v8.16.1 + hooks: + - id: gitleaks diff --git a/.releaserc b/.releaserc new file mode 100644 index 0000000..27c6c05 --- /dev/null +++ b/.releaserc @@ -0,0 +1,44 @@ +{ + "branches": [ + "main", + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/github", + { + "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", + "labels": false, + "releasedLabels": false + } + ], + [ + "@semantic-release/changelog", + { + "changelogFile": "CHANGELOG.md", + "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file." + } + ], + [ + "@semantic-release/git", + { + "assets": [ + "CHANGELOG.md" + ], + "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ] + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c328e1d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing + +## Local setup for pre-commit hooks + +- [pre-commit](https://pre-commit.com/#install) + +To test hooks before commiting, you can run `pre-commit run -a`. + +## Commit guidelines + +To generate changelog, Pull Requests and Commits must have semantic and must follow conventional specs below: + +- `feat()!:` for breaking changes (major release) +- `feat():` for new features (minor release) +- `fix():` for bug fixes (patch release) +- `docs():` for documentation and examples (no release) +- `refactor():` for code refactoring (no release) +- `test():` for tests (no release) +- `ci():` for CI purpose (no release) +- `chore():` for chores stuff (no release) + +The `chore` prefix skipped during changelog generation. It can be used for `chore: update changelog` commit message by +example. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b7eb09c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +ARG ALPINE_VERSION="3.19" + +ARG BASH_VERSION="5.2.26-r0" + +FROM alpine:${ALPINE_VERSION} + +WORKDIR /scripts + +RUN apk update --no-cache; \ + apk upgrade --no-cache; \ + apk add --no-cache bash=${BASH_VERSION}; \ + rm -rf /var/cache/apk/* + +ENV LOG_LEVEL "INFO" +ENV LOG_TIMESTAMPED "true" +ENV DEBUG_MODE "false" + +COPY scripts/utils.sh . +COPY scripts/script.sh . + +ENTRYPOINT ["/scripts/script.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..8979e59 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# actions-template + +Template repo for github actions diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..f55c3c9 --- /dev/null +++ b/action.yml @@ -0,0 +1,39 @@ +name: Some action # TODO(user): Replace this with your action name +branding: + icon: arrow-right-circle + color: gray-dark +description: | # TODO(user): replace this with your action description + This action does something + +inputs: + debug-mode: + description: Set to true for verbose execution when debugging + required: false + default: 'false' + log-level: + description: The log level to use for the execution + required: false + default: 'info' + log-timestamped: + description: Set to true in order to enable timestamps on log messages + required: false + default: 'true' + # TODO(user): Specify your inputs here + input-name: + description: Some input description + required: true + +# TODO(user): Define your outputs here +outputs: + some-output: + description: 'Some output description' + +runs: + using: 'docker' + image: Dockerfile + env: + DEBUG_MODE: ${{ inputs.debug-mode }} + LOG_LEVEL: ${{ inputs.log-level }} + LOG_TIMESTAMPED: ${{ inputs.log-timestamped }} + # TODO(user): Define your environment variables here + SOME_INPUT: ${{ inputs.input-name }} diff --git a/scripts/script.sh b/scripts/script.sh new file mode 100755 index 0000000..068071c --- /dev/null +++ b/scripts/script.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +. "$(dirname "$0")/utils.sh" + +# Your action logic goes here + +# TODO(user): Use this helper function to check if a required env variable is set or not +check_env_var "SOME_INPUT" + +# TODO(user): Use the `check_bool` helper function to check for bool values +if [[ "$(check_bool "true")" ]]; then + # TODO(user): Use the `log_out` helper function to log messages + log_out "hello world" "INFO" + # The following are some handy logging functions + log_debug "This is a DEBUG log" + log_info "This is a INFO log" + log_warning "This is a WARNING log" + log_error "This is a ERROR log" + log_fatal "This is a FATAL log" # <- This one exists with an error + log_fatal "This is a FATAL log with custom exit code" 5 # <- This one exists with an error + log_out "This is a custom log message that exits with code 10" "FATAL" 10 +fi + +# TODO(user): This is how to output something to GH actions +echo "some-output=HelloThereGeneralKenobi" >>"${GITHUB_OUTPUT}" diff --git a/scripts/utils.sh b/scripts/utils.sh new file mode 100755 index 0000000..71abaf7 --- /dev/null +++ b/scripts/utils.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash + +######################################################################################################## +##### This script hosts common functions and utils for all the scripts +##### Common Environment Variables: Environment variables to configure for all scripts are +##### LOG_LEVEL: +##### description: For setting log level during the execution +##### type: enum ["DEBUG" "INFO" "WARNING" "ERROR" "FATAL"] +##### default: INFO +##### LOG_TIMESTAMPED: +##### description: For adding timestamps to log messages +##### type: bool +##### default: false +##### DEBUG_MODE: +##### description: For setting debug output +##### type: bool +##### default: false +######################################################################################################## + +# Defining available log levels. +case "$(echo "${LOG_LEVEL:-INFO}" | tr '[:lower:]' '[:upper:]')" in +"DEBUG") + availableLogLevels=("DEBUG" "INFO" "WARNING" "ERROR" "FATAL") + ;; +"INFO") + availableLogLevels=("INFO" "WARNING" "ERROR" "FATAL") + ;; +"WARNING") + availableLogLevels=("WARNING" "ERROR" "FATAL") + ;; +"ERROR" | "FATAL") + availableLogLevels=("ERROR" "FATAL") + ;; +*) + availableLogLevels=("INFO" "WARNING" "ERROR" "FATAL") + echo -e "[Warning] unrecognized log level variable '${LOG_LEVEL}'." \ + "\n\tDefaulting to 'INFO' level" \ + "\n\tAvailable log levels are: 'DEBUG' 'INFO' 'WARNING' 'ERROR' 'FATAL'." + ;; +esac + +# The `log_out` function logs out a message with timestamp and exists with a specific code if is set. +# Parameters: +# [REQUIRED] ${1} the log message +# [OPTIONAL] ${2} the log level of the message. Defaults to 'INFO' +# [OPTIONAL] ${3} exit code. Default empty. +function log_out() { + _message="${1}" + _level="${2:-INFO}" + _exitCode="${3}" + + for _lvl in "${availableLogLevels[@]}"; do + [[ "${_lvl,,}" == "${_level,,}" && "$(check_bool "${LOG_TIMESTAMPED}")" ]] && echo -e "[$(date +"%FT%T%Z") | ${_level^^}] ${_message}" + [[ "${_lvl,,}" == "${_level,,}" && -z "$(check_bool "${LOG_TIMESTAMPED}")" ]] && echo -e "[${_level^^}] ${_message}" + done + + [[ -z "${_exitCode}" ]] || exit "${_exitCode}" +} + +function log_debug() { + _message="${1}" + log_out "${_message}" "DEBUG" +} +function log_info() { + _message="${1}" + log_out "${_message}" "INFO" +} +function log_warning() { + _message="${1}" + log_out "${_message}" "WARNING" +} +function log_error() { + _message="${1}" + _exitCode="${2}" + log_out "${_message}" "ERROR" "${_exitCode}" +} +function log_fatal() { + _message="${1}" + _exitCode="${2:-1}" + log_out "${_message}" "FATAL" "${_exitCode}" +} + +# The `check_bool` function checks if a value is equal to: 'true', 'yes', 'y', 'enable', or 'enabled'. +# If the value is one of the above, it returns 'true' otherwise, returns empty. +# Parameters: +# [REQUIRED] ${1} the value to check +function check_bool() { + _input="${1}" + if [[ "${_input,,}" =~ ^(true)|(y(es)?)|(enable(d)?)$ ]]; then + echo "true" + fi +} + +# The `check_env_var` function checks if an environment variable is required or not +# by its name which is passed as the first parameter. Depending on the value fo the +# second parameter, either exists with an error if the variable is not set, or logs +# out a warning staging that it is missing. +# Parameters: +# [REQUIRED] ${1} environment variable name +# [OPTIONAL] ${2} bool flag stating that the variable is required. Defaults to 'true' +function check_env_var() { + _envVar="${1}" + _required="${2:-true}" + + [[ (-z "${!_envVar}" || "${!_envVar,,}" == "null") && "$(check_bool "${_required}")" ]] && log_out "The required environment variable '${_envVar}' is missing. Aborting." "FATAL" 1 + [[ (-z "${!_envVar}" || "${!_envVar,,}" == "null") && -z "$(check_bool "${_required}")" ]] && log_out "The environment variable '${_envVar}' is missing." "WARNING" +} + +if [[ "$(check_bool "${DEBUG_MODE}")" ]]; then + set -x +fi