├── .github ├── dependabot.yml └── workflows │ ├── check-goreleaser-config.yaml │ ├── format-go.yaml │ ├── lint-github-actions.yaml │ ├── lint-go.yaml │ ├── lint-markdown.yaml │ ├── lint-yaml.yaml │ ├── release-binary.yaml │ └── test-go.yaml ├── .gitignore ├── .goreleaser.yaml ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md └── src └── gabo ├── .gitignore ├── Makefile ├── cmd └── gabo │ ├── main.go │ ├── main_test.go │ └── version.txt ├── go.mod ├── go.sum └── internal ├── analyzer └── analyze_dir.go └── generator ├── all_options.go ├── build_android_generator.go ├── build_docker_generator.go ├── build_npm_generator.go ├── build_yarn_generator.go ├── data ├── build-android-incomplete.yaml ├── build-docker-incomplete.yaml ├── build-npm-incomplete.yaml ├── build-yarn-incomplete.yaml ├── check-goreleaser-config.yaml ├── compress-images.yaml ├── format-go.yaml ├── format-python.yaml ├── lint-android.yaml ├── lint-docker.yaml ├── lint-github-actions.yaml ├── lint-go-incomplete.yaml ├── lint-html.yaml ├── lint-markdown.yaml ├── lint-python.yaml ├── lint-shell-script.yaml ├── lint-solidity.yaml ├── lint-yaml.yaml ├── translate-android.yaml ├── validate-openapi-schema.incomplete.yaml └── validate-render-blueprint.yaml ├── generator.go ├── golang_lint_generator.go ├── goreleaser_config_checker_generator.go ├── openapi_schema_validator_generator.go ├── write_utils.go └── yaml_embed_list.go /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gomod" # See documentation for possible values 9 | directory: "/src/gabo" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "github-actions" # See documentation for possible values 13 | directory: "/" # Location of package manifests 14 | schedule: 15 | interval: "weekly" 16 | -------------------------------------------------------------------------------- /.github/workflows/check-goreleaser-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Check Go Releaser config 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - ".goreleaser.yaml" 9 | - ".github/workflows/check-goreleaser-config.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - ".goreleaser.yaml" 14 | - ".github/workflows/check-goreleaser-config.yaml" 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.ref }} 18 | cancel-in-progress: true 19 | 20 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 21 | permissions: 22 | contents: read 23 | 24 | jobs: 25 | 26 | checkGoReleaserConfig: 27 | runs-on: ubuntu-latest 28 | timeout-minutes: 15 29 | 30 | steps: 31 | - name: checkout 32 | uses: actions/checkout@v4 33 | with: 34 | persist-credentials: false 35 | 36 | - uses: actions/setup-go@v5 37 | with: 38 | go-version-file: "src/gabo/go.mod" 39 | cache: false # Disable caching to avoid cache poisoning 40 | 41 | - name: Install Go Releaser 42 | uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 43 | with: 44 | distribution: goreleaser 45 | version: latest 46 | install-only: true 47 | 48 | - name: Check Go Releaser config is valid 49 | run: goreleaser check --config .goreleaser.yaml 50 | 51 | - name: Build (not release) binaries with Go Releaser 52 | run: goreleaser build --snapshot --clean 53 | -------------------------------------------------------------------------------- /.github/workflows/format-go.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Validate Go code formatting 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.go" 9 | - ".github/workflows/format-go.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**.go" 14 | - ".github/workflows/format-go.yaml" 15 | 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | 27 | validateCodeFormatGo: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: checkout 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | - name: Set up Go 38 | uses: actions/setup-go@v5 39 | with: 40 | go-version-file: "src/gabo/go.mod" 41 | 42 | # Ref: https://github.com/actions/cache/blob/main/examples.md#go---modules 43 | # Warning: This is Linux specific 44 | - uses: actions/cache@v4 45 | with: 46 | path: | 47 | ~/.cache/go-build 48 | ~/go/pkg/mod 49 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 50 | restore-keys: | 51 | ${{ runner.os }}-go- 52 | 53 | - name: Validate code formatting 54 | run: | 55 | gofmt -l . 56 | test -z "$(gofmt -l .)" 57 | -------------------------------------------------------------------------------- /.github/workflows/lint-github-actions.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintGitHubActions 4 | name: Lint GitHub Actions 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [master, main] 9 | paths: 10 | - ".github/workflows/**.yml" 11 | - ".github/workflows/**.yaml" 12 | - "src/gabo/internal/generator/data/*.yml" 13 | - "src/gabo/internal/generator/data/*.yaml" 14 | pull_request: 15 | branches: [master, main] 16 | paths: 17 | - ".github/workflows/**.yml" 18 | - ".github/workflows/**.yaml" 19 | - "src/gabo/internal/generator/data/*.yml" 20 | - "src/gabo/internal/generator/data/*.yaml" 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.ref }} 24 | cancel-in-progress: true 25 | 26 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 27 | permissions: 28 | contents: read 29 | 30 | jobs: 31 | lintGitHubActionsWithActionLint: 32 | runs-on: ubuntu-latest 33 | timeout-minutes: 15 34 | 35 | steps: 36 | - name: Checkout repository 37 | uses: actions/checkout@v4 38 | with: 39 | persist-credentials: false 40 | sparse-checkout: | 41 | .github/workflows 42 | src/gabo/internal/generator/data 43 | sparse-checkout-cone-mode: false 44 | 45 | - name: Lint GitHub Actions 46 | uses: reviewdog/action-actionlint@a5524e1c19e62881d79c1f1b9b6f09f16356e281 # v1.65.2 47 | 48 | - name: Check GitHub Actions with 'actionlint' 49 | # Ref: https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions 50 | # shellcheck is too noisy and disabled 51 | run: | 52 | find .github/workflows -type f -print0 | xargs -0 -n1 -I % sh -c 'docker run --init --rm --network none -v "$PWD":/work:ro rhysd/actionlint:latest -shellcheck= /work/%' 53 | find src/gabo/internal/generator/data -type f -print0 | xargs -0 -n1 -I % sh -c 'docker run --init --rm --network none -v "$PWD":/work:ro rhysd/actionlint:latest -shellcheck= /work/%' 54 | shell: bash 55 | 56 | 57 | lintGitHubActionsForSecurity: 58 | runs-on: ubuntu-latest 59 | timeout-minutes: 15 60 | 61 | permissions: 62 | security-events: write 63 | contents: read 64 | actions: read 65 | 66 | steps: 67 | - name: Checkout repository 68 | uses: actions/checkout@v4 69 | with: 70 | persist-credentials: false 71 | sparse-checkout: | 72 | .github/workflows 73 | src/gabo/internal/generator/data 74 | sparse-checkout-cone-mode: false 75 | 76 | - name: Run zizmor on GitHub Actions 77 | run: docker run --rm --network none -v "$PWD":/work:ro ghcr.io/woodruffw/zizmor:latest --offline /work/.github/workflows 78 | 79 | - name: Run zizmor on gabo's internal generator data 80 | run: find src/gabo/internal/generator/data -type f -print0 | xargs -0 -n1 -I % sh -c 'docker run --rm --network none -v "$PWD":/work:ro ghcr.io/woodruffw/zizmor:latest --offline /work/%' 81 | -------------------------------------------------------------------------------- /.github/workflows/lint-go.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Go 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.go" 9 | - ".github/workflows/lint-go.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**.go" 14 | - ".github/workflows/lint-go.yaml" 15 | 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | 27 | lintGo: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: checkout 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | - name: Set up Go 38 | uses: actions/setup-go@v5 39 | with: 40 | go-version-file: "src/gabo/go.mod" 41 | 42 | # Ref: https://github.com/actions/cache/blob/main/examples.md#go---modules 43 | # Warning: This is Linux specific 44 | - uses: actions/cache@v4 45 | with: 46 | path: | 47 | ~/.cache/go-build 48 | ~/go/pkg/mod 49 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 50 | restore-keys: | 51 | ${{ runner.os }}-go- 52 | 53 | - name: Run golangci-lint 54 | uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 55 | with: 56 | # We use cache provided by "actions/setup-go@v5" 57 | skip-cache: true 58 | # Directory containing go.mod file 59 | working-directory: src/gabo 60 | 61 | - name: Run `govulncheck` 62 | working-directory: src/gabo 63 | run: go run golang.org/x/vuln/cmd/govulncheck@latest ./... 64 | -------------------------------------------------------------------------------- /.github/workflows/lint-markdown.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintMarkdown 4 | name: Lint Markdown 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [master, main] 9 | paths: 10 | - '**.md' 11 | - '.github/workflows/lint-markdown.yaml' 12 | pull_request: 13 | branches: [master, main] 14 | paths: 15 | - '**.md' 16 | - '.github/workflows/lint-markdown.yaml' 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | lintMarkdown: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: Checkout code 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | - name: Set up Ruby 38 | # See https://github.com/ruby/setup-ruby#versioning 39 | uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 40 | with: 41 | ruby-version: 3.0 42 | 43 | - name: Install dependencies 44 | run: gem install mdl 45 | 46 | - name: Run tests 47 | # Rule list: https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md 48 | # Don't check for line length (MD013) 49 | # Don't care about list ordering (MD029) 50 | run: mdl --git-recurse --rules ~MD013,~MD029 . 51 | -------------------------------------------------------------------------------- /.github/workflows/lint-yaml.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintYaml 4 | name: Lint YAML 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [master, main] 9 | paths: 10 | - "**.yml" 11 | - "**.yaml" 12 | - ".github/workflows/**.yml" 13 | - ".github/workflows/**.yaml" 14 | pull_request: 15 | branches: [master, main] 16 | paths: 17 | - "**.yml" 18 | - "**.yaml" 19 | - ".github/workflows/**.yml" 20 | - ".github/workflows/**.yaml" 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.ref }} 24 | cancel-in-progress: true 25 | 26 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 27 | permissions: 28 | contents: read 29 | 30 | jobs: 31 | lintYaml: 32 | runs-on: ubuntu-latest 33 | timeout-minutes: 15 34 | 35 | steps: 36 | - name: Checkout repository 37 | uses: actions/checkout@v4 38 | with: 39 | persist-credentials: false 40 | 41 | - name: Check YAML files with linter 42 | uses: ibiqlik/action-yamllint@2576378a8e339169678f9939646ee3ee325e845c # v3.1.1 43 | with: 44 | # All files under base dir 45 | file_or_dir: "." 46 | config_data: | 47 | extends: default 48 | yaml-files: 49 | - '*.yaml' 50 | - '*.yml' 51 | rules: 52 | document-start: 53 | level: warning 54 | line-length: 55 | level: warning 56 | new-line-at-end-of-file: 57 | level: warning 58 | trailing-spaces: 59 | level: warning 60 | -------------------------------------------------------------------------------- /.github/workflows/release-binary.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Create release 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: ["main", "master"] 7 | # Release whenever this file changes 8 | paths: 9 | - "src/gabo/cmd/gabo/version.txt" 10 | workflow_dispatch: 11 | 12 | jobs: 13 | 14 | generateTag: 15 | 16 | name: "Auto-generate Git tag whenever version.txt changes" 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 15 19 | permissions: 20 | contents: write 21 | 22 | steps: 23 | 24 | - name: Checkout code 25 | uses: actions/checkout@v4 26 | with: 27 | persist-credentials: true # Required to allow git fetch 28 | fetch-depth: 0 29 | 30 | - name: Fetch git tags 31 | run: git fetch --force --tags 32 | 33 | - name: Setup Go 34 | uses: actions/setup-go@v5 35 | with: 36 | go-version-file: "src/gabo/go.mod" 37 | cache: false # Disable caching to avoid cache poisoning 38 | 39 | - name: Read gabo version name 40 | id: read-version 41 | run: | 42 | echo "version=$(cat src/gabo/cmd/gabo/version.txt)" > "$GITHUB_OUTPUT" 43 | 44 | - name: Create new tag 45 | id: tag_version 46 | uses: mathieudutour/github-tag-action@a22cf08638b34d5badda920f9daf6e72c477b07b # v6.2 47 | with: 48 | custom_tag: ${{ steps.read-version.outputs.version }} 49 | tag_prefix: "" # To prevent extra "v" in the prefix 50 | github_token: ${{ secrets.GITHUB_TOKEN }} 51 | 52 | releaseBinary: 53 | 54 | name: "Release Go binaries with Go Releaser" 55 | runs-on: ubuntu-latest 56 | needs: generateTag 57 | timeout-minutes: 15 58 | permissions: 59 | contents: write 60 | 61 | steps: 62 | 63 | - name: Checkout code 64 | uses: actions/checkout@v4 65 | with: 66 | persist-credentials: true # Required to allow git fetch 67 | fetch-depth: 0 68 | 69 | - name: Fetch git tags 70 | run: git fetch --force --tags 71 | 72 | - uses: actions/setup-go@v5 73 | with: 74 | go-version: stable 75 | cache: false # Disable caching to avoid cache poisoning 76 | 77 | # More assembly might be required: Docker logins, GPG, etc. It all depends 78 | # on your needs. 79 | - uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 80 | with: 81 | distribution: goreleaser 82 | version: latest 83 | args: release --clean 84 | env: 85 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 86 | -------------------------------------------------------------------------------- /.github/workflows/test-go.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Test 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**/*.go" 9 | - ".github/workflows/test-go.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**/*.go" 14 | - ".github/workflows/test-go.yaml" 15 | 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | 27 | testGo: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: checkout 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | - name: Set up Go 38 | uses: actions/setup-go@v5 39 | with: 40 | go-version-file: "src/gabo/go.mod" 41 | 42 | # Ref: https://github.com/actions/cache/blob/main/examples.md#go---modules 43 | # Warning: This is Linux specific 44 | - uses: actions/cache@v4 45 | with: 46 | path: | 47 | ~/.cache/go-build 48 | ~/go/pkg/mod 49 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 50 | restore-keys: | 51 | ${{ runner.os }}-go- 52 | 53 | - name: Run test 54 | run: make test 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/18e28746b0862059dbee8694fd366a679cb812fb/Go.gitignore 2 | 3 | # Binaries for programs and plugins 4 | *.exe 5 | *.exe~ 6 | *.dll 7 | *.so 8 | *.dylib 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | .idea 17 | 18 | dist/ 19 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Ref: https://goreleaser.com 3 | version: 2 4 | before: 5 | hooks: 6 | # You may remove this if you don't use go modules. 7 | # - cd src/gabo && go mod tidy 8 | # you may remove this if you don't need go generate 9 | # - go generate ./... 10 | builds: 11 | - dir: src/gabo 12 | # Ref: https://goreleaser.com/errors/no-main/ 13 | main: ./cmd/gabo 14 | env: 15 | - CGO_ENABLED=0 16 | goos: 17 | - linux 18 | - windows 19 | - darwin 20 | binary: gabo 21 | 22 | archives: 23 | - formats: ["tar.gz"] 24 | # this name template makes the OS and Arch compatible with the results of uname. 25 | name_template: >- 26 | {{ .ProjectName }}_ 27 | {{- title .Os }}_ 28 | {{- if eq .Arch "amd64" }}x86_64 29 | {{- else if eq .Arch "386" }}i386 30 | {{- else }}{{ .Arch }}{{ end }} 31 | {{- if .Arm }}v{{ .Arm }}{{ end }} 32 | # use zip for windows archives 33 | format_overrides: 34 | - goos: windows 35 | formats: ["zip"] 36 | checksum: 37 | name_template: 'checksums.txt' 38 | snapshot: 39 | version_template: "{{ incpatch .Version }}-next" 40 | changelog: 41 | sort: asc 42 | filters: 43 | exclude: 44 | - '^docs:' 45 | - '^test:' 46 | 47 | # The lines beneath this are called `modelines`. See `:help modeline` 48 | # Feel free to remove those if you don't want/use them. 49 | # yaml-language-server: $schema=https://goreleaser.com/static/schema.json 50 | # vim: set ts=2 sw=2 tw=0 fo=cnqoj 51 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions are welcome. 2 | There are no rigid guidelines, just see `GetOptions` function in [all_options.go](src/gabo/internal/generator/all_options.go) and add a new option for a language/script that you want to target. 3 | One pull request per option is preferred. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build_debug: 2 | cd src/gabo && make build_debug 3 | 4 | build: build_debug 5 | 6 | build_prod: 7 | cd src/gabo && make build_prod 8 | 9 | # Ref: https://goreleaser.com/install/ 10 | build_release: 11 | goreleaser check && goreleaser build --snapshot --clean 12 | 13 | go_lint: 14 | cd src/gabo && make lint 15 | 16 | lint: format go_lint 17 | 18 | format: 19 | cd src/gabo && make format 20 | 21 | clean: 22 | cd src/gabo && make clean 23 | 24 | test: 25 | cd src/gabo && make test 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub Actions Boilerplate (`gabo`) 2 | 3 | [![Lint YAML](https://github.com/ashishb/gabo/actions/workflows/lint-yaml.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/lint-yaml.yaml) [![Lint Markdown](https://github.com/ashishb/gabo/actions/workflows/lint-markdown.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/lint-markdown.yaml) 4 | [![Lint GitHub Actions](https://github.com/ashishb/gabo/actions/workflows/lint-github-actions.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/lint-github-actions.yaml) 5 | [![Lint Go](https://github.com/ashishb/gabo/actions/workflows/lint-go.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/lint-go.yaml) [![Validate Go code formatting](https://github.com/ashishb/gabo/actions/workflows/format-go.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/format-go.yaml) [![Test](https://github.com/ashishb/gabo/actions/workflows/test-go.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/test-go.yaml) 6 | 7 | [![Check Go Releaser config for validity](https://github.com/ashishb/gabo/actions/workflows/check-goreleaser-config.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/check-goreleaser-config.yaml) 8 | 9 | [![Release Go binaries with Go Releaser](https://github.com/ashishb/gabo/actions/workflows/release-binary.yaml/badge.svg)](https://github.com/ashishb/gabo/actions/workflows/release-binary.yaml) [![Go report](https://img.shields.io/badge/go%20report-A+-brightgreen.svg?style=flat)](https://goreportcard.com/report/github.com/ashishb/gabo/src/gabo) 10 | 11 | **gabo** short for GitHub Actions Boilerplate is for ease-of-generation of GitHub actions boilerplate with good timeouts, path filters, and concurrency preventions. See [this blogpost](https://ashishb.net/tech/common-pitfalls-of-github-actions/) for more details on why the GitHub defaults aren't great. 12 | 13 | The actions runs only on push/pull requests against `main` and `master` branch, by default. 14 | Feel free to add more branches if you want to runs these checks when push/pull request against any other branches. 15 | 16 | - [x] Auto-generated high quality GitHub Actions 17 | - [x] Better file filters 18 | - [x] Explicit timeout 19 | - [x] Auto-cancelaion of stale executions 20 | - [x] Better caching 21 | - [x] Reduced security permissions on `GITHUB_TOKEN` 22 | 23 | ## Installation 24 | 25 | ```bash 26 | $ go install github.com/ashishb/gabo/src/gabo/cmd/gabo@latest 27 | ... 28 | ``` 29 | 30 | or via homebrew ![homebrew version](https://img.shields.io/homebrew/v/gabo) 31 | 32 | ```bash 33 | $ brew install gabo 34 | ... 35 | ``` 36 | 37 | Or run directly 38 | 39 | ```bash 40 | # --dir flag is optional and defaults to current directory 41 | go run github.com/ashishb/gabo/src/gabo/cmd/gabo@latest --dir= 42 | ``` 43 | 44 | ## Usage 45 | 46 | ```bash 47 | $ gabo --help 48 | 49 | Usage of gabo: 50 | -dir string 51 | Path to root of git directory (default ".") 52 | -for string 53 | Generate GitHub Action (options: build-android,lint-android,translate-android,compress-images,build-docker,build-npm,build-yarn,lint-docker,format-go,lint-go,check-go-releaser,lint-html,lint-markdown,validate-openapi-schema,format-python,lint-python,lint-shell-script,lint-solidity,lint-yaml,lint-github-actions,validate-render-blueprint) 54 | -force 55 | Force overwrite existing files (in generate mode) 56 | -mode string 57 | Mode to operate in: [generate analyze] (default "analyze") 58 | -verbose 59 | Enable verbose logging 60 | -version 61 | Prints version of the binary 62 | ``` 63 | 64 | ### Sample usage - analyze a repository 65 | 66 | ```bash 67 | # Analyze current directory (it should be the root of the repository) 68 | $ gabo 69 | 70 | # Analyze a different dir 71 | $ gabo --dir=~/src/repo1 72 | ``` 73 | 74 | ### Sample usage - generate code 75 | 76 | ```bash 77 | $ gabo --mode=generate --for=lint-docker 78 | Wrote file .github/workflows/lint-docker.yaml 79 | ``` 80 | 81 | ### Supported actions 82 | 83 | - [x] build-android 84 | - [x] build-docker 85 | - [x] build-npm 86 | - [x] build-yarn 87 | - [x] check-go-releaser 88 | - [x] compress-images 89 | - [x] format-go 90 | - [x] format-python 91 | - [x] lint-android 92 | - [x] lint-docker using [hadolint](https://github.com/hadolint/hadolint) 93 | - [x] lint-github-actions using [actionlint](https://github.com/rhysd/actionlint) and [zizmor](https://github.com/woodruffw/zizmor/) 94 | - [x] lint-go 95 | - [x] lint-html 96 | - [x] lint-markdown 97 | - [x] lint-python 98 | - [x] lint-shell-script 99 | - [x] lint-solidity 100 | - [x] lint-yaml 101 | - [x] translate-android 102 | - [x] validate-openapi-schema using [vacuum](https://github.com/daveshanley/vacuum) and [oasdiff](https://github.com/Tufin/oasdiff) 103 | - [x] validate-render-blueprint using [jsonschema](https://json-schema.org/) 104 | - [ ] build-rust 105 | - [ ] lint-rust 106 | -------------------------------------------------------------------------------- /src/gabo/.gitignore: -------------------------------------------------------------------------------- 1 | # Contains generated binary 2 | bin/ 3 | -------------------------------------------------------------------------------- /src/gabo/Makefile: -------------------------------------------------------------------------------- 1 | build_debug: 2 | GO111MODULE=on go build -v -o bin/${BINARY_NAME} ./cmd/gabo 3 | 4 | build_prod: 5 | # Shrink binary by removing symbol and DWARF table 6 | # Ref: https://lukeeckley.com/post/useful-go-build-flags/ 7 | GO111MODULE=on go build -v -ldflags="-s -w" -o bin/${BINARY_NAME} ./cmd/gabo 8 | 9 | go_lint: 10 | GO111MODULE=on go mod tidy 11 | GO111MODULE=on go vet ./... 12 | golangci-lint run 13 | 14 | go_format: 15 | go fmt ./... 16 | 17 | format: go_format 18 | 19 | lint: go_lint 20 | 21 | clean: 22 | GO111MODULE=on go clean --modcache 23 | rm -rf bin/* 24 | 25 | test: 26 | GO111MODULE=on go test ./... -v 27 | 28 | update_go_deps: 29 | GO111MODULE=on go get -t -u ./... 30 | 31 | -------------------------------------------------------------------------------- /src/gabo/cmd/gabo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "embed" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | 11 | "github.com/ashishb/gabo/src/gabo/internal/analyzer" 12 | "github.com/ashishb/gabo/src/gabo/internal/generator" 13 | "github.com/rs/zerolog" 14 | "github.com/rs/zerolog/log" 15 | ) 16 | 17 | const ( 18 | _modeAnalyze = "analyze" 19 | _modeGenerate = "generate" 20 | ) 21 | 22 | var ( 23 | _verbose = flag.Bool("verbose", false, "Enable verbose logging") 24 | 25 | _validModes = []string{_modeGenerate, _modeAnalyze} 26 | _mode = flag.String("mode", _modeAnalyze, 27 | fmt.Sprintf("Mode to operate in: %s", _validModes)) 28 | _gitDir = flag.String("dir", ".", "Path to root of git directory") 29 | 30 | _options = flag.String("for", "", fmt.Sprintf("Generate GitHub Action (options: %s)", 31 | strings.Join(generator.GetOptionFlags(), ","))) 32 | _force = flag.Bool("force", false, 33 | fmt.Sprintf("Force overwrite existing files (in %s mode)", _modeGenerate)) 34 | _version = flag.Bool("version", false, "Prints version of the binary") 35 | ) 36 | 37 | //go:embed version.txt 38 | var _versionCode string 39 | 40 | func main() { 41 | flag.Parse() 42 | originalUsage := flag.Usage 43 | flag.Usage = func() { 44 | fmt.Printf("Generates GitHub Actions boilerplate\n") 45 | originalUsage() 46 | } 47 | log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) 48 | zerolog.SetGlobalLevel(zerolog.DebugLevel) 49 | if *_verbose { 50 | zerolog.SetGlobalLevel(zerolog.TraceLevel) 51 | } 52 | err := validateFlags() 53 | if err != nil { 54 | log.Fatal().Msgf("%v", err.Error()) 55 | } 56 | 57 | if *_version { 58 | fmt.Printf("gabo %s by Ashish Bhatia\nhttps://github.com/ashishb/gabo\n\n", 59 | strings.TrimSpace(_versionCode)) 60 | flag.Usage() 61 | return 62 | } 63 | err = validateGitDir() 64 | if err != nil { 65 | log.Fatal().Msgf("%v", err.Error()) 66 | } 67 | switch *_mode { 68 | case _modeAnalyze: 69 | log.Info().Msgf("Analyzing dir '%s'", *_gitDir) 70 | err := analyzer.Analyze(*_gitDir) 71 | if err != nil { 72 | log.Fatal().Msgf("Failed to analyze: %s", err.Error()) 73 | } 74 | case _modeGenerate: 75 | err := generator.NewGenerator(*_gitDir, *_force).Generate(strings.Split(*_options, ",")) 76 | if err != nil { 77 | log.Fatal().Err(err).Msgf("Failed to generate") 78 | } 79 | } 80 | } 81 | 82 | // validateFlags validates flags 83 | // This will normalize values of certain flags like _gitDir as well 84 | func validateFlags() error { 85 | if *_mode != _modeAnalyze && *_mode != _modeGenerate && !*_version { 86 | return fmt.Errorf("invalid mode: %s, valid values are %s", 87 | *_mode, _validModes) 88 | } 89 | if *_force && *_mode != _modeGenerate { 90 | return fmt.Errorf("force overwrite is only supported in %s mode", _modeGenerate) 91 | } 92 | if *_mode == _modeGenerate { 93 | if _options == nil { 94 | return fmt.Errorf("'for' not provided in in %s mode", _modeGenerate) 95 | } 96 | options := strings.Split(*_options, ",") 97 | for _, option := range options { 98 | if !generator.IsValid(option) { 99 | return fmt.Errorf("'for' is not valid, valid options are one or more of %s", 100 | strings.Join(generator.GetOptionFlags(), ",")) 101 | } 102 | } 103 | } 104 | return nil 105 | } 106 | 107 | // validateGitDir validates the provided dir is a git directory 108 | func validateGitDir() error { 109 | if len(*_gitDir) == 0 { 110 | return fmt.Errorf("dir cannot be empty") 111 | } 112 | if *_gitDir == "." { 113 | path, err := os.Getwd() 114 | if err != nil { 115 | return fmt.Errorf("unable to get current dir") 116 | } 117 | _gitDir = &path 118 | } else if strings.HasPrefix(*_gitDir, "~/") { 119 | tmp := strings.ReplaceAll(*_gitDir, "~", os.Getenv("HOME")) 120 | _gitDir = &tmp 121 | } 122 | if _, err := os.Stat(filepath.Join(*_gitDir, ".git")); os.IsNotExist(err) { 123 | return fmt.Errorf("dir exists but is not a git directory: %s", *_gitDir) 124 | } 125 | return nil 126 | } 127 | -------------------------------------------------------------------------------- /src/gabo/cmd/gabo/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "github.com/stretchr/testify/require" 6 | "os" 7 | "path/filepath" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | // A simple test that generates a docker linter for testing 14 | func TestGenerateALinter(t *testing.T) { 15 | dirPath, err := os.MkdirTemp("", "gabo-git-test") 16 | assert.NoError(t, err) 17 | t.Logf("Dir name is %s", dirPath) 18 | // Cleanup 19 | defer func() { 20 | require.NoError(t, os.RemoveAll(dirPath)) 21 | }() 22 | 23 | setFlagOrFail(t, "dir", dirPath) 24 | setFlagOrFail(t, "mode", _modeAnalyze) 25 | err = flag.Set("mode", _modeAnalyze) 26 | assert.NoError(t, err) 27 | 28 | // Expected as this dir does not have ".git" 29 | assert.Error(t, validateGitDir()) 30 | // Now make it a git dir 31 | err = os.Mkdir(filepath.Join(dirPath, ".git"), 0o755) 32 | assert.NoError(t, err) 33 | assert.NoError(t, validateGitDir()) 34 | 35 | // Now, do analyze again, verify it won't fail 36 | main() 37 | // Now, add a basic generate test for docker linting 38 | setFlagOrFail(t, "mode", _modeGenerate) 39 | setFlagOrFail(t, "for", "lint-docker") 40 | main() 41 | assert.FileExists(t, filepath.Join(dirPath, ".github/workflows/lint-docker.yaml")) 42 | } 43 | 44 | func setFlagOrFail(t *testing.T, flagName string, value string) { 45 | err := flag.Set(flagName, value) 46 | assert.NoError(t, err) 47 | } 48 | -------------------------------------------------------------------------------- /src/gabo/cmd/gabo/version.txt: -------------------------------------------------------------------------------- 1 | v1.6.0 2 | -------------------------------------------------------------------------------- /src/gabo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ashishb/gabo/src/gabo 2 | 3 | go 1.24 4 | 5 | require ( 6 | github.com/bmatcuk/doublestar/v4 v4.8.1 7 | github.com/rs/zerolog v1.34.0 8 | github.com/stretchr/testify v1.10.0 9 | ) 10 | 11 | require ( 12 | github.com/davecgh/go-spew v1.1.1 // indirect 13 | github.com/mattn/go-colorable v0.1.13 // indirect 14 | github.com/mattn/go-isatty v0.0.19 // indirect 15 | github.com/pmezard/go-difflib v1.0.0 // indirect 16 | golang.org/x/sys v0.12.0 // indirect 17 | gopkg.in/yaml.v3 v3.0.1 // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /src/gabo/go.sum: -------------------------------------------------------------------------------- 1 | github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= 2 | github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= 3 | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 4 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 7 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 8 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 9 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 10 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 11 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 12 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 13 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 15 | github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= 16 | github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= 17 | github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= 18 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 19 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 20 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 21 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 22 | golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= 23 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 24 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 25 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 26 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 27 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 28 | -------------------------------------------------------------------------------- /src/gabo/internal/analyzer/analyze_dir.go: -------------------------------------------------------------------------------- 1 | package analyzer 2 | 3 | import ( 4 | "fmt" 5 | "github.com/ashishb/gabo/src/gabo/internal/generator" 6 | "github.com/rs/zerolog/log" 7 | "io" 8 | "os" 9 | "path/filepath" 10 | "strings" 11 | ) 12 | 13 | func generateCommand(flagName string, rootDir string) string { 14 | if strings.Contains(rootDir, " ") { 15 | // escape whitespace in rootdir 16 | rootDir = fmt.Sprintf("'%s'", rootDir) 17 | } 18 | return fmt.Sprintf("%s --mode=generate --for=%s --dir=%s", os.Args[0], flagName, rootDir) 19 | } 20 | 21 | func Analyze(rootDir string) error { 22 | workflowsDir := filepath.Join(rootDir, ".github", "workflows") 23 | yamlStrings, err := getYamlData(workflowsDir) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | missingAnalyzers := make([]string, 0) 29 | for _, analyzer := range generator.GetOptions() { 30 | if !analyzer.IsApplicable(rootDir) { 31 | log.Trace().Msgf("Not applicable %s", analyzer.Name()) 32 | continue 33 | } 34 | if analyzer.IsImplemented(yamlStrings) { 35 | log.Info().Msgf("✅ %s is present", analyzer.Name()) 36 | } else { 37 | log.Warn().Msgf("❌ %s is missing, generate via \"%s\"", 38 | analyzer.Name(), generateCommand(analyzer.FlagName(), rootDir)) 39 | missingAnalyzers = append(missingAnalyzers, analyzer.FlagName()) 40 | } 41 | } 42 | if len(missingAnalyzers) == 0 { 43 | log.Info().Msg("No changes required") 44 | return nil 45 | } 46 | log.Info().Msgf("Run the following command to generate "+ 47 | "all the suggested GitHub Actions:\n%s", generateCommand( 48 | strings.Join(missingAnalyzers, ","), rootDir)) 49 | return nil 50 | } 51 | 52 | func getYamlData(dir string) ([]string, error) { 53 | // Glob pattern "*.y?(a)ml" is not supported by Go 54 | globPattern1 := filepath.Join(dir, "*.yaml") 55 | globPattern2 := filepath.Join(dir, "*.yml") 56 | log.Trace().Msgf("Glob patterns are %s and %s", globPattern1, globPattern2) 57 | matches1, err1 := filepath.Glob(globPattern1) 58 | matches2, err2 := filepath.Glob(globPattern2) 59 | if os.IsNotExist(err1) && os.IsNotExist(err2) { 60 | return nil, nil 61 | } 62 | matches := make([]string, 0) 63 | if len(matches1) > 0 { 64 | matches = append(matches, matches1...) 65 | } 66 | if len(matches2) > 0 { 67 | matches = append(matches, matches2...) 68 | } 69 | data := make([]string, 0, len(matches)) 70 | for _, filePath := range matches { 71 | file, err := os.Open(filePath) 72 | if err != nil { 73 | return nil, err 74 | } 75 | tmp, err := io.ReadAll(file) 76 | if err != nil { 77 | return nil, err 78 | } 79 | log.Trace().Msgf("File %s", filePath) 80 | data = append(data, string(tmp)) 81 | } 82 | return data, nil 83 | } 84 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/all_options.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "github.com/bmatcuk/doublestar/v4" 5 | "io/fs" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | 10 | "github.com/rs/zerolog/log" 11 | ) 12 | 13 | const ( 14 | _AndroidManifestFile = "**/AndroidManifest.xml" 15 | _dockerFile = "**/Dockerfile" 16 | _goFile = "**/*.go" 17 | _markdownFile = "**/*.md" 18 | _pythonFile = "**/*.py" 19 | ) 20 | 21 | type Option interface { 22 | // E.g. "Markdown Linter" 23 | Name() string 24 | // E.g. lint-markdown 25 | FlagName() string 26 | IsApplicable(repoDir string) bool 27 | IsImplemented(yamlData []string) bool 28 | GetYamlConfig(repoDir string) (*string, error) 29 | GetOutputFileName(repoDir string) string 30 | } 31 | 32 | func GetOptions() []Option { 33 | // _BuildGo Option = "build-go" 34 | // _TestGo Option = "test-go" 35 | // _TestPython Option = "test-python" 36 | 37 | return []Option{ 38 | _Option{ 39 | "Android Builder", "build-android", 40 | newFileMatcher(_AndroidManifestFile), 41 | newPatternMatcher("gradlew build"), 42 | newGenerator2(generateBuildAndroidYaml), "build-android.yaml", 43 | }, 44 | _Option{ 45 | "Android Linter", "lint-android", 46 | newFileMatcher(_AndroidManifestFile), 47 | newPatternMatcher("gradlew lint"), 48 | newGenerator(_lintAndroidYaml), "lint-android.yaml", 49 | }, 50 | _Option{ 51 | "Android Auto Translator", "translate-android", 52 | newFileMatcher(_AndroidManifestFile), 53 | newPatternMatcher("ashishb/android-auto-translate"), 54 | newGenerator(_translateAndroidYaml), 55 | "translate-android.yaml", 56 | }, 57 | _Option{ 58 | "Compress Images", "compress-images", 59 | newFileMatcher("**/*.jpg", "**/*.jpeg", "**/*.png", "**/*.webp"), 60 | newPatternMatcher("calibreapp/image-actions"), 61 | newGenerator(_comressImageYaml), "compress-images.yaml", 62 | }, 63 | _Option{ 64 | "Docker Builder", "build-docker", 65 | newFileMatcher(_dockerFile), 66 | newPatternMatcher("docker build ", "docker buildx"), 67 | newGenerator2(generateBuildDockerYaml), "build-docker.yaml", 68 | }, 69 | _Option{ 70 | "NPM Builder", "build-npm", newFileMatcher("**/package-lock.json"), 71 | newPatternMatcher("npm install "), 72 | newGenerator2(generateBuildNpmYaml), "build-npm.yaml", 73 | }, 74 | _Option{ 75 | "Yarn Builder", "build-yarn", newFileMatcher("**/yarn.lock"), 76 | newPatternMatcher("yarn build"), 77 | newGenerator2(generateBuildYarnYaml), "build-yarn.yaml", 78 | }, 79 | _Option{ 80 | "Docker Linter", "lint-docker", newFileMatcher(_dockerFile), 81 | newPatternMatcher("hadolint "), 82 | newGenerator(_lintDockerYaml), "lint-docker.yaml", 83 | }, 84 | 85 | _Option{ 86 | "Go Formatter", "format-go", newFileMatcher(_goFile), 87 | newPatternMatcher("gofmt -l", "go fmt", "gofumpt "), 88 | newGenerator(_formatGoYaml), "format-go.yaml", 89 | }, 90 | _Option{ 91 | "Go Linter", "lint-go", newFileMatcher(_goFile), 92 | newPatternMatcher("golangci-lint"), 93 | newGenerator2(generateGoLintYaml), "lint-go.yaml", 94 | }, 95 | _Option{ 96 | "Go Releaser Config Checker", "check-go-releaser", 97 | newFileMatcher(_goReleaserConfigFiles...), 98 | newPatternMatcher("goreleaser check "), 99 | newGenerator2(generateGoReleaserConfigCheckerYaml), "check-goreleaser-config.yaml", 100 | }, 101 | 102 | _Option{ 103 | "HTML Linter", "lint-html", newFileMatcher("**/*.html", "**/*.htm"), 104 | newPatternMatcher("htmlhint "), newGenerator(_lintHtmlYaml), 105 | "lint-html.yaml", 106 | }, 107 | 108 | _Option{ 109 | "Markdown Linter", "lint-markdown", newFileMatcher(_markdownFile), 110 | newPatternMatcher("mdl "), 111 | newGenerator(_lintMarkdownYaml), "lint-markdown.yaml", 112 | }, 113 | _Option{ 114 | "OpenAPI Schema Validator", "validate-openapi-schema", 115 | newFileMatcher(_openAPIFileList...), 116 | newPatternMatcher("mpetrunic/swagger-cli-action", "dshanley/vacuum"), 117 | newGenerator2(generateOpenAPISchemaValidator), 118 | "validate-openapi-schema.yaml", 119 | }, 120 | _Option{ 121 | "Python Formatter", "format-python", newFileMatcher(_pythonFile), 122 | newPatternMatcher("black "), 123 | newGenerator(_formatPythonYaml), "format-python.yaml", 124 | }, 125 | _Option{ 126 | "Python Linter", "lint-python", newFileMatcher(_pythonFile), 127 | newPatternMatcher("pylint ", "ruff "), 128 | newGenerator(_lintPythonYaml), "lint-python.yaml", 129 | }, 130 | _Option{ 131 | "Shell Script Linter", "lint-shell-script", newFileMatcher("**/*.sh", "**/*.bash"), 132 | newPatternMatcher("shellcheck ", "action-shellcheck"), 133 | newGenerator(_lintShellScriptYaml), "lint-shell-script.yaml", 134 | }, 135 | _Option{ 136 | "Solidity Linter", "lint-solidity", newFileMatcher("**/*.sol"), 137 | newPatternMatcher("solhint "), 138 | newGenerator(_lintSolidityYaml), "lint-solidity.yaml", 139 | }, 140 | _Option{ 141 | "YAML Linter", "lint-yaml", newFileMatcher("**/*.yml", "**/*.yaml"), 142 | newPatternMatcher("ibiqlik/action-yamllint@"), 143 | newGenerator(_lintYamlYaml), "lint-yaml.yaml", 144 | }, 145 | _Option{ 146 | "GitHub Actions Linter", "lint-github-actions", 147 | newFileMatcher(".github/workflows/*.yml", ".github/workflows/*.yaml"), 148 | newPatternMatcher( /*"actionlint",*/ "zizmor"), 149 | newGenerator(_lintGitHubActionsYaml), "lint-github-actions.yaml", 150 | }, 151 | _Option{ 152 | "Render.com blueprint Validator", "validate-render-blueprint", newFileMatcher("render.yml", "render.yaml"), 153 | newPatternMatcher("GrantBirki/json-yaml-validate"), 154 | newGenerator(_validateRenderBlueprintYaml), "validate-render-blueprint.yaml", 155 | }, 156 | } 157 | } 158 | 159 | type _FileMatcher interface { 160 | Matches(repoDir string) bool 161 | } 162 | 163 | type _FileMatcherImpl struct { 164 | patterns []string 165 | } 166 | 167 | func (f _FileMatcherImpl) Matches(rootDir string) bool { 168 | for _, pattern := range f.patterns { 169 | if hasFile(rootDir, pattern) { 170 | return true 171 | } 172 | } 173 | return false 174 | } 175 | 176 | func newFileMatcher(patterns ...string) _FileMatcher { 177 | return _FileMatcherImpl{patterns} 178 | } 179 | 180 | type _PatternMatcher interface { 181 | Matches(yamlData []string) bool 182 | } 183 | 184 | type _PatternMatcherImpl struct { 185 | patterns []string 186 | } 187 | 188 | func (f _PatternMatcherImpl) Matches(yamlData []string) bool { 189 | for _, pattern := range f.patterns { 190 | if contains(yamlData, pattern) { 191 | return true 192 | } 193 | } 194 | return false 195 | } 196 | 197 | func newPatternMatcher(patterns ...string) _PatternMatcher { 198 | return _PatternMatcherImpl{patterns} 199 | } 200 | 201 | type _Generator interface { 202 | Generate(repoDir string) (*string, error) 203 | } 204 | 205 | type _GeneratorStringImpl struct { 206 | yamlStr string 207 | } 208 | 209 | func (g _GeneratorStringImpl) Generate(_ string) (*string, error) { 210 | return &g.yamlStr, nil 211 | } 212 | 213 | type _GeneratorFuncImpl struct { 214 | f func(repoDir string) (*string, error) 215 | } 216 | 217 | func (g _GeneratorFuncImpl) Generate(repoDir string) (*string, error) { 218 | return g.f(repoDir) 219 | } 220 | 221 | func newGenerator(yamlStr string) _Generator { 222 | return _GeneratorStringImpl{yamlStr} 223 | } 224 | 225 | func newGenerator2(f func(repoDir string) (*string, error)) _Generator { 226 | return _GeneratorFuncImpl{f: f} 227 | } 228 | 229 | func GetOptionFlags() []string { 230 | result := make([]string, 0) 231 | for _, option := range GetOptions() { 232 | result = append(result, option.FlagName()) 233 | } 234 | return result 235 | } 236 | 237 | func IsValid(val string) bool { 238 | for _, option := range GetOptionFlags() { 239 | if val == option { 240 | return true 241 | } 242 | } 243 | return false 244 | } 245 | 246 | type _Option struct { 247 | name string 248 | flagName string 249 | filePatternToCheck _FileMatcher 250 | isImplementedPatternMatcher _PatternMatcher 251 | yamlConfigGenerator _Generator 252 | outputFileName string 253 | } 254 | 255 | func (o _Option) Name() string { 256 | return o.name 257 | } 258 | 259 | func (o _Option) FlagName() string { 260 | return o.flagName 261 | } 262 | 263 | func (o _Option) IsApplicable(repoDir string) bool { 264 | return o.filePatternToCheck.Matches(repoDir) 265 | } 266 | 267 | func (o _Option) IsImplemented(yamlData []string) bool { 268 | return o.isImplementedPatternMatcher.Matches(yamlData) 269 | } 270 | 271 | func (o _Option) GetYamlConfig(repoDir string) (*string, error) { 272 | return o.yamlConfigGenerator.Generate(repoDir) 273 | } 274 | 275 | func (o _Option) GetOutputFileName(repoDir string) string { 276 | return getPath(repoDir, o.outputFileName) 277 | } 278 | 279 | func getPath(rootDir string, fileName string) string { 280 | return filepath.Join(rootDir, ".github", "workflows", fileName) 281 | } 282 | 283 | // Note: Go does not support "**" glob pattern 284 | func hasFile(rootDir string, globPattern string) bool { 285 | log.Debug(). 286 | Str("rootDir", rootDir). 287 | Str("globPattern", globPattern). 288 | Msg("Glob pattern") 289 | found := false 290 | err := doublestar.GlobWalk(os.DirFS(rootDir), globPattern, func(path string, d fs.DirEntry) error { 291 | found = true 292 | log.Trace().Msgf("hasFile(%s, %s) = %s", globPattern, rootDir, path) 293 | return doublestar.SkipDir 294 | }) 295 | if err != nil { 296 | log.Error(). 297 | Err(err).Msgf("glob failed: '%s'", globPattern) 298 | } 299 | return found 300 | } 301 | 302 | func contains(yamlData []string, pattern string) bool { 303 | log.Trace().Msgf("Looking for %s", pattern) 304 | for _, data := range yamlData { 305 | if strings.Contains(data, pattern) { 306 | return true 307 | } 308 | } 309 | return false 310 | } 311 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/build_android_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import "fmt" 4 | 5 | const _buildAndroidTask = ` 6 | - name: Build with Gradle (dir %s) 7 | working-directory: "%s" 8 | run: | 9 | chmod +x gradlew 10 | ./gradlew buildDebug 11 | ` 12 | 13 | func generateBuildAndroidYaml(repoDir string) (*string, error) { 14 | dirs, err := getDirsContaining(repoDir, "gradlew") 15 | if err != nil { 16 | return nil, err 17 | } 18 | str := _buildAndroidTemplate 19 | for _, dir := range dirs { 20 | str += fmt.Sprintf(_buildAndroidTask, dir, dir) 21 | } 22 | return &str, nil 23 | } 24 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/build_docker_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import "fmt" 4 | 5 | const _buildDockerTask = ` 6 | - name: Docker build using %s/Dockerfile 7 | working-directory: "%s" 8 | run: | 9 | DOCKER_BUILDKIT=1 docker buildx build --cache-from type=gha --cache-to type=gha -t tmp1 -f Dockerfile . 10 | ` 11 | 12 | const _checkDockerWithDiveTask = ` 13 | - name: Check Docker image (%s/Dockerfile) with dive for wasted space 14 | working-directory: "%s" 15 | run: | 16 | docker run --rm \ 17 | -v /var/run/docker.sock:/var/run/docker.sock \ 18 | --env=CI=true \ 19 | --network none \ 20 | docker.io/wagoodman/dive:latest \ 21 | tmp1 22 | ` 23 | 24 | func generateBuildDockerYaml(repoDir string) (*string, error) { 25 | dirs, err := getDirsContaining(repoDir, "Dockerfile") 26 | if err != nil { 27 | return nil, err 28 | } 29 | str := _buildDockerTemplate 30 | for _, dir := range dirs { 31 | str += fmt.Sprintf(_buildDockerTask+"\n\n", dir, dir) 32 | str += fmt.Sprintf(_checkDockerWithDiveTask, dir, dir) 33 | } 34 | return &str, nil 35 | } 36 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/build_npm_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import "fmt" 4 | 5 | const _setupNodeJsTask = ` 6 | - name: "Setup Node.js for %s" 7 | uses: actions/setup-node@v4 8 | with: 9 | node-version: "latest" 10 | cache: "npm" 11 | cache-dependency-path: "%s/package-lock.json" 12 | ` 13 | 14 | const _buildNpmTask = ` 15 | - name: "Build %s using NPM" 16 | working-directory: %s 17 | run: npm install && npm run build 18 | ` 19 | 20 | func generateBuildNpmYaml(repoDir string) (*string, error) { 21 | dirs, err := getDirsContaining(repoDir, "package-lock.json") 22 | if err != nil { 23 | return nil, err 24 | } 25 | str := _buildNpmTemplate 26 | for _, dir := range dirs { 27 | str += fmt.Sprintf(_setupNodeJsTask, dir, dir) 28 | str += fmt.Sprintf(_buildNpmTask, dir, dir) 29 | } 30 | return &str, nil 31 | } 32 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/build_yarn_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import "fmt" 4 | 5 | const _setupYarnTask = ` 6 | - name: "Setup Node.js for %s" 7 | uses: actions/setup-node@v4 8 | with: 9 | node-version: "latest" 10 | cache: "yarn" 11 | cache-dependency-path: "%s/yarn.lock" 12 | ` 13 | 14 | const _buildYarnTask = ` 15 | - name: "Build %s using Yarn" 16 | working-directory: %s 17 | run: yarn && yarn build 18 | ` 19 | 20 | func generateBuildYarnYaml(repoDir string) (*string, error) { 21 | dirs, err := getDirsContaining(repoDir, "yarn.lock") 22 | if err != nil { 23 | return nil, err 24 | } 25 | str := _buildYarnTemplate 26 | for _, dir := range dirs { 27 | str += fmt.Sprintf(_setupYarnTask, dir, dir) 28 | str += fmt.Sprintf(_buildYarnTask, dir, dir) 29 | } 30 | return &str, nil 31 | } 32 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/build-android-incomplete.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build Android app 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - ".github/workflows/build-android.yaml" 9 | - "*/src/**" 10 | - "gradle/**" 11 | - "**.gradle" 12 | - "gradle.properties" 13 | - "gradlew*" 14 | - "**/gradle-wrapper.jar" 15 | pull_request: 16 | branches: [main, master] 17 | paths: 18 | - ".github/workflows/build-android.yaml" 19 | - "*/src/**" 20 | - "gradle/**" 21 | - "**.gradle" 22 | - "gradle.properties" 23 | - "gradlew*" 24 | - "**/gradle-wrapper.jar" 25 | 26 | concurrency: 27 | group: ${{ github.workflow }}-${{ github.ref }} 28 | cancel-in-progress: true 29 | 30 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 31 | permissions: 32 | contents: read 33 | 34 | jobs: 35 | 36 | # Run locally with "act -j buildAndroid" 37 | buildAndroid: 38 | 39 | runs-on: ubuntu-latest 40 | timeout-minutes: 15 41 | 42 | steps: 43 | - name: Checkout repository 44 | uses: actions/checkout@v4 45 | with: 46 | persist-credentials: false 47 | 48 | - name: Validate Gradle Wrapper is a known binary 49 | uses: gradle/actions/wrapper-validation@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 50 | 51 | - name: Set up JDK 52 | uses: actions/setup-java@v4 53 | with: 54 | java-version: "17" 55 | distribution: "zulu" 56 | 57 | - name: Use Gradle Build cache 58 | uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 59 | with: 60 | gradle-version: "current" 61 | 62 | # If you app depends on google-services.json to build then uncomment this 63 | # - name: Add mock google-services.json 64 | # run: | 65 | # curl https://raw.githubusercontent.com/firebase/quickstart-android/master/mock-google-services.json > app/google-services.json 66 | # sed -i "s/com.google.firebase.fiamquickstart//" app/google-services.json 67 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/build-docker-incomplete.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build Docker image(s) 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "Dockerfile" 9 | - ".github/workflows/build-docker.yaml" 10 | # TODO: Replace "*" with the list of all dir(s) whose 11 | # contents will go into the Dockerfile here 12 | # If you have multiple lots of docker files then it might be best to duplicate 13 | # this file and use separate path filters in every file for efficiency 14 | - "*" 15 | pull_request: 16 | branches: [main, master] 17 | paths: 18 | - "Dockerfile" 19 | - ".github/workflows/build-docker.yaml" 20 | # TODO: Replace "*" with the list of all dir(s) whose 21 | # contents will go into the Dockerfile here 22 | # If you have multiple lots of docker files then it might be best to duplicate 23 | # this file and use separate path filters in every file for efficiency 24 | - "*" 25 | 26 | concurrency: 27 | group: ${{ github.workflow }}-${{ github.ref }} 28 | cancel-in-progress: true 29 | 30 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 31 | permissions: 32 | contents: read 33 | 34 | jobs: 35 | buildDocker: 36 | runs-on: ubuntu-latest 37 | timeout-minutes: 15 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | with: 43 | persist-credentials: false 44 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/build-npm-incomplete.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build Node.js package(s) 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**/package-lock.json" 9 | - ".github/workflows/build-npm.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**/package-lock.json" 14 | - ".github/workflows/build-npm.yaml" 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.ref }} 18 | cancel-in-progress: true 19 | 20 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 21 | permissions: 22 | contents: read 23 | 24 | jobs: 25 | buildNpm: 26 | runs-on: ubuntu-latest 27 | timeout-minutes: 15 28 | 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@v4 32 | with: 33 | persist-credentials: false 34 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/build-yarn-incomplete.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build Node.js package(s) 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**/yarn.lock" 9 | - ".github/workflows/build-yarn.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**/yarn.lock" 14 | - ".github/workflows/build-yarn.yaml" 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.ref }} 18 | cancel-in-progress: true 19 | 20 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 21 | permissions: 22 | contents: read 23 | 24 | jobs: 25 | buildYarn: 26 | runs-on: ubuntu-latest 27 | timeout-minutes: 15 28 | 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@v4 32 | with: 33 | persist-credentials: false 34 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/check-goreleaser-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Check Go Releaser config 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - ".goreleaser.yaml" 9 | - ".goreleaser.yml" 10 | - "goreleaser.yaml" 11 | - "goreleaser.yml" 12 | - ".github/workflows/check-goreleaser-config.yaml" 13 | pull_request: 14 | branches: [main, master] 15 | paths: 16 | - ".goreleaser.yaml" 17 | - ".goreleaser.yml" 18 | - "goreleaser.yaml" 19 | - "goreleaser.yml" 20 | - ".github/workflows/check-goreleaser-config.yaml" 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.ref }} 24 | cancel-in-progress: true 25 | 26 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 27 | permissions: 28 | contents: read 29 | 30 | jobs: 31 | 32 | checkGoReleaserConfig: 33 | runs-on: ubuntu-latest 34 | timeout-minutes: 15 35 | 36 | strategy: 37 | matrix: 38 | # Without quotes, 1.20 becomes 1.2! 39 | go-version: ["1.23"] 40 | steps: 41 | - name: checkout 42 | uses: actions/checkout@v4 43 | with: 44 | persist-credentials: false 45 | 46 | - uses: actions/setup-go@v5 47 | with: 48 | go-version: ${{ matrix.go-version }} 49 | cache: false # Disable caching to avoid cache poisoning 50 | cache-dependency-path: src/gabo/go.sum 51 | 52 | - name: Install Go Releaser 53 | uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 54 | with: 55 | distribution: goreleaser 56 | version: latest 57 | install-only: true 58 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/compress-images.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Compress Images 3 | 4 | on: # yamllint disable-line rule:truthy 5 | workflow_dispatch: 6 | push: 7 | branches: ["master", "main"] 8 | # Run Image Actions when JPG, JPEG, PNG or WebP files are added or changed. 9 | # See https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#onpushpull_requestpaths for reference. 10 | paths: 11 | - ".github/workflows/compress-images.yaml" 12 | - "**.jpg" 13 | - "**.jpeg" 14 | - "**.png" 15 | - "**.webp" 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | compressImages: 23 | 24 | name: Compress Images using Calibre 25 | runs-on: ubuntu-latest 26 | permissions: 27 | contents: write 28 | pull-requests: write 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: Checkout Repo 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | - name: Compress Images 38 | id: calibre 39 | uses: calibreapp/image-actions@82caf2e46a1950e602c8440fde4730ec1da6fef4 # main 40 | with: 41 | # The `GITHUB_TOKEN` is automatically generated by GitHub and scoped only to the repository that is currently running the action. By default, the action can’t update Pull Requests initiated from forked repositories. 42 | # See https://docs.github.com/en/actions/reference/authentication-in-a-workflow and https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions 43 | githubToken: ${{ secrets.GITHUB_TOKEN }} 44 | compressOnly: true 45 | # Add ignore paths via `ignorePaths` here 46 | - name: Create New Pull Request If Needed 47 | if: steps.calibre.outputs.markdown != '' 48 | uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 49 | with: 50 | title: "Compressed Images via Calibre" 51 | branch-suffix: timestamp 52 | commit-message: "Compressed Images" 53 | body: ${{ steps.calibre.outputs.markdown }} 54 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/format-go.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Validate Go code formatting 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.go" 9 | - ".github/workflows/format-go.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**.go" 14 | - ".github/workflows/format-go.yaml" 15 | 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | 27 | validateCodeFormatGo: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | strategy: 32 | matrix: 33 | # Without quotes, 1.20 becomes 1.2! 34 | go-version: ["1.23"] 35 | steps: 36 | - name: checkout 37 | uses: actions/checkout@v4 38 | with: 39 | persist-credentials: false 40 | 41 | - name: Set up Go ${{ matrix.go-version }} 42 | uses: actions/setup-go@v5 43 | with: 44 | go-version: ${{ matrix.go-version }} 45 | 46 | # Ref: https://github.com/actions/cache/blob/main/examples.md#go---modules 47 | # Warning: This is Linux specific 48 | - uses: actions/cache@v4 49 | with: 50 | path: | 51 | ~/.cache/go-build 52 | ~/go/pkg/mod 53 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 54 | restore-keys: | 55 | ${{ runner.os }}-go- 56 | 57 | - name: Validate code formatting 58 | run: | 59 | gofmt -l . 60 | test -z $(gofmt -l .) 61 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/format-python.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Check Python code formatting 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.py" 9 | - ".github/workflows/format-python.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**.py" 14 | - ".github/workflows/format-python.yaml" 15 | 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | formatPython: 27 | runs-on: ubuntu-latest 28 | timeout-minutes: 15 29 | strategy: 30 | matrix: 31 | python-version: ["3.12"] 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v4 35 | with: 36 | persist-credentials: false 37 | 38 | - name: Set up Python ${{ matrix.python-version }} 39 | uses: actions/setup-python@v5 40 | with: 41 | python-version: ${{ matrix.python-version }} 42 | # Options are pip, pipenv, or poetry 43 | cache: "pip" 44 | cache-dependency-path: '**/requirements.txt' 45 | 46 | - name: Install black 47 | run: | 48 | pip install black 49 | 50 | - name: Check with black formatter 51 | run: | 52 | black . --check --diff 53 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-android.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Android 3 | 4 | on: # yamllint disable-line rule:truthy 5 | pull_request: 6 | branches: [main, master] 7 | paths: 8 | - ".github/workflows/lint-android.yaml" 9 | # TODO: Make this more narrow in case of a monorepo 10 | - "**.java" 11 | - "**.kt" 12 | - "**.gradle" 13 | - "**/gradle/**" 14 | - "gradle.properties" 15 | - "gradlew*" 16 | - "**/gradle-wrapper.jar" 17 | push: 18 | branches: [main, master] 19 | paths: 20 | - ".github/workflows/lint-android.yaml" 21 | # TODO: Make this more narrow in case of a monorepo 22 | - "**.java" 23 | - "**.kt" 24 | - "**.gradle" 25 | - "**/gradle/**" 26 | - "gradle.properties" 27 | - "gradlew*" 28 | - "**/gradle-wrapper.jar" 29 | 30 | concurrency: 31 | group: ${{ github.workflow }}-${{ github.ref }} 32 | cancel-in-progress: true 33 | 34 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 35 | permissions: 36 | contents: read 37 | 38 | jobs: 39 | 40 | lintAndroid: 41 | runs-on: ubuntu-latest 42 | timeout-minutes: 15 43 | 44 | steps: 45 | - name: Checkout repository 46 | uses: actions/checkout@v4 47 | with: 48 | persist-credentials: false 49 | 50 | - name: Set up JDK 51 | uses: actions/setup-java@v4 52 | with: 53 | distribution: "zulu" 54 | java-version: "17" 55 | 56 | - name: Use Gradle Build cache 57 | uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 58 | with: 59 | gradle-version: "current" 60 | 61 | - name: Validate Gradle Wrapper is a known binary 62 | uses: gradle/actions/wrapper-validation@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 63 | 64 | # # Required by apps that depend on Firebase 65 | # - name: Add mock google-services.json 66 | # run: | 67 | # curl https://raw.githubusercontent.com/firebase/quickstart-android/master/mock-google-services.json > app/google-services.json 68 | # sed -i "s/com.google.firebase.fiamquickstart/{your.app.id}/" app/google-services.json 69 | 70 | - name: Run Gradle Lint 71 | run: ./gradlew lint 72 | 73 | - uses: yutailang0119/action-android-lint@8345a8dece583030445b0b5f9611209431d601c4 # v5.0.0 74 | with: 75 | report-path: "**/build/reports/*.xml" # Support glob patterns by https://www.npmjs.com/package/@actions/glob 76 | continue-on-error: false # If annotations contain error of severity, action-android-lint exit 1. 77 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-docker.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Dockerfiles 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**/Dockerfile" 9 | - ".github/workflows/lint-docker.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**/Dockerfile" 14 | - ".github/workflows/lint-docker.yaml" 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.ref }} 18 | cancel-in-progress: true 19 | 20 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 21 | permissions: 22 | contents: read 23 | 24 | jobs: 25 | # Run this locally with act - https://github.com/nektos/act 26 | # act -j lintDocker 27 | lintDocker: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | # To lint multiple docker files 38 | # Ref: https://github.com/hadolint/hadolint-action/issues/54#issuecomment-1130157411 39 | - name: Install hadolint 40 | run: | 41 | docker pull hadolint/hadolint:latest 42 | container_id=$(docker create hadolint/hadolint) 43 | docker cp $container_id:/bin/hadolint . 44 | 45 | - name: Run hadolint 46 | run: > 47 | ./hadolint 48 | --ignore DL3007 49 | --ignore DL3008 50 | --ignore DL3013 51 | --ignore DL3018 52 | $(find . -iname Dockerfile) 53 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-github-actions.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintGitHubActions 4 | name: Lint GitHub Actions 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [master, main] 9 | paths: 10 | - ".github/workflows/**.yml" 11 | - ".github/workflows/**.yaml" 12 | pull_request: 13 | branches: [master, main] 14 | paths: 15 | - ".github/workflows/**.yml" 16 | - ".github/workflows/**.yaml" 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | lintGitHubActionsWithActionLint: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | sparse-checkout: | 37 | .github/workflows 38 | sparse-checkout-cone-mode: false 39 | 40 | - name: Lint GitHub Actions 41 | uses: reviewdog/action-actionlint@a5524e1c19e62881d79c1f1b9b6f09f16356e281 # v1.65.2 42 | 43 | - name: Check GitHub Actions with 'actionlint' 44 | # Ref: https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions 45 | # shellcheck is too noisy and disabled 46 | run: | 47 | bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 48 | ./actionlint -color -shellcheck= 49 | shell: bash 50 | 51 | 52 | lintGitHubActionsForSecurity: 53 | runs-on: ubuntu-latest 54 | timeout-minutes: 15 55 | 56 | permissions: 57 | security-events: write 58 | contents: read 59 | actions: read 60 | 61 | steps: 62 | - name: Checkout repository 63 | uses: actions/checkout@v4 64 | with: 65 | persist-credentials: false 66 | sparse-checkout: | 67 | .github/workflows 68 | sparse-checkout-cone-mode: false 69 | 70 | - name: Run zizmor on GitHub Actions 71 | run: docker run --rm --network none -v "$PWD":/work:ro ghcr.io/woodruffw/zizmor:latest --offline /work/.github/workflows 72 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-go-incomplete.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Go 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.go" 9 | - ".github/workflows/lint-go.yaml" 10 | pull_request: 11 | branches: [main, master] 12 | paths: 13 | - "**.go" 14 | - ".github/workflows/lint-go.yaml" 15 | 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | 27 | # Run it locally with https://github.com/nektos/act 28 | # act -j lintGo 29 | lintGo: 30 | runs-on: ubuntu-latest 31 | timeout-minutes: 15 32 | 33 | strategy: 34 | matrix: 35 | # Without quotes, 1.20 becomes 1.2! 36 | go-version: ["1.23"] 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v4 40 | with: 41 | persist-credentials: false 42 | 43 | - name: Set up Go ${{ matrix.go-version }} 44 | uses: actions/setup-go@v5 45 | with: 46 | go-version: ${{ matrix.go-version }} 47 | 48 | # Ref: https://github.com/actions/cache/blob/main/examples.md#go---modules 49 | # Warning: This is Linux specific 50 | - uses: actions/cache@v4 51 | with: 52 | path: | 53 | ~/.cache/go-build 54 | ~/go/pkg/mod 55 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 56 | restore-keys: | 57 | ${{ runner.os }}-go- 58 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-html.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint HTML 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.htm" 9 | - "*.htm" 10 | - ".github/workflows/lint-html.yaml" 11 | pull_request: 12 | branches: [main, master] 13 | paths: 14 | - "**.htm" 15 | - "*.htm" 16 | - ".github/workflows/lint-html.yaml" 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | 28 | # Run this locally with act - https://github.com/nektos/act 29 | # act -j lintHTML 30 | lintHTML: 31 | runs-on: ubuntu-latest 32 | timeout-minutes: 15 33 | 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v4 37 | with: 38 | persist-credentials: false 39 | 40 | - name: Install HTMLHint (Linter) 41 | run: npm install htmlhint -g 42 | 43 | - name: Run Linter 44 | run: htmlhint . 45 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-markdown.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintMarkdown 4 | name: Lint Markdown 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [main, master] 9 | paths: 10 | - "**.md" 11 | - ".github/workflows/lint-markdown.yaml" 12 | pull_request: 13 | branches: [main, master] 14 | paths: 15 | - "**.md" 16 | - ".github/workflows/lint-markdown.yaml" 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | lintMarkdown: 28 | runs-on: ubuntu-latest 29 | timeout-minutes: 15 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v4 34 | with: 35 | persist-credentials: false 36 | 37 | - name: Set up Ruby 38 | # See https://github.com/ruby/setup-ruby#versioning 39 | uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 40 | with: 41 | ruby-version: 3.0 42 | 43 | - name: Install dependencies 44 | run: gem install mdl 45 | 46 | - name: Run tests 47 | # Rule list: https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md 48 | # Don't check for line length (MD013) 49 | # Don't care about list ordering (MD029) 50 | run: mdl --git-recurse --rules ~MD013,~MD029 . 51 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-python.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Python 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [main, master] 7 | paths: 8 | - "**.py" 9 | - "**/requirements.txt" 10 | - "**/requirements-dev.txt" 11 | - ".github/workflows/lint-python.yaml" 12 | pull_request: 13 | branches: [main, master] 14 | paths: 15 | - "**.py" 16 | - "**/requirements.txt" 17 | - "**/requirements-dev.txt" 18 | - ".github/workflows/lint-python.yaml" 19 | 20 | 21 | concurrency: 22 | group: ${{ github.workflow }}-${{ github.ref }} 23 | cancel-in-progress: true 24 | 25 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 26 | permissions: 27 | contents: read 28 | 29 | jobs: 30 | lintPython: 31 | runs-on: ubuntu-latest 32 | timeout-minutes: 15 33 | strategy: 34 | matrix: 35 | # https://devguide.python.org/versions 36 | python-version: ["3.8"] 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v4 40 | with: 41 | persist-credentials: false 42 | 43 | - name: Set up Python ${{ matrix.python-version }} 44 | uses: actions/setup-python@v5 45 | with: 46 | python-version: ${{ matrix.python-version }} 47 | # Options are pip, pipenv, or poetry 48 | cache: "pip" 49 | cache-dependency-path: "**/requirements.txt" 50 | 51 | - name: Install dependencies 52 | run: find . -iname requirements.txt -exec pip install -r {} \; 53 | 54 | - name: Install pylint and flake8 55 | run: | 56 | pip install pylint 57 | pip install flake8 58 | 59 | - name: Run pylint 60 | run: | 61 | # Add ignore rules here via --disable 62 | # By default, only errors and warnings are enabled 63 | python3 -m pylint --disable=R,C --recursive=y . 64 | 65 | - name: Run flake8 66 | run: | 67 | # Add ignore rules here via --ignore 68 | flake8 . --count --ignore=E501,W504 --show-source --statistics 69 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 70 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-shell-script.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintShellScript 4 | name: Lint Shell scripts 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [main, master] 9 | paths: 10 | - "**.sh" 11 | - "**.bash" 12 | - ".github/workflows/lint-shell-script.yaml" 13 | pull_request: 14 | branches: [main, master] 15 | paths: 16 | - "**.sh" 17 | - "**.bash" 18 | - ".github/workflows/lint-shell-script.yaml" 19 | 20 | concurrency: 21 | group: ${{ github.workflow }}-${{ github.ref }} 22 | cancel-in-progress: true 23 | 24 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 25 | permissions: 26 | contents: read 27 | 28 | jobs: 29 | 30 | lintShellScript: 31 | runs-on: ubuntu-latest 32 | timeout-minutes: 15 33 | 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v4 37 | with: 38 | persist-credentials: false 39 | 40 | - name: Run ShellCheck 41 | uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0 42 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-solidity.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Solidity Linter 3 | on: # yamllint disable-line rule:truthy 4 | pull_request: 5 | branches: [main, master] 6 | paths: 7 | - "**.sol" 8 | - ".github/workflows/lint-solidity.yaml" 9 | push: 10 | branches: [main, master] 11 | paths: 12 | - "**.sol" 13 | - ".github/workflows/lint-solidity.yaml" 14 | 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.ref }} 17 | cancel-in-progress: true 18 | 19 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 20 | permissions: 21 | contents: read 22 | 23 | jobs: 24 | 25 | # Run it locally with https://github.com/nektos/act 26 | # act -j lintSolidity 27 | lintSolidity: 28 | 29 | runs-on: ubuntu-latest 30 | timeout-minutes: 15 31 | 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v4 35 | with: 36 | persist-credentials: false 37 | 38 | - name: solhint 39 | uses: contractshark/inject-solhint-ci@7d2f4b657ae76a93605d045e7be0378b43bb2382 # v1.0.0+alpha 40 | with: 41 | github_token: ${{ secrets.github_token }} 42 | reporter: github-pr-review # Change reporter 43 | solhint_input: '*/**.sol' 44 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/lint-yaml.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j lintYaml 4 | name: Lint YAML 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [main, master] 9 | paths: 10 | - '**.yml' 11 | - '**.yaml' 12 | - '.github/workflows/**.yml' 13 | - '.github/workflows/**.yaml' 14 | pull_request: 15 | branches: [main, master] 16 | paths: 17 | - "**.yml" 18 | - "**.yaml" 19 | - ".github/workflows/**.yml" 20 | - ".github/workflows/**.yaml" 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.ref }} 24 | cancel-in-progress: true 25 | 26 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 27 | permissions: 28 | contents: read 29 | 30 | jobs: 31 | lintYaml: 32 | runs-on: ubuntu-latest 33 | timeout-minutes: 15 34 | 35 | steps: 36 | - name: Checkout repository 37 | uses: actions/checkout@v4 38 | with: 39 | persist-credentials: false 40 | 41 | - name: Check YAML files with linter 42 | uses: ibiqlik/action-yamllint@2576378a8e339169678f9939646ee3ee325e845c # v3.1.1 43 | with: 44 | # All files under base dir 45 | file_or_dir: "." 46 | config_data: | 47 | extends: default 48 | yaml-files: 49 | - '*.yaml' 50 | - '*.yml' 51 | rules: 52 | document-start: 53 | level: warning 54 | line-length: 55 | level: warning 56 | new-line-at-end-of-file: 57 | level: warning 58 | trailing-spaces: 59 | level: warning 60 | 61 | - name: Lint GitHub Actions 62 | uses: reviewdog/action-actionlint@a5524e1c19e62881d79c1f1b9b6f09f16356e281 # v1.65.2 63 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/translate-android.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Automatically Translate Android App 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: ["master", "main"] 7 | paths: 8 | - "**/strings.xml" 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.ref }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | 16 | # Run locally with "act -j translateAndroid" 17 | translateAndroid: 18 | 19 | runs-on: ubuntu-latest 20 | timeout-minutes: 15 21 | 22 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 23 | permissions: 24 | contents: read 25 | pull-requests: write 26 | 27 | steps: 28 | - name: Checkout repository 29 | uses: actions/checkout@v4 30 | with: 31 | persist-credentials: false 32 | 33 | - name: Translate strings.xml to supported languages 34 | uses: ashishb/android-auto-translate@465b9bb4feb7ce761cad417cf9faac720f8abdfa # v1.0.0 35 | 36 | - name: Create Pull Request 37 | uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 38 | with: 39 | committer: "ashishb's Translation Bot " 40 | commit-message: "Auto-generated translations by [Android Auto Translate](https://github.com/ashishb/android-auto-translate) bot" 41 | title: "[Bot]Auto-generated translations for non-English languages" 42 | body: "Auto-generated translations by [Android Auto Translate](https://github.com/ashishb/android-auto-translate) bot" 43 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/validate-openapi-schema.incomplete.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Validate Open API schema 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [master, main] 7 | paths: 8 | - ".github/workflows/validate-openapi-schema.yaml" 9 | - "**/openapi.json" 10 | - "**/openapi.yaml" 11 | - "**/openapi.yml" 12 | pull_request: 13 | branches: [master, main] 14 | paths: 15 | - ".github/workflows/validate-openapi-schema.yaml" 16 | - "**/openapi.json" 17 | - "**/openapi.yaml" 18 | - "**/openapi.yml" 19 | 20 | concurrency: 21 | group: ${{ github.workflow }}-${{ github.ref }} 22 | cancel-in-progress: true 23 | 24 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 25 | permissions: 26 | contents: read 27 | 28 | jobs: 29 | 30 | # Run locally with "act -j validateOpenAPISchema" 31 | validateOpenAPISchema: 32 | runs-on: ubuntu-latest 33 | timeout-minutes: 15 34 | 35 | steps: 36 | 37 | - name: Checkout repository (current branch) 38 | uses: actions/checkout@v4 39 | with: 40 | persist-credentials: false 41 | path: head 42 | fetch-depth: 1 43 | 44 | - name: Checkout repository (default branch) 45 | uses: actions/checkout@v4 46 | with: 47 | persist-credentials: false 48 | ref: ${{ github.event.repository.default_branch }} 49 | path: base 50 | fetch-depth: 1 51 | 52 | # Perform linter and backward compatibility checks here 53 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/data/validate-render-blueprint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Run this locally with act - https://github.com/nektos/act 3 | # act -j validateRenderBlueprint 4 | name: Validate Render Blueprint 5 | 6 | on: # yamllint disable-line rule:truthy 7 | push: 8 | branches: [main, master] 9 | paths: 10 | - "render.yml" 11 | - "render.yaml" 12 | - ".github/workflows/validate-render-blueprint.yaml" 13 | pull_request: 14 | branches: [main, master] 15 | paths: 16 | - "render.yml" 17 | - "render.yaml" 18 | - ".github/workflows/validate-render-blueprint.yaml" 19 | 20 | concurrency: 21 | group: ${{ github.workflow }}-${{ github.ref }} 22 | cancel-in-progress: true 23 | 24 | # Ref: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token 25 | permissions: 26 | contents: read 27 | 28 | jobs: 29 | validateRenderBlueprint: 30 | runs-on: ubuntu-latest 31 | timeout-minutes: 15 32 | 33 | steps: 34 | - name: Checkout repository 35 | uses: actions/checkout@v4 36 | with: 37 | persist-credentials: false 38 | sparse-checkout: | 39 | render.yml 40 | render.yaml 41 | 42 | - name: Download render.com blueprint schema 43 | run: | 44 | wget https://render.com/schema/render.yaml.json -O /tmp/render.yaml.json 45 | 46 | - name: Validate Render Blueprint 47 | uses: GrantBirki/json-yaml-validate@250fa0dc7d7f4a888b24dc2a6b2ff589753fba70 # v3.3.2@v3 48 | with: 49 | yaml_schema: /tmp/render.yaml.json # validate YAML files against the schema 50 | yaml_as_json: true 51 | files: | 52 | render.yml 53 | render.yaml 54 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "fmt" 5 | "github.com/rs/zerolog/log" 6 | ) 7 | 8 | type Generator struct { 9 | // base dir to the git repo 10 | dir string 11 | // if true, overwrite existing files 12 | force bool 13 | } 14 | 15 | func NewGenerator(dir string, force bool) Generator { 16 | return Generator{ 17 | dir: dir, 18 | force: force, 19 | } 20 | } 21 | 22 | func (g Generator) Generate(options []string) error { 23 | if g.force { 24 | log.Warn().Msgf("Force overwrite is on, existing files will be over-written") 25 | } 26 | for _, optionStr := range options { 27 | option, err := getOptionForFlag(optionStr) 28 | if err != nil { 29 | return err 30 | } 31 | str, err := (*option).GetYamlConfig(g.dir) 32 | if err != nil { 33 | return err 34 | } 35 | err = writeOrWarn((*option).GetOutputFileName(g.dir), *str, g.force) 36 | if err != nil { 37 | return err 38 | } 39 | } 40 | return nil 41 | } 42 | 43 | func getOptionForFlag(target string) (*Option, error) { 44 | for _, option := range GetOptions() { 45 | if option.FlagName() == target { 46 | return &option, nil 47 | } 48 | } 49 | return nil, fmt.Errorf("invalid option: %s", target) 50 | } 51 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/golang_lint_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "fmt" 5 | "github.com/rs/zerolog/log" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | ) 10 | 11 | const _goLangLintTask = ` 12 | 13 | - name: Run "govulncheck" 14 | working-directory: "%s" 15 | run: go run golang.org/x/vuln/cmd/govulncheck@latest ./... 16 | 17 | - name: Run golangci-lint on %s 18 | uses: golangci/golangci-lint-action@v6 19 | with: 20 | # We use cache provided by "actions/setup-go" 21 | skip-cache: true 22 | # Directory containing go.mod file 23 | working-directory: "%s" 24 | ` 25 | 26 | var errNoSuchDir = fmt.Errorf("no such dir") 27 | 28 | func generateGoLintYaml(repoDir string) (*string, error) { 29 | dirs, err := getDirsContaining(repoDir, "go.mod") 30 | if err != nil { 31 | return nil, err 32 | } 33 | str := _lintGoTemplate 34 | for _, dir := range dirs { 35 | str += fmt.Sprintf(_goLangLintTask, dir, dir, dir) 36 | } 37 | return &str, nil 38 | } 39 | 40 | // Returns "relative" path of dirs inside baseDir containing "fileName" 41 | // Error is returned instead of the empty array 42 | func getDirsContaining(dir string, fileName string) ([]string, error) { 43 | absPaths, err := getDirsContaining2(dir, fileName) 44 | if err != nil { 45 | return nil, err 46 | } 47 | if len(absPaths) == 0 { 48 | return nil, errNoSuchDir 49 | } 50 | return getRelativePaths(dir, absPaths), nil 51 | } 52 | 53 | func getRelativePaths(dir string, absPaths []string) []string { 54 | relPaths := make([]string, 0, len(absPaths)) 55 | for _, absPath := range absPaths { 56 | relPath := strings.TrimPrefix(strings.TrimPrefix(absPath, dir), string(os.PathSeparator)) 57 | if len(relPath) == 0 { 58 | relPath = "." 59 | } 60 | relPaths = append(relPaths, relPath) 61 | } 62 | return relPaths 63 | } 64 | 65 | // Returns "absolute" path of dirs inside baseDir containing "fileName" 66 | // Error is returned instead of the empty array 67 | func getDirsContaining2(dir string, fileName string) ([]string, error) { 68 | entries, err := os.ReadDir(dir) 69 | if err != nil { 70 | return nil, err 71 | } 72 | results := make([]string, 0) 73 | 74 | for _, entry := range entries { 75 | // Ignore 76 | if entry.IsDir() && (entry.Name() == ".git" || entry.Name() == "node_modules" || 77 | entry.Name() == ".idea") { 78 | continue 79 | } 80 | if entry.IsDir() { 81 | tmp, err := getDirsContaining2(filepath.Join(dir, entry.Name()), fileName) 82 | if err != nil { 83 | return nil, err 84 | } 85 | results = append(results, tmp...) 86 | continue 87 | } 88 | if strings.EqualFold(entry.Name(), fileName) { 89 | log.Debug().Msgf("Looking at the file %s", entry.Name()) 90 | results = append(results, dir) 91 | } 92 | } 93 | return results, nil 94 | } 95 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/goreleaser_config_checker_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/rs/zerolog/log" 7 | ) 8 | 9 | const _goReleaserCheckerTask = ` 10 | - name: Check Go Releaser config is valid 11 | run: goreleaser check --config %s/%s 12 | 13 | - name: Build (not release) binaries with Go Releaser 14 | run: goreleaser build --snapshot --clean 15 | ` 16 | 17 | var _goReleaserConfigFiles = []string{ 18 | "**/goreleaser.yaml", "**/goreleaser.yml", "**/.goreleaser.yaml", "**/.goreleaser.yml", 19 | } 20 | 21 | func generateGoReleaserConfigCheckerYaml(repoDir string) (*string, error) { 22 | found := false 23 | template := _checkGoReleaserConfigTemplate 24 | for _, openAPIFile := range _goReleaserConfigFiles { 25 | result, err := generateGoReleaserCheckerInternal(template, repoDir, openAPIFile) 26 | if err != nil && !errors.Is(err, errNoSuchDir) { 27 | return nil, err 28 | } 29 | if errors.Is(err, errNoSuchDir) { 30 | log.Debug().Msgf("No dir containing %s found", openAPIFile) 31 | continue 32 | } 33 | template = *result 34 | found = true 35 | } 36 | if !found { 37 | return nil, errNoSuchDir 38 | } 39 | return &template, nil 40 | } 41 | 42 | func generateGoReleaserCheckerInternal(template, repoDir, releaserFile string) (*string, error) { 43 | dirs, err := getDirsContaining(repoDir, releaserFile) 44 | if err != nil { 45 | return nil, err 46 | } 47 | str := template 48 | for _, dir := range dirs { 49 | str += fmt.Sprintf(_goReleaserCheckerTask, dir, releaserFile) 50 | } 51 | return &str, nil 52 | } 53 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/openapi_schema_validator_generator.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/rs/zerolog/log" 7 | ) 8 | 9 | const _validateSchemaTask = ` 10 | # Ref: https://github.com/daveshanley/vacuum 11 | - name: Validate OpenAPI schema 12 | working-directory: head 13 | run: 14 | docker run --rm -v $PWD:/work:ro dshanley/vacuum lint -d %s 15 | 16 | # Ref: https://github.com/Tufin/oasdiff 17 | - name: Running OpenAPI Spec diff action 18 | env: 19 | BASE: ./base/%s 20 | REVISION: ./head/%s 21 | run: | 22 | docker run --rm -v $PWD:/code:ro -t tufin/oasdiff breaking --fail-on WARN -f githubactions "${BASE}" "${REVISION}" 23 | ` 24 | 25 | var _openAPIFileList = []string{"openapi.yaml", "openapi.yml", "**/openapi.json"} 26 | 27 | func generateOpenAPISchemaValidator(repoDir string) (*string, error) { 28 | found := false 29 | template := _generateOpenAPISchemaValidatorTemplate 30 | for _, openAPIFile := range _openAPIFileList { 31 | result, err := generateOpenAPISchemaValidatorInternal(template, repoDir, openAPIFile) 32 | if err != nil && !errors.Is(err, errNoSuchDir) { 33 | return nil, err 34 | } 35 | if errors.Is(err, errNoSuchDir) { 36 | log.Debug().Msgf("No dir containing %s found", openAPIFile) 37 | continue 38 | } 39 | template = *result 40 | found = true 41 | } 42 | if !found { 43 | return nil, errNoSuchDir 44 | } 45 | return &template, nil 46 | } 47 | 48 | func generateOpenAPISchemaValidatorInternal(template string, repoDir string, openAPIFile string) (*string, error) { 49 | dirs, err := getDirsContaining(repoDir, openAPIFile) 50 | if err != nil { 51 | return nil, err 52 | } 53 | str := template 54 | for _, dir := range dirs { 55 | path := fmt.Sprintf("%s/%s", dir, openAPIFile) 56 | str += fmt.Sprintf(_validateSchemaTask, path, path, path) 57 | } 58 | return &str, nil 59 | } 60 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/write_utils.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "fmt" 5 | "github.com/rs/zerolog/log" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | ) 10 | 11 | func writeOrWarn(outFilePath string, data string, force bool) error { 12 | if !force && fileExists(outFilePath) { 13 | return fmt.Errorf("cannot write %s, file already exists", outFilePath) 14 | } 15 | if !dirExists(filepath.Dir(outFilePath)) { 16 | log.Debug().Msgf("Creating directory %s", filepath.Dir(outFilePath)) 17 | err := os.MkdirAll(filepath.Dir(outFilePath), 0755) 18 | if err != nil { 19 | return err 20 | } 21 | } 22 | file, err := os.Create(outFilePath) 23 | if err != nil { 24 | return err 25 | } 26 | data = "# Generated by Gabo (https://github.com/ashishb/gabo)\n" + data 27 | _, err = io.WriteString(file, data) 28 | if err != nil { 29 | return err 30 | } 31 | log.Info().Msgf("Wrote file %s", outFilePath) 32 | return file.Close() 33 | } 34 | 35 | func fileExists(path string) bool { 36 | _, err := os.Stat(path) 37 | return err == nil 38 | } 39 | 40 | func dirExists(path string) bool { 41 | info, err := os.Stat(path) 42 | if err != nil { 43 | return false 44 | } 45 | if !info.IsDir() { 46 | log.Warn().Msgf("Path exists but is not a directory: %s", path) 47 | return false 48 | } 49 | return true 50 | } 51 | -------------------------------------------------------------------------------- /src/gabo/internal/generator/yaml_embed_list.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import _ "embed" 4 | 5 | var ( 6 | //go:embed data/build-android-incomplete.yaml 7 | _buildAndroidTemplate string 8 | //go:embed data/build-docker-incomplete.yaml 9 | _buildDockerTemplate string 10 | //go:embed data/build-npm-incomplete.yaml 11 | _buildNpmTemplate string 12 | //go:embed data/build-yarn-incomplete.yaml 13 | _buildYarnTemplate string 14 | //go:embed data/check-goreleaser-config.yaml 15 | _checkGoReleaserConfigTemplate string 16 | //go:embed data/compress-images.yaml 17 | _comressImageYaml string 18 | //go:embed data/format-go.yaml 19 | _formatGoYaml string 20 | //go:embed data/format-python.yaml 21 | _formatPythonYaml string 22 | //go:embed data/validate-openapi-schema.incomplete.yaml 23 | _generateOpenAPISchemaValidatorTemplate string 24 | //go:embed data/lint-android.yaml 25 | _lintAndroidYaml string 26 | //go:embed data/lint-docker.yaml 27 | _lintDockerYaml string 28 | //go:embed data/lint-go-incomplete.yaml 29 | _lintGoTemplate string 30 | //go:embed data/lint-html.yaml 31 | _lintHtmlYaml string 32 | //go:embed data/lint-markdown.yaml 33 | _lintMarkdownYaml string 34 | //go:embed data/lint-python.yaml 35 | _lintPythonYaml string 36 | //go:embed data/lint-shell-script.yaml 37 | _lintShellScriptYaml string 38 | //go:embed data/lint-solidity.yaml 39 | _lintSolidityYaml string 40 | //go:embed data/lint-yaml.yaml 41 | _lintYamlYaml string 42 | //go:embed data/lint-github-actions.yaml 43 | _lintGitHubActionsYaml string 44 | //go:embed data/translate-android.yaml 45 | _translateAndroidYaml string 46 | //go:embed data/validate-render-blueprint.yaml 47 | _validateRenderBlueprintYaml string 48 | ) 49 | --------------------------------------------------------------------------------