├── .all-contributorsrc ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── codacy-analysis.yml │ ├── code-coverage.yml │ ├── codeql.yml │ ├── format-tidy.yml │ ├── lint.yml │ ├── sync-release-version.yml │ └── test.yml ├── .gitignore ├── .goreleaser.yaml ├── .whitesource ├── CODE_OF_CONDUCT.md ├── HISTORY.md ├── LICENSE ├── Makefile ├── README.md ├── action.yml ├── cmd ├── root.go └── root_test.go ├── entrypoint.sh ├── go.mod ├── go.sum ├── internal ├── constants.go ├── types │ ├── action.go │ ├── code_block.go │ ├── documentation.go │ └── reusable.go └── utils │ ├── bytes_utils.go │ ├── format_value.go │ ├── get_latest_repository_tag.go │ ├── markdown_link.go │ └── word_wrap.go ├── main.go └── test ├── README-action-empty-markers-no-inputs-no-outputs.expected.md ├── README-action-empty-markers.md ├── README-codeBlocks.md ├── README-codeBlocksMajorVersion.md ├── README-codeBlocksWithCommitHash.md ├── README-codeBlocksWithCommitHashMajorVersion.md ├── README-inputColumns.md ├── README-markdownLinks.md ├── README-outputColumns.md ├── README-reusable-inputColumns.md ├── README-reusable-markdownLinks.md ├── README-reusable-outputColumns.md ├── README-reusable-secretColumns.md ├── README-reusable.md ├── README-workflow-empty-markers-no-inputs-no-outputs.expected.md ├── README-workflow-empty-markers.md ├── README.md ├── action-no-inputs-no-outputs.yml ├── action.yml ├── reusable-action.yml └── reusable-workflow-no-inputs-no-outputs.yml /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "commitConvention": "angular", 8 | "contributors": [ 9 | { 10 | "login": "andreas-aman", 11 | "name": "Andreas Åman", 12 | "avatar_url": "https://avatars.githubusercontent.com/u/118175695?v=4", 13 | "profile": "https://github.com/andreas-aman", 14 | "contributions": [ 15 | "code", 16 | "doc" 17 | ] 18 | }, 19 | { 20 | "login": "ViacheslavKudinov", 21 | "name": "Viacheslav Kudinov", 22 | "avatar_url": "https://avatars.githubusercontent.com/u/56436734?v=4", 23 | "profile": "https://github.com/ViacheslavKudinov", 24 | "contributions": [ 25 | "code", 26 | "test" 27 | ] 28 | }, 29 | { 30 | "login": "looztra", 31 | "name": "Christophe Furmaniak", 32 | "avatar_url": "https://avatars.githubusercontent.com/u/246526?v=4", 33 | "profile": "https://github.com/looztra", 34 | "contributions": [ 35 | "code", 36 | "test" 37 | ] 38 | }, 39 | { 40 | "login": "mw-root", 41 | "name": "Mike W", 42 | "avatar_url": "https://avatars.githubusercontent.com/u/12434761?v=4", 43 | "profile": "https://github.com/mw-root", 44 | "contributions": [ 45 | "code", 46 | "doc" 47 | ] 48 | } 49 | ], 50 | "contributorsPerLine": 7, 51 | "skipCi": true, 52 | "repoType": "github", 53 | "repoHost": "https://github.com", 54 | "projectName": "auto-doc", 55 | "projectOwner": "tj-actions", 56 | "commitType": "docs" 57 | } 58 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | open-pull-requests-limit: 10 8 | labels: 9 | - "merge when passing" 10 | - package-ecosystem: "gomod" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | open-pull-requests-limit: 10 15 | labels: 16 | - "merge when passing" 17 | -------------------------------------------------------------------------------- /.github/workflows/codacy-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow checks out code, performs a Codacy security scan 2 | # and integrates the results with the 3 | # GitHub Advanced Security code scanning feature. For more information on 4 | # the Codacy security scan action usage and parameters, see 5 | # https://github.com/codacy/codacy-analysis-cli-action. 6 | # For more information on Codacy Analysis CLI in general, see 7 | # https://github.com/codacy/codacy-analysis-cli. 8 | 9 | name: Codacy Security Scan 10 | 11 | on: 12 | push: 13 | branches: [ main ] 14 | pull_request: 15 | # The branches below must be a subset of the branches above 16 | branches: [ main ] 17 | schedule: 18 | - cron: '15 16 * * 2' 19 | 20 | jobs: 21 | codacy-security-scan: 22 | # Cancel other workflows that are running for the same branch 23 | # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.ref }} 26 | cancel-in-progress: true 27 | name: Codacy Security Scan 28 | runs-on: ubuntu-latest 29 | steps: 30 | # Checkout the repository to the GitHub Actions runner 31 | - name: Checkout code 32 | uses: actions/checkout@v4 33 | 34 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis 35 | - name: Run Codacy Analysis CLI 36 | continue-on-error: true 37 | uses: codacy/codacy-analysis-cli-action@v4.4.5 38 | with: 39 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository 40 | # You can also omit the token and run the tools that support default configurations 41 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 42 | verbose: true 43 | output: results.sarif 44 | format: sarif 45 | # Adjust severity of non-security issues 46 | gh-code-scanning-compat: true 47 | # Force 0 exit code to allow SARIF file generation 48 | # This will hand over control about PR rejection to the GitHub side 49 | max-allowed-issues: 2147483647 50 | 51 | # Upload the SARIF file generated in the previous step 52 | - name: Upload SARIF results file 53 | continue-on-error: true 54 | uses: github/codeql-action/upload-sarif@v3 55 | with: 56 | sarif_file: results.sarif 57 | -------------------------------------------------------------------------------- /.github/workflows/code-coverage.yml: -------------------------------------------------------------------------------- 1 | name: Generate code coverage badge 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | if: | 15 | ( 16 | github.actor != 'dependabot[bot]' && 17 | github.actor != 'dependabot' && 18 | github.event.pull_request.head.repo.fork != 'true' 19 | ) 20 | name: Update coverage badge 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | with: 25 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. 26 | fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. 27 | 28 | - name: Setup go 29 | uses: actions/setup-go@v5 30 | with: 31 | go-version-file: 'go.mod' 32 | 33 | - uses: actions/cache@v4 34 | with: 35 | path: ~/go/pkg/mod 36 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 37 | restore-keys: | 38 | ${{ runner.os }}-go- 39 | 40 | - name: Run Test 41 | run: | 42 | go test -v ./... -covermode=count -coverprofile=coverage.out 43 | go tool cover -func=coverage.out -o=coverage2.out 44 | 45 | - name: Run codacy-coverage-reporter 46 | uses: codacy/codacy-coverage-reporter-action@v1 47 | with: 48 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 49 | coverage-reports: coverage.out 50 | force-coverage-parser: go 51 | language: go 52 | 53 | - name: Upload coverage to Codecov 54 | uses: codecov/codecov-action@v5 55 | 56 | - name: Go Coverage Badge 57 | uses: tj-actions/coverage-badge-go@v2 58 | with: 59 | filename: coverage2.out 60 | 61 | - name: Verify Changed files 62 | uses: tj-actions/verify-changed-files@v20 63 | id: verify-changed-files 64 | with: 65 | files: README.md 66 | 67 | - name: Commit changes 68 | if: steps.verify-changed-files.outputs.files_changed == 'true' 69 | run: | 70 | git config --local user.email "action@github.com" 71 | git config --local user.name "GitHub Action" 72 | git add README.md 73 | git commit -m "chore: Updated coverage badge." 74 | 75 | - name: Push changes 76 | if: steps.verify-changed-files.outputs.files_changed == 'true' 77 | uses: ad-m/github-push-action@master 78 | with: 79 | github_token: ${{ secrets.PAT_TOKEN || github.token }} 80 | branch: ${{ github.head_ref }} 81 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '16 9 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'go' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v3 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v3 73 | with: 74 | category: "/language:${{matrix.language}}" 75 | -------------------------------------------------------------------------------- /.github/workflows/format-tidy.yml: -------------------------------------------------------------------------------- 1 | name: Format & Tidy go.mod 2 | on: 3 | pull_request: 4 | paths: 5 | - '**.go' 6 | - '**.mod' 7 | - 'Makefile' 8 | - '.github/workflows/format-tidy.yml' 9 | branches: 10 | - 'main' 11 | 12 | jobs: 13 | cleanup-runs: 14 | runs-on: ubuntu-latest 15 | if: github.event.pull_request.head.repo.owner.login == github.repository_owner 16 | steps: 17 | - uses: rokroskar/workflow-run-cleanup-action@v0.3.3 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.github_token }} 20 | 21 | format: 22 | name: format 23 | runs-on: ubuntu-latest 24 | if: github.event.pull_request.head.repo.owner.login == github.repository_owner 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | with: 29 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. 30 | fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. 31 | 32 | - name: Setup go 33 | uses: actions/setup-go@v5 34 | with: 35 | go-version-file: 'go.mod' 36 | 37 | - uses: actions/cache@v4 38 | with: 39 | path: ~/go/pkg/mod 40 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 41 | restore-keys: | 42 | ${{ runner.os }}-go- 43 | 44 | - name: Format code 45 | run: 46 | make format 47 | 48 | - name: Tidy go.mod 49 | run: 50 | make tidy 51 | 52 | - name: Verify Changed files 53 | uses: tj-actions/verify-changed-files@v20 54 | id: verify-changed-files 55 | with: 56 | files: | 57 | **/*.go 58 | *.mod 59 | *.sum 60 | 61 | - name: Commit formatting changes 62 | if: steps.verify-changed-files.outputs.files_changed == 'true' 63 | run: | 64 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 65 | git config --local user.name "github-actions[bot]" 66 | git add cmd ${{ steps.verify-changed-files.outputs.changed_files }} 67 | git commit -m "Formatted code." 68 | 69 | - name: Push formatting changes 70 | if: steps.verify-changed-files.outputs.files_changed == 'true' 71 | uses: ad-m/github-push-action@master 72 | with: 73 | github_token: ${{ secrets.PAT_TOKEN || github.token }} 74 | branch: ${{ github.head_ref }} 75 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - 'main' 6 | pull_request: 7 | paths: 8 | - '**.go' 9 | - '**.mod' 10 | - 'Makefile' 11 | - '.github/workflows/lint.yml' 12 | branches: 13 | - 'main' 14 | 15 | jobs: 16 | cleanup-runs: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: rokroskar/workflow-run-cleanup-action@v0.3.3 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.github_token }} 22 | 23 | golangci-lint: 24 | name: golangci lint 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | 30 | - name: golangci-lint 31 | uses: reviewdog/action-golangci-lint@v2 32 | with: 33 | go-version-file: 'go.mod' 34 | -------------------------------------------------------------------------------- /.github/workflows/sync-release-version.yml: -------------------------------------------------------------------------------- 1 | name: Update release version. 2 | on: 3 | release: 4 | types: [published] 5 | 6 | 7 | jobs: 8 | check-version: 9 | runs-on: ubuntu-latest 10 | name: semver-diff 11 | steps: 12 | - uses: actions/checkout@v4 13 | with: 14 | fetch-depth: 0 15 | ref: main 16 | 17 | - name: Get branch name 18 | id: branch-name 19 | uses: tj-actions/branch-names@v8 20 | 21 | - name: Run semver-diff 22 | id: semver-diff 23 | uses: tj-actions/semver-diff@v3 24 | 25 | - name: Show release type 26 | if: steps.semver-diff.outputs.release_type == 'major' 27 | run: | 28 | OLD_VERSION=$(echo "${{ steps.semver-diff.outputs.old_version }}" | cut -d'.' -f1 | cut -d'v' -f2) 29 | MAJOR_VERSION=$(echo "${{ steps.semver-diff.outputs.new_version }}" | cut -d'.' -f1 | cut -d'v' -f2) 30 | 31 | make upgrade-from-one-version-to-a-major-version OLD_VERSION=$OLD_VERSION MAJOR_VERSION=$MAJOR_VERSION 32 | 33 | - name: Commit the change to the main branch and update the latest version 34 | if: steps.semver-diff.outputs.release_type == 'major' 35 | run: | 36 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 37 | git config --local user.name "github-actions[bot]" 38 | git tag -d ${{ steps.branch-name.outputs.tag }} 39 | git add . 40 | git commit -m "chore: upgraded from ${{ steps.semver-diff.outputs.old_version }} -> ${{ steps.semver-diff.outputs.new_version }}" 41 | git push -f origin main 42 | git tag ${{ steps.branch-name.outputs.tag }} 43 | git push -f origin ${{ steps.branch-name.outputs.tag }} 44 | 45 | release: 46 | name: release 47 | runs-on: ubuntu-latest 48 | needs: check-version 49 | steps: 50 | - uses: actions/checkout@v4 51 | with: 52 | fetch-depth: 0 53 | 54 | - uses: actions/setup-go@v5 55 | with: 56 | go-version-file: 'go.mod' 57 | 58 | - uses: actions/cache@v4 59 | with: 60 | path: ~/go/pkg/mod 61 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 62 | restore-keys: | 63 | ${{ runner.os }}-go- 64 | 65 | - name: GoReleaser 66 | uses: goreleaser/goreleaser-action@v5 67 | with: 68 | version: latest 69 | args: release --clean 70 | env: 71 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 72 | HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }} 73 | 74 | update-version: 75 | runs-on: ubuntu-latest 76 | needs: release 77 | steps: 78 | - uses: actions/checkout@v4 79 | with: 80 | fetch-depth: 0 81 | ref: main 82 | 83 | - name: Sync release version. 84 | uses: tj-actions/sync-release-version@v13 85 | id: sync-release-version 86 | with: 87 | pattern: '${{ github.repository }}@' 88 | only_major: true 89 | paths: | 90 | README.md 91 | 92 | - name: Sync release version for action.yml. 93 | uses: tj-actions/sync-release-version@v13 94 | id: sync-release-version-action 95 | with: 96 | pattern: 'version: ' 97 | paths: | 98 | action.yml 99 | 100 | - name: Run git-cliff 101 | uses: tj-actions/git-cliff@v1 102 | 103 | - name: Get branch name 104 | id: branch-name 105 | uses: tj-actions/branch-names@v8 106 | 107 | - name: Verify Changed files 108 | uses: tj-actions/verify-changed-files@v20 109 | id: verify-changed-files 110 | with: 111 | files: | 112 | README.md 113 | HISTORY.md 114 | action.yml 115 | 116 | - name: Commit changes 117 | if: steps.verify-changed-files.outputs.files_changed == 'true' 118 | run: | 119 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 120 | git config --local user.name "github-actions[bot]" 121 | git tag -d ${{ steps.branch-name.outputs.tag }} 122 | git add ${{ steps.verify-changed-files.outputs.changed_files }} 123 | git commit -m "chore: upgraded from ${{ steps.sync-release-version.outputs.old_version }} -> ${{ steps.sync-release-version.outputs.new_version }}" 124 | git tag ${{ steps.branch-name.outputs.tag }} 125 | git push -f origin ${{ steps.branch-name.outputs.tag }} 126 | 127 | - name: Run release-tagger 128 | uses: tj-actions/release-tagger@v4 129 | with: 130 | token: ${{ secrets.PAT_TOKEN }} 131 | 132 | - name: Create Pull Request 133 | uses: peter-evans/create-pull-request@v7.0.8 134 | with: 135 | base: "main" 136 | labels: "merge when passing" 137 | title: "Upgraded to ${{ steps.sync-release-version.outputs.new_version }}" 138 | branch: "upgrade-to-${{ steps.sync-release-version.outputs.new_version }}" 139 | commit-message: "Upgraded from ${{ steps.sync-release-version.outputs.old_version }} -> ${{ steps.sync-release-version.outputs.new_version }}" 140 | body: "View [CHANGES](https://github.com/${{ github.repository }}/compare/${{ steps.sync-release-version.outputs.old_version }}...${{ steps.sync-release-version.outputs.new_version }})" 141 | token: ${{ secrets.PAT_TOKEN }} 142 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | snapshot: 16 | name: snapshot 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | 23 | - uses: actions/setup-go@v5 24 | with: 25 | go-version-file: 'go.mod' 26 | 27 | - name: GoReleaser 28 | uses: goreleaser/goreleaser-action@v5 29 | with: 30 | version: '~> 1' 31 | args: release --snapshot --clean 32 | 33 | - name: Capture x86_64 (64-bit) Linux binary 34 | uses: actions/upload-artifact@v4 35 | with: 36 | name: auto-doc-linux-amd64 37 | path: dist/auto-doc_linux_amd64_v1/auto-doc 38 | 39 | - name: Capture i386 (32-bit) Linux binary 40 | uses: actions/upload-artifact@v4 41 | with: 42 | name: auto-doc-linux-i386 43 | path: dist/auto-doc_linux_386/auto-doc 44 | 45 | - name: Capture arm64 (64-bit) Linux binary 46 | uses: actions/upload-artifact@v4 47 | with: 48 | name: auto-doc-linux-arm64 49 | path: dist/auto-doc_linux_arm64/auto-doc 50 | 51 | - name: Capture armv6 (32-bit) Linux binary 52 | uses: actions/upload-artifact@v4 53 | with: 54 | name: auto-doc-linux-armv6 55 | path: dist/auto-doc_linux_arm_6/auto-doc 56 | 57 | - name: Capture armv7 (32-bit) Linux binary 58 | uses: actions/upload-artifact@v4 59 | with: 60 | name: auto-doc-linux-armv7 61 | path: dist/auto-doc_linux_arm_7/auto-doc 62 | 63 | - name: Capture x86_64 (64-bit) Windows binary 64 | uses: actions/upload-artifact@v4 65 | with: 66 | name: auto-doc-windows-amd64 67 | path: dist/auto-doc_windows_amd64_v1/auto-doc.exe 68 | 69 | - name: Capture i386 (32-bit) Windows binary 70 | uses: actions/upload-artifact@v4 71 | with: 72 | name: auto-doc-windows-i386 73 | path: dist/auto-doc_windows_386/auto-doc.exe 74 | 75 | - name: Capture arm64 (64-bit) Windows binary 76 | uses: actions/upload-artifact@v4 77 | with: 78 | name: auto-doc-windows-arm64 79 | path: dist/auto-doc_windows_arm64/auto-doc.exe 80 | 81 | - name: Capture armv7 (32-bit) Windows binary 82 | uses: actions/upload-artifact@v4 83 | with: 84 | name: auto-doc-windows-armv7 85 | path: dist/auto-doc_windows_arm_7/auto-doc.exe 86 | 87 | - name: Capture x86_64 (64-bit) MacOS binary 88 | uses: actions/upload-artifact@v4 89 | with: 90 | name: auto-doc-macos-amd64 91 | path: dist/auto-doc_darwin_amd64_v1/auto-doc 92 | 93 | - name: Capture arm64 (64-bit) MacOS binary 94 | uses: actions/upload-artifact@v4 95 | with: 96 | name: auto-doc-macos-arm64 97 | path: dist/auto-doc_darwin_arm64/auto-doc 98 | 99 | test: 100 | name: Test auto-doc 101 | if: | 102 | ( 103 | github.actor != 'dependabot[bot]' && 104 | github.actor != 'dependabot' && 105 | github.actor != 'github-actions[bot]' 106 | ) 107 | runs-on: ${{ matrix.platform }} 108 | strategy: 109 | fail-fast: false 110 | matrix: 111 | platform: [ubuntu-latest, windows-latest, macos-latest] 112 | steps: 113 | - name: Checkout 114 | uses: actions/checkout@v4 115 | if: github.event.pull_request.head.repo.owner.login == github.repository_owner 116 | with: 117 | fetch-depth: 0 # otherwise, you will fail to push refs to dest repo 118 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token 119 | ref: ${{ github.head_ref }} 120 | 121 | - name: Checkout 122 | uses: actions/checkout@v4 123 | if: github.event.pull_request.head.repo.owner.login != github.repository_owner 124 | with: 125 | fetch-depth: 0 # otherwise, you will fail to push refs to dest repo 126 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token 127 | 128 | - name: Setup go 129 | uses: actions/setup-go@v5 130 | with: 131 | go-version-file: 'go.mod' 132 | 133 | # - name: Test action 134 | # uses: ./ 135 | # if: github.event_name == 'push' 136 | 137 | - name: Run build 138 | run: make build 139 | 140 | - name: Test action with bin_path 141 | uses: ./ 142 | with: 143 | bin_path: ./bin/auto_doc 144 | use_code_blocks: true 145 | use_major_version: true 146 | 147 | - name: Test action with bin_path and reusable 148 | uses: ./ 149 | with: 150 | bin_path: ./bin/auto_doc 151 | reusable: true 152 | filename: test/reusable-action.yml 153 | output: test/README-reusable-outputColumns.md 154 | reusable_output_columns: | 155 | Output 156 | Value 157 | 158 | - name: Run auto-doc using the test directory 159 | run: make test 160 | 161 | - name: Format markdown 162 | uses: tj-actions/remark@v3 163 | 164 | - name: Verify Changed files 165 | uses: tj-actions/verify-changed-files@v20 166 | id: verify-changed-files 167 | with: 168 | files: | 169 | README.md 170 | test/** 171 | 172 | - name: Commit README changes 173 | if: steps.verify-changed-files.outputs.files_changed == 'true' && matrix.platform == 'ubuntu-latest' 174 | run: | 175 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 176 | git config --local user.name "github-actions[bot]" 177 | git add ${{ steps.verify-changed-files.outputs.changed_files }} 178 | git commit -m "Updated README." 179 | 180 | - name: Push README changes 181 | if: steps.verify-changed-files.outputs.files_changed == 'true' && matrix.platform == 'ubuntu-latest' 182 | uses: ad-m/github-push-action@master 183 | continue-on-error: true 184 | with: 185 | github_token: ${{ secrets.PAT_TOKEN || github.token }} 186 | branch: ${{ github.head_ref }} 187 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | 11 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as 12 | # password, private keys, and other secrets. These should not be part of version 13 | # control as they are data points which are potentially sensitive and subject 14 | # to change depending on the environment. 15 | # 16 | *.tfvars 17 | 18 | # Ignore override files as they are usually used to override resources locally and so 19 | # are not checked in 20 | override.tf 21 | override.tf.json 22 | *_override.tf 23 | *_override.tf.json 24 | 25 | # Include override files you do wish to add to version control using negated pattern 26 | # 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc 35 | 36 | # Pycharm 37 | .idea/ 38 | .DS_Store 39 | 40 | # Direnv 41 | .envrc 42 | 43 | # Binaries for programs and plugins 44 | *.exe 45 | *.exe~ 46 | *.dll 47 | *.so 48 | *.dylib 49 | 50 | # Test binary, built with `go test -c` 51 | *.test 52 | 53 | # Output of the go coverage tool, specifically when used with LiteIDE 54 | *.out 55 | 56 | # Dependency directories (remove the comment below to include it) 57 | vendor/ 58 | 59 | 60 | bin/ -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | # https://goreleaser.com 2 | before: 3 | hooks: 4 | - go mod tidy 5 | builds: 6 | - env: 7 | - CGO_ENABLED=0 8 | goos: 9 | - linux 10 | - windows 11 | - darwin 12 | goarch: 13 | - amd64 14 | - '386' 15 | - arm64 16 | - arm 17 | goarm: 18 | - '6' 19 | - '7' 20 | ignore: 21 | - goos: windows 22 | goarm: '6' 23 | 24 | archives: 25 | - name_template: >- 26 | {{ .ProjectName }}_ 27 | {{- .Version }}_ 28 | {{- title .Os }}_ 29 | {{- if eq .Arch "amd64" }}x86_64 30 | {{- else if eq .Arch "386" }}i386 31 | {{- else }}{{ .Arch }}{{ end }} 32 | {{- if .Arm }}v{{ .Arm }}{{ end }} 33 | format_overrides: 34 | - goos: windows 35 | format: zip 36 | checksum: 37 | name_template: 'checksums.txt' 38 | changelog: 39 | sort: asc 40 | filters: 41 | exclude: 42 | - '^docs:' 43 | - '^test:' 44 | brews: 45 | - name: auto-doc 46 | homepage: https://github.com/tj-actions/auto-doc 47 | description: Generate markdown tables for your Github action and reusable workflow with ease. 48 | repository: 49 | owner: tj-actions 50 | name: homebrew-tap 51 | branch: main 52 | token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}" 53 | license: "Apache-2.0" 54 | folder: Formula -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "baseBranches": [] 4 | }, 5 | "checkRunSettings": { 6 | "vulnerableCheckRunConclusionLevel": "failure", 7 | "displayMode": "diff" 8 | }, 9 | "issueSettings": { 10 | "minSeverityLevel": "LOW" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | jtonye@ymail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2020 Tonye Jack 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Self-Documented Makefile see https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 2 | 3 | OUTPUT := README.md 4 | FILENAME := action.yml 5 | 6 | .DEFAULT_GOAL := help 7 | 8 | .PHONY: help 9 | # Put it first so that "make" without argument is like "make help". 10 | help: 11 | @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-20s-\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) 12 | 13 | .PHONY: clean 14 | clean: ## Clean binary file 15 | @echo "Cleaning binary..." 16 | @rm -rf bin 17 | 18 | guard-%: ## Checks that env var is set else exits with non 0 mainly used in CI; 19 | @if [ -z '${${*}}' ]; then echo 'Environment variable $* not set' && exit 1; fi 20 | 21 | .PHONY: build 22 | build: clean ## Compile go modules 23 | @echo "Compiling *.go..." 24 | @go build -o ./bin/auto_doc *.go 25 | 26 | .PHONY: run 27 | run: build guard-OUTPUT guard-FILENAME ## Execute binary 28 | @echo "Running auto doc..." 29 | @./bin/auto_doc --filename=$(FILENAME) --output=$(OUTPUT) 30 | @$(MAKE) clean 31 | 32 | .PHONY: run-help 33 | run-help: build guard-OUTPUT guard-FILENAME ## Execute binary 34 | @echo "Running auto doc help..." 35 | @echo "" 36 | @./bin/auto_doc --help 37 | @$(MAKE) clean 38 | 39 | upgrade-from-one-version-to-a-major-version: guard-OLD_VERSION guard-MAJOR_VERSION ## Upgrade from and old version to a major version 40 | @echo "Upgrading from v$(OLD_VERSION) to v$(MAJOR_VERSION)" 41 | @find . -type f \ 42 | -name '*.go' \ 43 | -exec sed -i '' -e 's,github.com/tj-actions/auto-doc/v$(OLD_VERSION),github.com/tj-actions/auto-doc/v$(MAJOR_VERSION),g' {} \; 44 | @find . -type f \ 45 | -name 'go.mod' \ 46 | -exec sed -i '' -e 's,github.com/tj-actions/auto-doc/v$(OLD_VERSION),github.com/tj-actions/auto-doc/v$(MAJOR_VERSION),g' {} \; 47 | @find . -type f \ 48 | -name 'README.md' \ 49 | -exec sed -i '' -e 's,github.com/tj-actions/auto-doc/v$(OLD_VERSION),github.com/tj-actions/auto-doc/v$(MAJOR_VERSION),g' {} \; 50 | 51 | .PHONY: test 52 | test: clean 53 | @go test ./cmd 54 | 55 | .PHONY: format 56 | format: ## Format go modules 57 | @go fmt ./... 58 | 59 | .PHONY: tidy 60 | tidy: ## Tidy go.mod 61 | @go mod tidy 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Ubuntu](https://img.shields.io/badge/Ubuntu-E95420?style=for-the-badge\&logo=ubuntu\&logoColor=white)](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on) 2 | [![Mac OS](https://img.shields.io/badge/mac%20os-000000?style=for-the-badge\&logo=macos\&logoColor=F0F0F0)](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on) 3 | [![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge\&logo=windows\&logoColor=white)](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on) 4 | [![Public workflows that use this action.](https://img.shields.io/endpoint?style=for-the-badge\&url=https%3A%2F%2Fused-by.vercel.app%2Fapi%2Fgithub-actions%2Fused-by%3Faction%3Dtj-actions%2Fauto-doc%26badge%3Dtrue%26package_id%3DUGFja2FnZS0yOTU3MDU0NDI1)](https://github.com/search?o=desc\&q=tj-actions+auto-doc+language%3AYAML\&s=\&type=Code) 5 | 6 | [![CI](https://github.com/tj-actions/auto-doc/workflows/CI/badge.svg)](https://github.com/tj-actions/auto-doc/actions?query=workflow%3ACI) 7 | ![Coverage](https://img.shields.io/badge/Coverage-84.9%25-brightgreen) 8 | [![Update release version.](https://github.com/tj-actions/auto-doc/workflows/Update%20release%20version./badge.svg)](https://github.com/tj-actions/auto-doc/actions?query=workflow%3A%22Update+release+version.%22) 9 | [![codecov](https://codecov.io/github/tj-actions/auto-doc/branch/main/graph/badge.svg?token=TNXW4QRRJD)](https://codecov.io/github/tj-actions/auto-doc) 10 | 11 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/2ca092c5436e4994b536b02ba6752436)](https://app.codacy.com/gh/tj-actions/auto-doc/dashboard?utm_source=gh\&utm_medium=referral\&utm_content=\&utm_campaign=Badge_grade) 12 | [![Go Report Card](https://goreportcard.com/badge/github.com/tj-actions/auto-doc)](https://goreportcard.com/report/github.com/tj-actions/auto-doc) 13 | [![Go Reference](https://pkg.go.dev/badge/github.com/tj-actions/auto-doc/v3.svg)](https://pkg.go.dev/github.com/tj-actions/auto-doc/v3) 14 | 15 | 16 | 17 | [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) 18 | 19 | 20 | 21 | ## auto-doc 22 | 23 | GitHub Action generates a beautiful, easy-to-read markdown table or YAML code block with just a few lines of code. Say goodbye to manual table creation or outdated YAML code blocks and hello to streamlined documentation that is always up-to-date. 24 | 25 | ## Features 26 | 27 | * Document your custom [Github action](https://docs.github.com/en/actions/creating-actions) using the `action.yml` file. 28 | * Document [reusable workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows) by specifying the filename. 29 | * Easy to understand markdown table of all inputs, outputs, and secrets. 30 | * Optional YAML code block for your `action.yml` file which includes all inputs. 31 | * Show deprecated inputs. 32 | * Fast and always up-to-date documentation. 33 | 34 | ## Table of Contents 35 | 36 | * [Usage](#usage) 37 | * [Supported Headings](#supported-headings) 38 | * [Example](#example) 39 | * [Inputs](#inputs) 40 | * [Example workflow](#example-workflow) 41 | * [CLI](#cli) 42 | * [Installation](#installation) 43 | * [Install using Go:](#install-using-go) 44 | * [Install using Homebrew:](#install-using-homebrew) 45 | * [Install using Chocolatey (Windows):](#install-using-chocolatey-windows) 46 | * [Synopsis](#synopsis) 47 | * [Flags](#flags) 48 | * [Credits](#credits) 49 | * [Report Bugs](#report-bugs) 50 | * [Contributors ✨](#contributors-) 51 | 52 | ## Usage 53 | 54 | Add any of the supported headings as a [`H2` header](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#headers) in any location of your markdown file. 55 | 56 | ### Supported Headings 57 | 58 | * `Inputs` 59 | * `Outputs` 60 | * `Secrets` (only supported by reusable workflows) 61 | * `Description` (only supported by actions) 62 | 63 | ### Example 64 | 65 | 1. Add one or more headings to your `README.md` 66 | 67 | > \[!NOTE] 68 | > This can be multiple headings supported by the input file 69 | 70 | ## Inputs 71 | 72 | 2\. Update your workflow 73 | 74 | ```yaml 75 | ... 76 | steps: 77 | - uses: actions/checkout@v4 78 | - name: Run auto-doc 79 | uses: tj-actions/auto-doc@v3 80 | ``` 81 | 82 | **👇 This was generated 👇 using 👉: [action.yml](./action.yml)** 83 | 84 | ## Inputs 85 | 86 | 87 | 88 | ```yaml 89 | - uses: tj-actions/auto-doc@v3 90 | id: auto-doc 91 | with: 92 | # Optionally pass a path to 93 | # the auto-doc binary 94 | # Type: string 95 | bin_path: '' 96 | 97 | # Max width of a column 98 | # Type: string 99 | # Default: "1000" 100 | col_max_width: '' 101 | 102 | # Max number of words per 103 | # line in a column 104 | # Type: string 105 | # Default: "5" 106 | col_max_words: '' 107 | 108 | # Path to the yaml file 109 | # Type: string 110 | # Default: "action.yml" 111 | filename: '' 112 | 113 | # List of action.yml **input** columns 114 | # names to display, default (display all columns) 115 | # Type: string 116 | input_columns: '' 117 | 118 | # Boolean indicating whether to output 119 | # input, output and secret names 120 | # as markdown links 121 | # Type: boolean 122 | # Default: "true" 123 | markdown_links: '' 124 | 125 | # Path to the output file 126 | # Type: string 127 | # Default: "README.md" 128 | output: '' 129 | 130 | # List of action.yml **output** column 131 | # names to display, default (display all columns) 132 | # Type: string 133 | output_columns: '' 134 | 135 | # Repository name with owner. For 136 | # example, tj-actions/auto-doc 137 | # Type: string 138 | # Default: "${{ github.repository }}" 139 | repository: '' 140 | 141 | # Boolean Indicating whether the file 142 | # is a reusable workflow 143 | # Type: string 144 | reusable: '' 145 | 146 | # List of reusable workflow **input** 147 | # column names to display, default 148 | # (display all columns) 149 | # Type: string 150 | reusable_input_columns: '' 151 | 152 | # List of reusable workflow **output** 153 | # column names to display, default 154 | # (display all columns) 155 | # Type: string 156 | reusable_output_columns: '' 157 | 158 | # List of reusable workflow **secret** 159 | # column names to display, default 160 | # (display all columns) 161 | # Type: string 162 | reusable_secret_columns: '' 163 | 164 | # GitHub token or Personal Access 165 | # Token used to fetch the 166 | # repository latest tag. 167 | # Type: string 168 | # Default: "${{ github.token }}" 169 | token: '' 170 | 171 | # Enable code block documentation 172 | # Type: boolean 173 | # Default: "false" 174 | use_code_blocks: '' 175 | 176 | # Use the major version of 177 | # the repository tag e.g v1.0.0 178 | # -> v1 179 | # Type: boolean 180 | # Default: "false" 181 | use_major_version: '' 182 | 183 | # Use the tag commit hash 184 | # as the version and add 185 | # a comment with the tag 186 | # name. Example: v1.0.0 -> 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t 187 | # // v1.0.0 or v1 188 | # Type: boolean 189 | # Default: "false" 190 | use_tag_commit_hash: '' 191 | 192 | # The version number to run 193 | # Type: string 194 | version: '' 195 | 196 | ``` 197 | 198 | 199 | 200 | **👆 This was generated 👆 using 👉 [action.yml](./action.yml)** 201 | 202 | ## Example workflow 203 | 204 | Create a pull request each time the action.yml inputs/outputs change 205 | 206 | ```yaml 207 | name: Update README.md with the latest actions.yml 208 | 209 | on: 210 | push: 211 | branches: 212 | - main 213 | 214 | jobs: 215 | update-doc: 216 | runs-on: ubuntu-latest 217 | steps: 218 | - name: Checkout 219 | uses: actions/checkout@v4 220 | with: 221 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo 222 | 223 | - name: Run auto-doc 224 | uses: tj-actions/auto-doc@v3 225 | 226 | - name: Verify Changed files 227 | uses: tj-actions/verify-changed-files@v8.6 228 | id: verify-changed-files 229 | with: 230 | files: | 231 | README.md 232 | 233 | - name: Create Pull Request 234 | if: steps.verify-changed-files.outputs.files_changed == 'true' 235 | uses: peter-evans/create-pull-request@v3 236 | with: 237 | base: "main" 238 | title: "auto-doc: Updated README.md" 239 | branch: "chore/auto-doc-update-readme" 240 | commit-message: "auto-doc: Updated README.md" 241 | body: "auto-doc: Updated README.md" 242 | ``` 243 | 244 | ## CLI 245 | 246 | ### Installation 247 | 248 | #### Install using Go: 249 | 250 | ```shell script 251 | go get -u github.com/tj-actions/auto-doc/v3 252 | ``` 253 | 254 | #### Install using Homebrew: 255 | 256 | ```shell script 257 | brew install tj-actions/tap/auto-doc 258 | ``` 259 | 260 | #### Install using Chocolatey (Windows): 261 | 262 | ```shell script 263 | choco install auto-doc 264 | ``` 265 | 266 | ### Synopsis 267 | 268 | Automatically generate documentation for your custom GitHub action or reusable workflow. 269 | 270 | auto-doc [flags] 271 | 272 | ### Flags 273 | 274 | --colMaxWidth string Max width of a column. (default "1000") 275 | --colMaxWords string Max number of words per line in a column. (default "6") 276 | -f, --filename string config file. 277 | -h, --help help for auto-doc 278 | --inputColumns stringArray list of input column names. (default [Input,Type,Required,Default,Description]) 279 | -m, --markdownLinks Names of inputs, outputs and secrets as markdown links. 280 | -o, --output string Output file. (default "README.md") 281 | --outputColumns stringArray list of output column names. (default [Output,Type,Description]) 282 | --repository string Repository name with owner. Example: tj-actions/auto-doc 283 | -r, --reusable A reusable workflow. 284 | --reusableInputColumns stringArray list of reusable input column names. (default [Input,Type,Required,Default,Description]) 285 | --reusableOutputColumns stringArray list of reusable output column names. (default [Output,Value,Description]) 286 | --reusableSecretColumns stringArray list of reusable secrets column names. (default [Secret,Required,Description]) 287 | --token string GitHub token or Personal Access Token used to fetch the repository latest tag. 288 | --useCodeBlocks Enable code block documentation. 289 | --useMajorVersion Use the major version of the repository tag. Example: v1.0.0 -> v Use the major version of the repository tag. e.g v1.0.0 -> v1 290 | 291 | * Free software: [Apache License 2.0](LICENSE) 292 | 293 | If you feel generous and want to show some extra appreciation: 294 | 295 | [![Buy me a coffee][buymeacoffee-shield]][buymeacoffee] 296 | 297 | [buymeacoffee]: https://www.buymeacoffee.com/jackton1 298 | 299 | [buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png 300 | 301 | ## Credits 302 | 303 | This package was created with [Cookiecutter](https://github.com/cookiecutter/cookiecutter) using [cookiecutter-action](https://github.com/tj-actions/cookiecutter-action) 304 | 305 | * [cobra](https://github.com/spf13/cobra) 306 | * [goreleaser](https://github.com/goreleaser/goreleaser/) 307 | 308 | ## Report Bugs 309 | 310 | Report bugs at https://github.com/tj-actions/auto-doc/issues. 311 | 312 | If you are reporting a bug, please include: 313 | 314 | * Your operating system name and version. 315 | * Any details about your workflow that might be helpful in troubleshooting. 316 | * Detailed steps to reproduce the bug. 317 | 318 | ## Contributors ✨ 319 | 320 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 |
Andreas Åman
Andreas Åman

💻 📖
Viacheslav Kudinov
Viacheslav Kudinov

💻 ⚠️
Christophe Furmaniak
Christophe Furmaniak

💻 ⚠️
Mike W
Mike W

💻 📖
338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 346 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: auto-doc 2 | description: Document your github action or reusable workflow with ease 3 | author: jackton1 4 | inputs: 5 | filename: 6 | description: 'Path to the yaml file' 7 | required: false 8 | default: action.yml 9 | col_max_width: 10 | description: 'Max width of a column' 11 | required: false 12 | default: '1000' 13 | col_max_words: 14 | description: 'Max number of words per line in a column' 15 | required: false 16 | default: '5' 17 | output: 18 | description: 'Path to the output file' 19 | required: false 20 | default: README.md 21 | bin_path: 22 | description: 'Optionally pass a path to the auto-doc binary' 23 | required: false 24 | input_columns: 25 | description: 'List of action.yml **input** columns names to display, default (display all columns)' 26 | required: false 27 | output_columns: 28 | description: 'List of action.yml **output** column names to display, default (display all columns)' 29 | required: false 30 | reusable_output_columns: 31 | description: 'List of reusable workflow **output** column names to display, default (display all columns)' 32 | required: false 33 | reusable_input_columns: 34 | description: 'List of reusable workflow **input** column names to display, default (display all columns)' 35 | required: false 36 | reusable_secret_columns: 37 | description: 'List of reusable workflow **secret** column names to display, default (display all columns)' 38 | required: false 39 | reusable: 40 | description: 'Boolean Indicating whether the file is a reusable workflow' 41 | required: false 42 | version: 43 | description: 'The version number to run' 44 | required: false 45 | markdown_links: 46 | description: 'Boolean indicating whether to output input, output and secret names as markdown links' 47 | required: false 48 | default: 'true' 49 | repository: 50 | description: 'Repository name with owner. For example, tj-actions/auto-doc' 51 | required: false 52 | default: ${{ github.repository }} 53 | token: 54 | description: 'GitHub token or Personal Access Token used to fetch the repository latest tag.' 55 | required: false 56 | default: ${{ github.token }} 57 | use_code_blocks: 58 | description: 'Enable code block documentation' 59 | required: false 60 | default: 'false' 61 | use_major_version: 62 | description: 'Use the major version of the repository tag e.g v1.0.0 -> v1' 63 | required: false 64 | default: 'false' 65 | use_tag_commit_hash: 66 | description: 'Use the tag commit hash as the version and add a comment with the tag name. Example: v1.0.0 -> 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t // v1.0.0 or v1' 67 | required: false 68 | default: 'false' 69 | 70 | 71 | runs: 72 | using: 'composite' 73 | steps: 74 | - name: Setup bin 75 | if: inputs.bin_path == '' 76 | uses: tj-actions/setup-bin@cc2f416f28163075dc4d67e8b298dcbe2ecf4d5a # v1 77 | id: setup-bin-go 78 | with: 79 | repository-owner: tj-actions 80 | repository: auto-doc 81 | version: v3.6.0 82 | language-type: 'go' 83 | - run: | 84 | bash $GITHUB_ACTION_PATH/entrypoint.sh 85 | id: autodoc 86 | shell: bash 87 | env: 88 | # INPUT_ is not available in Composite run steps 89 | # https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs 90 | INPUT_FILENAME: ${{ inputs.filename }} 91 | INPUT_COL_MAX_WIDTH: ${{ inputs.col_max_width }} 92 | INPUT_COL_MAX_WORDS: ${{ inputs.col_max_words }} 93 | INPUT_OUTPUT: ${{ inputs.output }} 94 | INPUT_BIN_PATH: ${{ inputs.bin_path || steps.setup-bin-go.outputs.binary_path }} 95 | INPUT_INPUT_COLUMNS: ${{ inputs.input_columns }} 96 | INPUT_OUTPUT_COLUMNS: ${{ inputs.output_columns }} 97 | INPUT_REUSABLE_OUTPUT_COLUMNS: ${{ inputs.reusable_output_columns }} 98 | INPUT_REUSABLE_INPUT_COLUMNS: ${{ inputs.reusable_input_columns }} 99 | INPUT_REUSABLE_SECRET_COLUMNS: ${{ inputs.reusable_secret_columns }} 100 | INPUT_REUSABLE: ${{ inputs.reusable }} 101 | INPUT_VERSION: ${{ inputs.version }} 102 | INPUT_MARKDOWN_LINKS: ${{ inputs.markdown_links }} 103 | INPUT_REPOSITORY: ${{ inputs.repository }} 104 | INPUT_TOKEN: ${{ inputs.token }} 105 | INPUT_USE_CODE_BLOCKS: ${{ inputs.use_code_blocks }} 106 | INPUT_USE_MAJOR_VERSION: ${{ inputs.use_major_version }} 107 | INPUT_USE_TAG_COMMIT_HASH: ${{ inputs.use_tag_commit_hash }} 108 | 109 | branding: 110 | icon: file-text 111 | color: white 112 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | // Package cmd provides a cli script that parses the GitHub action.yml and reusable workflow files and outputs a Markdown table to a specified path. 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package cmd 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/spf13/cobra" 23 | 24 | "github.com/tj-actions/auto-doc/v3/internal" 25 | "github.com/tj-actions/auto-doc/v3/internal/types" 26 | ) 27 | 28 | var fileName string 29 | var outputFileName string 30 | var colMaxWidth string 31 | var colMaxWords string 32 | var repository string 33 | var token string 34 | 35 | // action.yml 36 | var inputColumns []string 37 | var outputColumns []string 38 | 39 | // Reusable workflows 40 | var reusableInputColumns []string 41 | var reusableOutputColumns []string 42 | var reusableSecretColumns []string 43 | 44 | // rootCmd represents the base command when called without any subcommands 45 | var rootCmd = &cobra.Command{ 46 | Use: "auto-doc", 47 | Short: "Auto doc generator for your custom github action or reusable workflow", 48 | Long: "Automatically generate documentation for your custom github action or reusable workflow", 49 | RunE: RootCmdRunE, 50 | } 51 | 52 | // RootCmdRunE runs the root commands RunE function and handles invalid options and prints the help message 53 | // if the command is called with no arguments. 54 | func RootCmdRunE(cmd *cobra.Command, args []string) error { 55 | if len(args) > 0 { 56 | return fmt.Errorf("requires no positional arguments: %d given", len(args)) 57 | } 58 | 59 | if fileName == "" { 60 | return fmt.Errorf("filename must be specified with --filename") 61 | } 62 | 63 | reusable, err := cmd.Flags().GetBool("reusable") 64 | // coverage:ignore 65 | if err != nil { 66 | return err 67 | } 68 | 69 | markdownLinks, err := cmd.Flags().GetBool("markdownLinks") 70 | // coverage:ignore 71 | if err != nil { 72 | return err 73 | } 74 | 75 | useCodeBlocks, err := cmd.Flags().GetBool("useCodeBlocks") 76 | // coverage:ignore 77 | if err != nil { 78 | return err 79 | } 80 | 81 | useMajorVersion, err := cmd.Flags().GetBool("useMajorVersion") 82 | // coverage:ignore 83 | if err != nil { 84 | return err 85 | } 86 | 87 | useTagCommitHash, err := cmd.Flags().GetBool("useTagCommitHash") 88 | // coverage:ignore 89 | if err != nil { 90 | return err 91 | } 92 | 93 | if repository == "" && useCodeBlocks { 94 | return fmt.Errorf("repository must be specified with --repository") 95 | } 96 | 97 | var documentation types.Documentation 98 | 99 | if reusable { 100 | documentation = &types.Reusable{ 101 | InputFileName: fileName, 102 | OutputFileName: outputFileName, 103 | ColMaxWidth: colMaxWidth, 104 | ColMaxWords: colMaxWords, 105 | InputColumns: reusableInputColumns, 106 | OutputColumns: reusableOutputColumns, 107 | SecretColumns: reusableSecretColumns, 108 | InputMarkdownLinks: markdownLinks, 109 | } 110 | } else if useCodeBlocks { 111 | documentation = &types.CodeBlock{ 112 | Repository: repository, 113 | Token: token, 114 | UseMajorVersion: useMajorVersion, 115 | UseTagCommitHash: useTagCommitHash, 116 | InputFileName: fileName, 117 | OutputFileName: outputFileName, 118 | OutputColumns: outputColumns, 119 | ColMaxWidth: colMaxWidth, 120 | ColMaxWords: colMaxWords, 121 | InputMarkdownLinks: markdownLinks, 122 | } 123 | } else { 124 | documentation = &types.Action{ 125 | InputFileName: fileName, 126 | OutputFileName: outputFileName, 127 | ColMaxWidth: colMaxWidth, 128 | ColMaxWords: colMaxWords, 129 | InputColumns: inputColumns, 130 | OutputColumns: outputColumns, 131 | InputMarkdownLinks: markdownLinks, 132 | } 133 | } 134 | 135 | err = documentation.GetData() 136 | if err != nil { 137 | return err 138 | } 139 | 140 | err = documentation.RenderOutput() 141 | // coverage:ignore 142 | if err != nil { 143 | return err 144 | } 145 | 146 | _, err = fmt.Fprintln( 147 | cmd.OutOrStdout(), 148 | "Successfully generated documentation", 149 | ) 150 | 151 | return err 152 | } 153 | 154 | // Execute adds all child commands to the root command and sets flags appropriately. 155 | // This is called by main.main(). It only needs to happen once to the rootCmd. 156 | // coverage:ignore 157 | func Execute() { 158 | cobra.CheckErr(rootCmd.Execute()) 159 | } 160 | 161 | // RootCmdFlags adds the flags to the root command. 162 | func RootCmdFlags(cmd *cobra.Command) { 163 | // Custom flags 164 | cmd.Flags().StringVarP( 165 | &fileName, 166 | "filename", 167 | "f", 168 | "", 169 | "config file.", 170 | ) 171 | cmd.Flags().BoolP( 172 | "reusable", 173 | "r", 174 | false, 175 | "A reusable workflow.", 176 | ) 177 | cmd.Flags().StringVarP( 178 | &outputFileName, 179 | "output", 180 | "o", 181 | "README.md", 182 | "Output file.", 183 | ) 184 | cmd.Flags().StringVar( 185 | &colMaxWidth, 186 | "colMaxWidth", 187 | "1000", 188 | "Max width of a column.", 189 | ) 190 | cmd.Flags().StringVar( 191 | &colMaxWords, 192 | "colMaxWords", 193 | "6", 194 | "Max number of words per line in a column.", 195 | ) 196 | cmd.Flags().StringArrayVar( 197 | &inputColumns, 198 | "inputColumns", 199 | internal.DefaultActionInputColumns, 200 | "list of input column names.", 201 | ) 202 | cmd.Flags().StringArrayVar( 203 | &outputColumns, 204 | "outputColumns", 205 | internal.DefaultActionOutputColumns, 206 | "list of output column names.", 207 | ) 208 | cmd.Flags().StringArrayVar( 209 | &reusableInputColumns, 210 | "reusableInputColumns", 211 | internal.DefaultReusableInputColumns, 212 | "list of reusable input column names.", 213 | ) 214 | cmd.Flags().StringArrayVar( 215 | &reusableOutputColumns, 216 | "reusableOutputColumns", 217 | internal.DefaultReusableOutputColumns, 218 | "list of reusable output column names.", 219 | ) 220 | cmd.Flags().StringArrayVar( 221 | &reusableSecretColumns, 222 | "reusableSecretColumns", 223 | internal.DefaultReusableSecretColumns, 224 | "list of reusable secrets column names.", 225 | ) 226 | cmd.Flags().BoolP( 227 | "markdownLinks", 228 | "m", 229 | false, 230 | "Names of inputs, outputs and secrets as markdown links.", 231 | ) 232 | cmd.Flags().StringVar( 233 | &repository, 234 | "repository", 235 | "", 236 | "Repository name with owner. Example: tj-actions/auto-doc", 237 | ) 238 | cmd.Flags().StringVar( 239 | &token, 240 | "token", 241 | "", 242 | "GitHub token or Personal Access Token used to fetch the repository latest tag.", 243 | ) 244 | cmd.Flags().Bool( 245 | "useCodeBlocks", 246 | false, 247 | "Enable code block documentation.", 248 | ) 249 | cmd.Flags().Bool( 250 | "useMajorVersion", 251 | false, 252 | "Use the major version of the repository tag. Example: v1.0.0 -> v1", 253 | ) 254 | cmd.Flags().Bool( 255 | "useTagCommitHash", 256 | false, 257 | "Use the tag commit hash as the version and add a comment with the tag name. Example: v1.0.0 -> 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t // v1.0.0 or v1", 258 | ) 259 | } 260 | 261 | func init() { 262 | RootCmdFlags(rootCmd) 263 | } 264 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | EXTRA_ARGS="" 5 | BIN_PATH="$INPUT_BIN_PATH" 6 | REUSABLE="$INPUT_REUSABLE" 7 | VERSION="$INPUT_VERSION" 8 | 9 | # action.yml file 10 | IFS=$'\n' read -rd '' -a INPUT_COLUMNS <<<"$INPUT_INPUT_COLUMNS" || true 11 | 12 | if [[ ${#INPUT_COLUMNS[@]} -gt 0 ]]; then 13 | for input_column in "${INPUT_COLUMNS[@]}"; do 14 | EXTRA_ARGS="${EXTRA_ARGS} --inputColumns=${input_column}" 15 | done 16 | fi 17 | 18 | IFS=$'\n' read -rd '' -a OUTPUT_COLUMNS <<<"$INPUT_OUTPUT_COLUMNS" || true 19 | 20 | if [[ ${#OUTPUT_COLUMNS[@]} -gt 0 ]]; then 21 | for output_column in "${OUTPUT_COLUMNS[@]}"; do 22 | EXTRA_ARGS="${EXTRA_ARGS} --outputColumns=${output_column}" 23 | done 24 | fi 25 | 26 | # reusable workflow 27 | IFS=$'\n' read -rd '' -a REUSABLE_SECRET_COLUMNS <<<"$INPUT_REUSABLE_SECRET_COLUMNS" || true 28 | 29 | if [[ ${#REUSABLE_SECRET_COLUMNS[@]} -gt 0 ]]; then 30 | for reusable_secret_column in "${REUSABLE_SECRET_COLUMNS[@]}"; do 31 | EXTRA_ARGS="${EXTRA_ARGS} --reusableSecretColumns=${reusable_secret_column}" 32 | done 33 | fi 34 | 35 | IFS=$'\n' read -rd '' -a REUSABLE_INPUT_COLUMNS <<<"$INPUT_REUSABLE_INPUT_COLUMNS" || true 36 | 37 | if [[ ${#REUSABLE_INPUT_COLUMNS[@]} -gt 0 ]]; then 38 | for reusable_input_column in "${REUSABLE_INPUT_COLUMNS[@]}"; do 39 | EXTRA_ARGS="${EXTRA_ARGS} --reusableInputColumns=${reusable_input_column}" 40 | done 41 | fi 42 | 43 | IFS=$'\n' read -rd '' -a REUSABLE_OUTPUT_COLUMNS <<<"$INPUT_REUSABLE_OUTPUT_COLUMNS" || true 44 | 45 | if [[ ${#REUSABLE_OUTPUT_COLUMNS[@]} -gt 0 ]]; then 46 | for reusable_output_column in "${REUSABLE_OUTPUT_COLUMNS[@]}"; do 47 | EXTRA_ARGS="${EXTRA_ARGS} --reusableOutputColumns=${reusable_output_column}" 48 | done 49 | fi 50 | 51 | if [[ ! -f "$INPUT_FILENAME" ]]; then 52 | echo "::warning::No file found at: $INPUT_FILENAME" 53 | exit 0 54 | fi 55 | 56 | if [[ ! -f "$BIN_PATH" ]]; then 57 | echo "::error::No binary found at: $BIN_PATH" 58 | exit 1 59 | fi 60 | 61 | # reusable workflow 62 | if [[ "$REUSABLE" == "true" ]]; then 63 | EXTRA_ARGS="${EXTRA_ARGS} --reusable" 64 | fi 65 | 66 | # markdown links 67 | if [[ "$INPUT_MARKDOWN_LINKS" == "true" ]]; then 68 | EXTRA_ARGS="${EXTRA_ARGS} --markdownLinks" 69 | fi 70 | 71 | # repository 72 | if [[ -n "$INPUT_REPOSITORY" ]]; then 73 | EXTRA_ARGS="${EXTRA_ARGS} --repository=${INPUT_REPOSITORY}" 74 | fi 75 | 76 | # token 77 | if [[ -n "$INPUT_TOKEN" ]]; then 78 | EXTRA_ARGS="${EXTRA_ARGS} --token=${INPUT_TOKEN}" 79 | fi 80 | 81 | # use_code_blocks 82 | if [[ "$INPUT_USE_CODE_BLOCKS" == "true" ]]; then 83 | EXTRA_ARGS="${EXTRA_ARGS} --useCodeBlocks" 84 | fi 85 | 86 | # use_major_version 87 | if [[ "$INPUT_USE_MAJOR_VERSION" == "true" ]]; then 88 | EXTRA_ARGS="${EXTRA_ARGS} --useMajorVersion" 89 | fi 90 | 91 | # use_tag_commit_hash 92 | if [[ "$INPUT_USE_TAG_COMMIT_HASH" == "true" ]]; then 93 | EXTRA_ARGS="${EXTRA_ARGS} --useTagCommitHash" 94 | fi 95 | 96 | echo "::debug::Generating documentation using ${BIN_PATH}..." 97 | echo "::debug::Extra args: ${EXTRA_ARGS}" 98 | 99 | # shellcheck disable=SC2086 100 | $BIN_PATH --filename="$INPUT_FILENAME" --output="$INPUT_OUTPUT" \ 101 | --colMaxWidth="$INPUT_COL_MAX_WIDTH" --colMaxWords="$INPUT_COL_MAX_WORDS" \ 102 | ${EXTRA_ARGS} && exit_status=$? || exit_status=$? 103 | 104 | if [[ $exit_status -ne 0 ]]; then 105 | echo "::warning::Error occurred running auto-doc" 106 | exit "$exit_status"; 107 | fi 108 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tj-actions/auto-doc/v3 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/olekukonko/tablewriter v0.0.5 7 | github.com/spf13/cobra v1.9.1 8 | gopkg.in/yaml.v3 v3.0.1 9 | ) 10 | 11 | require ( 12 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 13 | github.com/kr/pretty v0.3.1 // indirect 14 | github.com/mattn/go-runewidth v0.0.15 // indirect 15 | github.com/rivo/uniseg v0.4.4 // indirect 16 | github.com/rogpeppe/go-internal v1.11.0 // indirect 17 | github.com/spf13/pflag v1.0.6 // indirect 18 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 2 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 3 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 4 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 5 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 6 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 7 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 8 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 9 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 10 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 11 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 12 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 13 | github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= 14 | github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 15 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= 16 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 17 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 18 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 19 | github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= 20 | github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 21 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 22 | github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= 23 | github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= 24 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 25 | github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= 26 | github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= 27 | github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= 28 | github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 29 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 30 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 31 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 32 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 33 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 34 | -------------------------------------------------------------------------------- /internal/constants.go: -------------------------------------------------------------------------------- 1 | // Package internal contains all internal packages and utility functions. 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package internal 18 | 19 | import "fmt" 20 | 21 | // DescriptionHeader represents the markdown header of description 22 | const DescriptionHeader = "## Description" 23 | 24 | // InputsHeader represents the markdown header of inputs 25 | const InputsHeader = "## Inputs" 26 | 27 | // OutputsHeader represents the markdown header of outputs 28 | const OutputsHeader = "## Outputs" 29 | 30 | // SecretsHeader represents the markdown header of secrets 31 | const SecretsHeader = "## Secrets" 32 | 33 | // AutoDocStart placeholder that represents the start of the input table 34 | const AutoDocStart = "" 35 | 36 | // AutoDocEnd placeholder that represents the end of the input table 37 | const AutoDocEnd = "" 38 | 39 | // PipeSeparator represents the separator used for the distinguishing between columns 40 | const PipeSeparator = "|" 41 | 42 | // NewLineSeparator used for splitting lines 43 | const NewLineSeparator = "\n" 44 | 45 | // DescriptionAutoDocStart is the start of the description 46 | var DescriptionAutoDocStart = fmt.Sprintf(AutoDocStart, "DESCRIPTION") 47 | 48 | // DescriptionAutoDocEnd is the end of the description 49 | var DescriptionAutoDocEnd = fmt.Sprintf(AutoDocEnd, "DESCRIPTION") 50 | 51 | // InputAutoDocStart is the start of the input 52 | var InputAutoDocStart = fmt.Sprintf(AutoDocStart, "INPUT") 53 | 54 | // InputAutoDocEnd is the end of the input 55 | var InputAutoDocEnd = fmt.Sprintf(AutoDocEnd, "INPUT") 56 | 57 | // NoInputsMessage is the message printed when there are no inputs 58 | var NoInputsMessage = "No inputs." 59 | 60 | // OutputAutoDocStart is the start of the output 61 | var OutputAutoDocStart = fmt.Sprintf(AutoDocStart, "OUTPUT") 62 | 63 | // OutputAutoDocEnd is the end of the output 64 | var OutputAutoDocEnd = fmt.Sprintf(AutoDocEnd, "OUTPUT") 65 | 66 | // NoOutputsMessage is the message printed when there are no outputs 67 | var NoOutputsMessage = "No outputs." 68 | 69 | // SecretsAutoDocStart is the start of the secrets 70 | var SecretsAutoDocStart = fmt.Sprintf(AutoDocStart, "SECRETS") 71 | 72 | // SecretsAutoDocEnd is the end of the secrets 73 | var SecretsAutoDocEnd = fmt.Sprintf(AutoDocEnd, "SECRETS") 74 | 75 | // NoSecretsMessage is the message printed when there are no secrets 76 | var NoSecretsMessage = "No secrets." 77 | 78 | // action.yml 79 | 80 | // DefaultActionInputColumns default values 81 | var DefaultActionInputColumns = []string{"Input", "Type", "Required", "Default", "Description"} 82 | 83 | // DefaultActionOutputColumns default values 84 | var DefaultActionOutputColumns = []string{"Output", "Type", "Description"} 85 | 86 | // Reusable workflows 87 | 88 | // DefaultReusableSecretColumns default values 89 | var DefaultReusableSecretColumns = []string{"Secret", "Required", "Description"} 90 | 91 | // DefaultReusableOutputColumns default values 92 | var DefaultReusableOutputColumns = []string{"Output", "Value", "Description"} 93 | 94 | // DefaultReusableInputColumns default values 95 | var DefaultReusableInputColumns = []string{"Input", "Type", "Required", "Default", "Description"} 96 | -------------------------------------------------------------------------------- /internal/types/action.go: -------------------------------------------------------------------------------- 1 | //Package types contains all defined types 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package types 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "os" 23 | "regexp" 24 | "sort" 25 | "strconv" 26 | "strings" 27 | 28 | "github.com/olekukonko/tablewriter" 29 | "github.com/spf13/cobra" 30 | "gopkg.in/yaml.v3" 31 | 32 | "github.com/tj-actions/auto-doc/v3/internal" 33 | "github.com/tj-actions/auto-doc/v3/internal/utils" 34 | ) 35 | 36 | // ActionInput represents the input of the action.yml 37 | type ActionInput struct { 38 | Description string `yaml:"description"` 39 | Required bool `yaml:"required"` 40 | Default string `yaml:"default,omitempty"` 41 | DeprecationMessage string `yaml:"deprecationMessage,omitempty"` 42 | } 43 | 44 | // ActionOutput represents the output of the action.yml 45 | type ActionOutput struct { 46 | Description string `yaml:"description"` 47 | Value string `yaml:"default,omitempty"` 48 | } 49 | 50 | // Action represents the action.yml 51 | type Action struct { 52 | InputFileName string 53 | OutputFileName string 54 | ColMaxWidth string 55 | ColMaxWords string 56 | InputColumns []string 57 | OutputColumns []string 58 | Inputs map[string]ActionInput `yaml:"inputs,omitempty"` 59 | Outputs map[string]ActionOutput `yaml:"outputs,omitempty"` 60 | Description string `yaml:"description,omitempty"` 61 | InputMarkdownLinks bool 62 | } 63 | 64 | // GetData parses the source yaml file 65 | func (a *Action) GetData() error { 66 | actionYaml, err := os.ReadFile(a.InputFileName) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | err = yaml.Unmarshal(actionYaml, &a) 72 | return err 73 | } 74 | 75 | // WriteDocumentation write the table to the output file 76 | func (a *Action) WriteDocumentation(inputTable, outputTable, description *strings.Builder) error { 77 | var err error 78 | input, err := os.ReadFile(a.OutputFileName) 79 | if err != nil { 80 | return err 81 | } 82 | 83 | var output []byte 84 | 85 | hasDescriptionData, indices := utils.HasBytesInBetween( 86 | input, 87 | []byte(internal.DescriptionAutoDocStart), 88 | []byte(internal.DescriptionAutoDocEnd), 89 | ) 90 | output = input 91 | 92 | descriptionStr := strings.TrimSpace(description.String()) 93 | 94 | if hasDescriptionData { 95 | output = utils.ReplaceBytesInBetween(output, indices, []byte(descriptionStr)) 96 | } else { 97 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.DescriptionHeader)) 98 | output = re.ReplaceAllFunc(input, func(match []byte) []byte { 99 | if bytes.HasPrefix(match, []byte(internal.DescriptionHeader)) { 100 | if descriptionStr != "" { 101 | return []byte(fmt.Sprintf("%s\n\n%v", internal.DescriptionHeader, descriptionStr)) 102 | } 103 | return []byte(internal.DescriptionHeader) 104 | } 105 | return match 106 | }) 107 | } 108 | 109 | hasInputsData, indices := utils.HasBytesInBetween( 110 | output, 111 | []byte(internal.InputAutoDocStart), 112 | []byte(internal.InputAutoDocEnd), 113 | ) 114 | 115 | inputsStr := strings.TrimSpace(inputTable.String()) 116 | 117 | if hasInputsData { 118 | output = utils.ReplaceBytesInBetween(output, indices, []byte(inputsStr)) 119 | } else { 120 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.InputsHeader)) 121 | output = re.ReplaceAllFunc(input, func(match []byte) []byte { 122 | if bytes.HasPrefix(match, []byte(internal.InputsHeader)) { 123 | if inputsStr != "" { 124 | return []byte(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputsStr)) 125 | } else { 126 | return []byte(internal.InputsHeader) 127 | } 128 | } 129 | return match 130 | }) 131 | } 132 | hasOutputsData, indices := utils.HasBytesInBetween( 133 | output, 134 | []byte(internal.OutputAutoDocStart), 135 | []byte(internal.OutputAutoDocEnd), 136 | ) 137 | 138 | outputsStr := strings.TrimSpace(outputTable.String()) 139 | 140 | if hasOutputsData { 141 | output = utils.ReplaceBytesInBetween(output, indices, []byte(outputsStr)) 142 | } else { 143 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader)) 144 | output = re.ReplaceAllFunc(output, func(match []byte) []byte { 145 | if bytes.HasPrefix(match, []byte(internal.OutputsHeader)) { 146 | if outputsStr != "" { 147 | return []byte(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputsStr)) 148 | } else { 149 | return []byte(internal.OutputsHeader) 150 | } 151 | } 152 | return match 153 | }) 154 | } 155 | 156 | if err = os.WriteFile(a.OutputFileName, output, 0o666); err != nil { 157 | cobra.CheckErr(err) 158 | } 159 | 160 | return nil 161 | } 162 | 163 | // RenderOutput renders the output and writes it to the given output 164 | func (a *Action) RenderOutput() error { 165 | var err error 166 | maxWidth, err := strconv.Atoi(a.ColMaxWidth) 167 | if err != nil { 168 | return err 169 | } 170 | 171 | maxWords, err := strconv.Atoi(a.ColMaxWords) 172 | if err != nil { 173 | return err 174 | } 175 | 176 | descriptionOutput, err := renderDescription(a.Description) 177 | if err != nil { 178 | return err 179 | } 180 | 181 | inputTableOutput, err := renderActionInputTableOutput(a.Inputs, a.InputColumns, a.InputMarkdownLinks, maxWidth, maxWords) 182 | if err != nil { 183 | return err 184 | } 185 | 186 | outputTableOutput, err := renderActionOutputTableOutput(a.Outputs, a.OutputColumns, a.InputMarkdownLinks, maxWidth, maxWords) 187 | if err != nil { 188 | return err 189 | } 190 | 191 | err = a.WriteDocumentation(inputTableOutput, outputTableOutput, descriptionOutput) 192 | if err != nil { 193 | return err 194 | } 195 | 196 | return nil 197 | } 198 | 199 | // renderDescription renders the description 200 | func renderDescription(description string) (*strings.Builder, error) { 201 | descriptionOutput := &strings.Builder{} 202 | _, err := fmt.Fprintln(descriptionOutput, internal.DescriptionAutoDocStart) 203 | if err != nil { 204 | return descriptionOutput, err 205 | } 206 | 207 | _, err = fmt.Fprintln(descriptionOutput) 208 | if err != nil { 209 | return descriptionOutput, err 210 | } 211 | descriptionOutput.WriteString(description) 212 | descriptionOutput.WriteString("\n\n") 213 | 214 | _, err = fmt.Fprint(descriptionOutput, internal.DescriptionAutoDocEnd) 215 | if err != nil { 216 | return descriptionOutput, err 217 | } 218 | return descriptionOutput, nil 219 | } 220 | 221 | // renderActionOutputTableOutput renders the action input table 222 | 223 | func renderActionInputTableOutput(inputs map[string]ActionInput, inputColumns []string, markdownLinks bool, maxWidth int, maxWords int) (*strings.Builder, error) { 224 | inputTableOutput := &strings.Builder{} 225 | 226 | _, err := fmt.Fprintln(inputTableOutput, internal.InputAutoDocStart) 227 | if err != nil { 228 | return inputTableOutput, err 229 | } 230 | 231 | if len(inputs) > 0 { 232 | inputTable := tablewriter.NewWriter(inputTableOutput) 233 | inputTable.SetHeader(inputColumns) 234 | inputTable.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) 235 | inputTable.SetCenterSeparator(internal.PipeSeparator) 236 | inputTable.SetAlignment(tablewriter.ALIGN_CENTER) 237 | 238 | keys := make([]string, 0, len(inputs)) 239 | for k := range inputs { 240 | keys = append(keys, k) 241 | } 242 | sort.Strings(keys) 243 | 244 | inputTable.SetColWidth(maxWidth) 245 | 246 | for _, key := range keys { 247 | var row []string 248 | inputKey := key 249 | 250 | if markdownLinks { 251 | inputKey = utils.MarkdownLink(inputKey, "input") 252 | } 253 | 254 | for _, col := range inputColumns { 255 | switch col { 256 | case "Input": 257 | if inputs[key].DeprecationMessage != "" { 258 | row = append(row, fmt.Sprintf("~~%s~~
%s", inputKey, inputs[key].DeprecationMessage)) 259 | } else { 260 | row = append(row, inputKey) 261 | } 262 | case "Type": 263 | row = append(row, "string") 264 | case "Required": 265 | row = append(row, strconv.FormatBool(inputs[key].Required)) 266 | case "Default": 267 | row = append(row, utils.FormatValue(inputs[key].Default, true, "
")) 268 | case "Description": 269 | if inputs[key].DeprecationMessage != "" { 270 | row = append(row, utils.WordWrap(fmt.Sprintf("**Deprecated:** %s", inputs[key].Description), maxWords, "
")) 271 | } else { 272 | row = append(row, utils.WordWrap(inputs[key].Description, maxWords, "
")) 273 | } 274 | default: 275 | return inputTableOutput, fmt.Errorf( 276 | "unknown inputs column: '%s'. Please specify any of the following columns: %s", 277 | col, 278 | strings.Join(internal.DefaultActionInputColumns, ", "), 279 | ) 280 | } 281 | } 282 | inputTable.Append(row) 283 | } 284 | 285 | _, err = fmt.Fprintln(inputTableOutput) 286 | if err != nil { 287 | return inputTableOutput, err 288 | } 289 | 290 | inputTable.Render() 291 | 292 | _, err = fmt.Fprintln(inputTableOutput) 293 | if err != nil { 294 | return inputTableOutput, err 295 | } 296 | 297 | } else { 298 | _, err := fmt.Fprintln(inputTableOutput, internal.NoInputsMessage) 299 | if err != nil { 300 | return inputTableOutput, err 301 | } 302 | } 303 | _, err = fmt.Fprint(inputTableOutput, internal.InputAutoDocEnd) 304 | if err != nil { 305 | return inputTableOutput, err 306 | } 307 | return inputTableOutput, nil 308 | } 309 | 310 | // renderActionOutputTableOutput renders the action output table 311 | func renderActionOutputTableOutput(outputs map[string]ActionOutput, outputColumns []string, markdownLinks bool, maxWidth int, maxWords int) (*strings.Builder, error) { 312 | outputTableOutput := &strings.Builder{} 313 | 314 | _, err := fmt.Fprintln(outputTableOutput, internal.OutputAutoDocStart) 315 | if err != nil { 316 | return outputTableOutput, err 317 | } 318 | 319 | if len(outputs) > 0 { 320 | outputTable := tablewriter.NewWriter(outputTableOutput) 321 | outputTable.SetHeader(outputColumns) 322 | outputTable.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) 323 | outputTable.SetCenterSeparator(internal.PipeSeparator) 324 | outputTable.SetAlignment(tablewriter.ALIGN_CENTER) 325 | 326 | keys := make([]string, 0, len(outputs)) 327 | for k := range outputs { 328 | keys = append(keys, k) 329 | } 330 | sort.Strings(keys) 331 | 332 | outputTable.SetColWidth(maxWidth) 333 | for _, key := range keys { 334 | var row []string 335 | outputKey := key 336 | 337 | if markdownLinks { 338 | outputKey = utils.MarkdownLink(outputKey, "output") 339 | } 340 | 341 | for _, col := range outputColumns { 342 | switch col { 343 | case "Output": 344 | row = append(row, outputKey) 345 | case "Type": 346 | row = append(row, "string") 347 | case "Description": 348 | row = append(row, utils.WordWrap(outputs[key].Description, maxWords, "
")) 349 | default: 350 | return outputTableOutput, fmt.Errorf( 351 | "unknown outputs column: '%s'. Please specify any of the following columns: %s", 352 | col, 353 | strings.Join(internal.DefaultActionOutputColumns, ", "), 354 | ) 355 | } 356 | } 357 | outputTable.Append(row) 358 | } 359 | 360 | _, err = fmt.Fprintln(outputTableOutput) 361 | if err != nil { 362 | return outputTableOutput, err 363 | } 364 | outputTable.Render() 365 | 366 | _, err = fmt.Fprintln(outputTableOutput) 367 | if err != nil { 368 | return outputTableOutput, err 369 | } 370 | } else { 371 | _, err = fmt.Fprintln(outputTableOutput, internal.NoOutputsMessage) 372 | if err != nil { 373 | return outputTableOutput, err 374 | } 375 | } 376 | 377 | _, err = fmt.Fprint(outputTableOutput, internal.OutputAutoDocEnd) 378 | if err != nil { 379 | return outputTableOutput, err 380 | } 381 | 382 | return outputTableOutput, nil 383 | } 384 | -------------------------------------------------------------------------------- /internal/types/code_block.go: -------------------------------------------------------------------------------- 1 | //Package types contains all defined types 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package types 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "os" 23 | "regexp" 24 | "sort" 25 | "strconv" 26 | "strings" 27 | 28 | "github.com/spf13/cobra" 29 | "gopkg.in/yaml.v3" 30 | 31 | "github.com/tj-actions/auto-doc/v3/internal" 32 | "github.com/tj-actions/auto-doc/v3/internal/utils" 33 | ) 34 | 35 | // CodeBlock represents the action.yml outputted as a code block 36 | type CodeBlock struct { 37 | Repository string 38 | Token string 39 | UseMajorVersion bool 40 | UseTagCommitHash bool 41 | OutputColumns []string 42 | InputMarkdownLinks bool 43 | ColMaxWidth string 44 | ColMaxWords string 45 | InputFileName string 46 | OutputFileName string 47 | Inputs map[string]ActionInput `yaml:"inputs,omitempty"` 48 | Outputs map[string]ActionOutput `yaml:"outputs,omitempty"` 49 | } 50 | 51 | // GetData parses the source yaml file 52 | func (c *CodeBlock) GetData() error { 53 | actionYaml, err := os.ReadFile(c.InputFileName) 54 | // coverage:ignore 55 | if err != nil { 56 | return err 57 | } 58 | 59 | err = yaml.Unmarshal(actionYaml, &c) 60 | return err 61 | } 62 | 63 | // writeDocumentation write the table to the output file 64 | func (c *CodeBlock) writeDocumentation(inputCodeBlock, outputTableOutput *strings.Builder) error { 65 | var err error 66 | input, err := os.ReadFile(c.OutputFileName) 67 | // coverage:ignore 68 | if err != nil { 69 | return err 70 | } 71 | 72 | var output []byte 73 | 74 | hasInputsData, indices := utils.HasBytesInBetween( 75 | input, 76 | []byte(internal.InputAutoDocStart), 77 | []byte(internal.InputAutoDocEnd), 78 | ) 79 | 80 | output = input 81 | inputCodeBlockStr := strings.TrimSpace(inputCodeBlock.String()) 82 | 83 | if hasInputsData { 84 | output = utils.ReplaceBytesInBetween(output, indices, []byte(inputCodeBlockStr)) 85 | } else { 86 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.InputsHeader)) 87 | output = re.ReplaceAllFunc(input, func(match []byte) []byte { 88 | if bytes.HasPrefix(match, []byte(internal.InputsHeader)) { 89 | if inputCodeBlockStr != "" { 90 | return []byte(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputCodeBlockStr)) 91 | } else { 92 | return []byte(internal.InputsHeader) 93 | } 94 | } 95 | return match 96 | }) 97 | } 98 | 99 | hasOutputsData, indices := utils.HasBytesInBetween( 100 | output, 101 | []byte(internal.OutputAutoDocStart), 102 | []byte(internal.OutputAutoDocEnd), 103 | ) 104 | 105 | outputTableOutputStr := strings.TrimSpace(outputTableOutput.String()) 106 | 107 | if hasOutputsData { 108 | output = utils.ReplaceBytesInBetween(output, indices, []byte(outputTableOutputStr)) 109 | } else { 110 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader)) 111 | output = re.ReplaceAllFunc(output, func(match []byte) []byte { 112 | if bytes.HasPrefix(match, []byte(internal.OutputsHeader)) { 113 | if outputTableOutputStr != "" { 114 | return []byte(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputTableOutputStr)) 115 | } else { 116 | return []byte(internal.OutputsHeader) 117 | } 118 | } 119 | return match 120 | }) 121 | } 122 | 123 | if err = os.WriteFile(c.OutputFileName, output, 0o666); err != nil { 124 | cobra.CheckErr(err) 125 | } 126 | 127 | return nil 128 | } 129 | 130 | // getLatestTagForRepository returns the latest tag of a repository 131 | func (c *CodeBlock) getLatestTagForRepository() (string, error) { 132 | fmt.Println("Downloading the latest release") 133 | 134 | tag, err := utils.GetLatestRepositoryTag(c.Repository, c.Token, c.UseMajorVersion, c.UseTagCommitHash) 135 | // coverage:ignore 136 | if err != nil { 137 | return "", err 138 | } 139 | 140 | return tag, nil 141 | } 142 | 143 | // renderCodeBlockActionInputs renders the inputs as a code block 144 | func renderCodeBlockActionInputs(inputs map[string]ActionInput, repository, tag string, maxWords int) (*strings.Builder, error) { 145 | // Output this as a code block 146 | codeBlock := &strings.Builder{} 147 | 148 | _, err := fmt.Fprintln(codeBlock, internal.InputAutoDocStart) 149 | // coverage:ignore 150 | if err != nil { 151 | return codeBlock, err 152 | } 153 | 154 | keys := make([]string, 0, len(inputs)) 155 | for k := range inputs { 156 | keys = append(keys, k) 157 | } 158 | sort.Strings(keys) 159 | 160 | if len(keys) > 0 { 161 | codeBlock.WriteString("```yaml\n") 162 | codeBlock.WriteString(fmt.Sprintf("- uses: %s@%s\n", repository, tag)) 163 | codeBlock.WriteString(fmt.Sprintf(" id: %s\n", strings.Split(repository, "/")[1])) 164 | codeBlock.WriteString(" with:\n") 165 | 166 | for _, key := range keys { 167 | codeBlock.WriteString(fmt.Sprintf(" # %s\n", utils.WordWrap(inputs[key].Description, maxWords, "\n # "))) 168 | if inputs[key].Default == "false" || inputs[key].Default == "true" { 169 | codeBlock.WriteString(" # Type: boolean\n") 170 | } else { 171 | codeBlock.WriteString(" # Type: string\n") 172 | } 173 | if inputs[key].Default != "" { 174 | codeBlock.WriteString(fmt.Sprintf(" # Default: %s\n", utils.FormatValue(inputs[key].Default, false, "\n # "))) 175 | } 176 | if inputs[key].DeprecationMessage != "" { 177 | codeBlock.WriteString(fmt.Sprintf(" # Deprecated: %s\n", inputs[key].DeprecationMessage)) 178 | } 179 | codeBlock.WriteString(fmt.Sprintf(" %s: ''\n", key)) 180 | codeBlock.WriteString("\n") 181 | } 182 | codeBlock.WriteString("```\n") 183 | } else { 184 | _, err := fmt.Fprintln(codeBlock, internal.NoInputsMessage) 185 | if err != nil { 186 | return codeBlock, err 187 | } 188 | } 189 | 190 | _, err = fmt.Fprintln(codeBlock, internal.InputAutoDocEnd) 191 | // coverage:ignore 192 | if err != nil { 193 | return codeBlock, err 194 | } 195 | 196 | return codeBlock, nil 197 | } 198 | 199 | // RenderOutput renders the output and writes it to the given output 200 | func (c *CodeBlock) RenderOutput() error { 201 | maxWidth, err := strconv.Atoi(c.ColMaxWidth) 202 | if err != nil { 203 | return err 204 | } 205 | 206 | maxWords, err := strconv.Atoi(c.ColMaxWords) 207 | if err != nil { 208 | return err 209 | } 210 | 211 | tag, err := c.getLatestTagForRepository() 212 | // coverage:ignore 213 | if err != nil { 214 | return err 215 | } 216 | 217 | inputCodeBlockOutput, err := renderCodeBlockActionInputs(c.Inputs, c.Repository, tag, maxWords) 218 | 219 | // coverage:ignore 220 | if err != nil { 221 | return err 222 | } 223 | 224 | outputTableOutput, err := renderActionOutputTableOutput(c.Outputs, c.OutputColumns, c.InputMarkdownLinks, maxWidth, maxWords) 225 | if err != nil { 226 | return err 227 | } 228 | 229 | err = c.writeDocumentation(inputCodeBlockOutput, outputTableOutput) 230 | // coverage:ignore 231 | if err != nil { 232 | return err 233 | } 234 | 235 | return nil 236 | } 237 | -------------------------------------------------------------------------------- /internal/types/documentation.go: -------------------------------------------------------------------------------- 1 | //Package types contains all defined types 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package types 18 | 19 | // Documentation is the interface for Action, Reusable and CodeBlock 20 | type Documentation interface { 21 | GetData() error 22 | RenderOutput() error 23 | } 24 | -------------------------------------------------------------------------------- /internal/types/reusable.go: -------------------------------------------------------------------------------- 1 | //Package types contains all defined types 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package types 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "os" 23 | "regexp" 24 | "sort" 25 | "strconv" 26 | "strings" 27 | 28 | "github.com/olekukonko/tablewriter" 29 | "github.com/spf13/cobra" 30 | "gopkg.in/yaml.v3" 31 | 32 | "github.com/tj-actions/auto-doc/v3/internal" 33 | "github.com/tj-actions/auto-doc/v3/internal/utils" 34 | ) 35 | 36 | // ReusableInput represents the input of the reusable workflow 37 | type ReusableInput struct { 38 | Description string `yaml:"description"` 39 | Required bool `yaml:"required"` 40 | Default string `yaml:"default,omitempty"` 41 | Type string `yaml:"type"` 42 | DeprecationMessage string `yaml:"deprecationMessage,omitempty"` 43 | } 44 | 45 | // ReusableOutput represents the output of the reusable workflow 46 | type ReusableOutput struct { 47 | Description string `yaml:"description"` 48 | Value string `yaml:"value"` 49 | } 50 | 51 | // ReusableSecret represents the secret of reusable workflows 52 | type ReusableSecret struct { 53 | Required bool `yaml:"required"` 54 | Description string `yaml:"description"` 55 | } 56 | 57 | // Reusable represents a reusable workflow 58 | type Reusable struct { 59 | InputFileName string 60 | OutputFileName string 61 | ColMaxWidth string 62 | ColMaxWords string 63 | InputColumns []string 64 | OutputColumns []string 65 | SecretColumns []string 66 | On struct { 67 | WorkflowCall struct { 68 | Inputs map[string]ReusableInput `yaml:"inputs,omitempty"` 69 | Secrets map[string]ReusableSecret `yaml:"secrets,omitempty"` 70 | Outputs map[string]ReusableOutput `yaml:"outputs,omitempty"` 71 | } `yaml:"workflow_call"` 72 | } 73 | InputMarkdownLinks bool 74 | } 75 | 76 | // GetData parses the source yaml file 77 | func (r *Reusable) GetData() error { 78 | reusableYaml, err := os.ReadFile(r.InputFileName) 79 | if err != nil { 80 | return err 81 | } 82 | err = yaml.Unmarshal(reusableYaml, &r) 83 | 84 | return err 85 | } 86 | 87 | // WriteDocumentation write the table to the output file 88 | func (r *Reusable) WriteDocumentation(inputTable, outputTable, secretsTable *strings.Builder) error { 89 | var err error 90 | input, err := os.ReadFile(r.OutputFileName) 91 | if err != nil { 92 | return err 93 | } 94 | 95 | var output []byte 96 | 97 | hasInputsData, indices := utils.HasBytesInBetween( 98 | input, 99 | []byte(internal.InputAutoDocStart), 100 | []byte(internal.InputAutoDocEnd), 101 | ) 102 | 103 | output = input 104 | inputsStr := strings.TrimSpace(inputTable.String()) 105 | 106 | if hasInputsData { 107 | output = utils.ReplaceBytesInBetween(output, indices, []byte(inputsStr)) 108 | } else { 109 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.InputsHeader)) 110 | output = re.ReplaceAllFunc(input, func(match []byte) []byte { 111 | if bytes.HasPrefix(match, []byte(internal.InputsHeader)) { 112 | if inputsStr != "" { 113 | return []byte(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputsStr)) 114 | } else { 115 | return []byte(internal.InputsHeader) 116 | } 117 | } 118 | return match 119 | }) 120 | } 121 | 122 | hasOutputsData, indices := utils.HasBytesInBetween( 123 | output, 124 | []byte(internal.OutputAutoDocStart), 125 | []byte(internal.OutputAutoDocEnd), 126 | ) 127 | 128 | outputsStr := strings.TrimSpace(outputTable.String()) 129 | 130 | if hasOutputsData { 131 | output = utils.ReplaceBytesInBetween(output, indices, []byte(outputsStr)) 132 | } else { 133 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader)) 134 | output = re.ReplaceAllFunc(output, func(match []byte) []byte { 135 | if bytes.HasPrefix(match, []byte(internal.OutputsHeader)) { 136 | if outputsStr != "" { 137 | return []byte(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputsStr)) 138 | } else { 139 | return []byte(internal.OutputsHeader) 140 | } 141 | } 142 | return match 143 | }) 144 | } 145 | 146 | hasSecretsData, indices := utils.HasBytesInBetween( 147 | output, 148 | []byte(internal.SecretsAutoDocStart), 149 | []byte(internal.SecretsAutoDocEnd), 150 | ) 151 | 152 | secretsStr := strings.TrimSpace(secretsTable.String()) 153 | 154 | if hasSecretsData { 155 | output = utils.ReplaceBytesInBetween(output, indices, []byte(secretsStr)) 156 | } else { 157 | re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.SecretsHeader)) 158 | output = re.ReplaceAllFunc(output, func(match []byte) []byte { 159 | if bytes.HasPrefix(match, []byte(internal.SecretsHeader)) { 160 | if secretsStr != "" { 161 | return []byte(fmt.Sprintf("%s\n\n%v", internal.SecretsHeader, secretsStr)) 162 | } else { 163 | return []byte(internal.SecretsHeader) 164 | } 165 | } 166 | return match 167 | }) 168 | } 169 | 170 | if err = os.WriteFile(r.OutputFileName, output, 0o666); err != nil { 171 | cobra.CheckErr(err) 172 | } 173 | 174 | return nil 175 | } 176 | 177 | // RenderOutput renders the output and writes it to the given output 178 | func (r *Reusable) RenderOutput() error { 179 | var err error 180 | maxWidth, err := strconv.Atoi(r.ColMaxWidth) 181 | if err != nil { 182 | return err 183 | } 184 | 185 | maxWords, err := strconv.Atoi(r.ColMaxWords) 186 | if err != nil { 187 | return err 188 | } 189 | inputTableOutput, err := renderReusableInputTableOutput(r.On.WorkflowCall.Inputs, r.InputColumns, r.InputMarkdownLinks, maxWidth, maxWords) 190 | if err != nil { 191 | return err 192 | } 193 | 194 | secretTableOutput, err := renderReusableSecretTableOutput(r.On.WorkflowCall.Secrets, r.SecretColumns, r.InputMarkdownLinks, maxWidth, maxWords) 195 | if err != nil { 196 | return err 197 | } 198 | 199 | outputTableOutput, err := renderReusableOutputTableOutput(r.On.WorkflowCall.Outputs, r.OutputColumns, r.InputMarkdownLinks, maxWidth, maxWords) 200 | if err != nil { 201 | return err 202 | } 203 | 204 | err = r.WriteDocumentation(inputTableOutput, outputTableOutput, secretTableOutput) 205 | if err != nil { 206 | return err 207 | } 208 | 209 | return nil 210 | } 211 | 212 | // renderReusableInputTableOutput renders the reusable workflow input table 213 | func renderReusableInputTableOutput(inputs map[string]ReusableInput, inputColumns []string, markdownLinks bool, maxWidth int, maxWords int) (*strings.Builder, error) { 214 | inputTableOutput := &strings.Builder{} 215 | 216 | _, err := fmt.Fprintln(inputTableOutput, internal.InputAutoDocStart) 217 | if err != nil { 218 | return inputTableOutput, err 219 | } 220 | 221 | if len(inputs) > 0 { 222 | inputTable := tablewriter.NewWriter(inputTableOutput) 223 | inputTable.SetHeader(inputColumns) 224 | inputTable.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) 225 | inputTable.SetCenterSeparator(internal.PipeSeparator) 226 | inputTable.SetAlignment(tablewriter.ALIGN_CENTER) 227 | 228 | keys := make([]string, 0, len(inputs)) 229 | for k := range inputs { 230 | keys = append(keys, k) 231 | } 232 | sort.Strings(keys) 233 | 234 | inputTable.SetColWidth(maxWidth) 235 | 236 | for _, key := range keys { 237 | var row []string 238 | 239 | for _, col := range inputColumns { 240 | switch col { 241 | case "Input": 242 | modifiedKey := key 243 | if markdownLinks { 244 | modifiedKey = utils.MarkdownLink(key, "input") 245 | } 246 | if inputs[key].DeprecationMessage != "" { 247 | row = append(row, fmt.Sprintf("~~%s~~
%s", modifiedKey, inputs[key].DeprecationMessage)) 248 | } else { 249 | row = append(row, modifiedKey) 250 | } 251 | case "Type": 252 | row = append(row, inputs[key].Type) 253 | case "Required": 254 | row = append(row, strconv.FormatBool(inputs[key].Required)) 255 | case "Default": 256 | switch inputs[key].Type { 257 | case "string": 258 | row = append(row, utils.FormatValue(inputs[key].Default, true, "
")) 259 | default: 260 | row = append(row, "`"+inputs[key].Default+"`") 261 | } 262 | case "Description": 263 | if inputs[key].DeprecationMessage != "" { 264 | row = append(row, utils.WordWrap(fmt.Sprintf("**Deprecated:** %s", inputs[key].Description), maxWords, "
")) 265 | } else { 266 | row = append(row, utils.WordWrap(inputs[key].Description, maxWords, "
")) 267 | } 268 | default: 269 | return inputTableOutput, fmt.Errorf( 270 | "unknown inputs column: '%s'. Please specify any of the following columns: %s", 271 | col, 272 | strings.Join(internal.DefaultReusableInputColumns, ", "), 273 | ) 274 | } 275 | } 276 | inputTable.Append(row) 277 | } 278 | 279 | _, err = fmt.Fprintln(inputTableOutput) 280 | if err != nil { 281 | return inputTableOutput, err 282 | } 283 | 284 | inputTable.Render() 285 | 286 | _, err = fmt.Fprintln(inputTableOutput) 287 | if err != nil { 288 | return inputTableOutput, err 289 | } 290 | } else { 291 | _, err := fmt.Fprintln(inputTableOutput, internal.NoInputsMessage) 292 | if err != nil { 293 | return inputTableOutput, err 294 | } 295 | } 296 | 297 | _, err = fmt.Fprint(inputTableOutput, internal.InputAutoDocEnd) 298 | if err != nil { 299 | return inputTableOutput, err 300 | } 301 | return inputTableOutput, nil 302 | } 303 | 304 | // renderReusableOutputTableOutput renders the reusable workflow output table 305 | func renderReusableOutputTableOutput(outputs map[string]ReusableOutput, reusableOutputColumns []string, markdownLinks bool, maxWidth int, maxWords int) (*strings.Builder, error) { 306 | outputTableOutput := &strings.Builder{} 307 | 308 | _, err := fmt.Fprintln(outputTableOutput, internal.OutputAutoDocStart) 309 | if err != nil { 310 | return outputTableOutput, err 311 | } 312 | 313 | if len(outputs) > 0 { 314 | outputTable := tablewriter.NewWriter(outputTableOutput) 315 | outputTable.SetHeader(reusableOutputColumns) 316 | outputTable.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) 317 | outputTable.SetCenterSeparator(internal.PipeSeparator) 318 | outputTable.SetAlignment(tablewriter.ALIGN_CENTER) 319 | 320 | keys := make([]string, 0, len(outputs)) 321 | for k := range outputs { 322 | keys = append(keys, k) 323 | } 324 | sort.Strings(keys) 325 | 326 | outputTable.SetColWidth(maxWidth) 327 | for _, key := range keys { 328 | var row []string 329 | 330 | for _, col := range reusableOutputColumns { 331 | switch col { 332 | case "Output": 333 | if markdownLinks { 334 | row = append(row, utils.MarkdownLink(key, "output")) 335 | } else { 336 | row = append(row, key) 337 | } 338 | case "Value": 339 | row = append(row, utils.FormatValue(outputs[key].Value, true, "
")) 340 | case "Description": 341 | row = append(row, utils.WordWrap(outputs[key].Description, maxWords, "
")) 342 | default: 343 | return outputTableOutput, fmt.Errorf( 344 | "unknown outputs column: '%s'. Please specify any of the following columns: %s", 345 | col, 346 | strings.Join(internal.DefaultReusableOutputColumns, ", "), 347 | ) 348 | } 349 | } 350 | outputTable.Append(row) 351 | } 352 | 353 | _, err = fmt.Fprintln(outputTableOutput) 354 | if err != nil { 355 | return outputTableOutput, err 356 | } 357 | outputTable.Render() 358 | 359 | _, err = fmt.Fprintln(outputTableOutput) 360 | if err != nil { 361 | return outputTableOutput, err 362 | } 363 | } else { 364 | _, err := fmt.Fprintln(outputTableOutput, internal.NoOutputsMessage) 365 | if err != nil { 366 | return outputTableOutput, err 367 | } 368 | } 369 | 370 | _, err = fmt.Fprint(outputTableOutput, internal.OutputAutoDocEnd) 371 | if err != nil { 372 | return outputTableOutput, err 373 | } 374 | return outputTableOutput, nil 375 | } 376 | 377 | // renderReusableSecretTableOutput renders the reusable workflow secret table 378 | func renderReusableSecretTableOutput(secrets map[string]ReusableSecret, secretColumns []string, markdownLinks bool, maxWidth int, maxWords int) (*strings.Builder, error) { 379 | secretTableOutput := &strings.Builder{} 380 | 381 | _, err := fmt.Fprintln(secretTableOutput, internal.SecretsAutoDocStart) 382 | if err != nil { 383 | return secretTableOutput, err 384 | } 385 | 386 | if len(secrets) > 0 { 387 | secretTable := tablewriter.NewWriter(secretTableOutput) 388 | secretTable.SetHeader(secretColumns) 389 | secretTable.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) 390 | secretTable.SetCenterSeparator(internal.PipeSeparator) 391 | secretTable.SetAlignment(tablewriter.ALIGN_CENTER) 392 | 393 | keys := make([]string, 0, len(secrets)) 394 | for k := range secrets { 395 | keys = append(keys, k) 396 | } 397 | sort.Strings(keys) 398 | 399 | secretTable.SetColWidth(maxWidth) 400 | for _, key := range keys { 401 | var row []string 402 | 403 | for _, col := range secretColumns { 404 | switch col { 405 | case "Secret": 406 | if markdownLinks { 407 | row = append(row, utils.MarkdownLink(key, "secret")) 408 | } else { 409 | row = append(row, key) 410 | } 411 | case "Required": 412 | row = append(row, fmt.Sprintf("%v", secrets[key].Required)) 413 | case "Description": 414 | row = append(row, utils.WordWrap(secrets[key].Description, maxWords, "
")) 415 | default: 416 | return secretTableOutput, fmt.Errorf( 417 | "unknown secrets column: '%secrets'. Please specify any of the following columns: %secrets", 418 | col, 419 | strings.Join(internal.DefaultReusableSecretColumns, ", "), 420 | ) 421 | } 422 | } 423 | secretTable.Append(row) 424 | } 425 | _, err = fmt.Fprintln(secretTableOutput) 426 | if err != nil { 427 | return secretTableOutput, err 428 | } 429 | secretTable.Render() 430 | 431 | _, err = fmt.Fprintln(secretTableOutput) 432 | if err != nil { 433 | return secretTableOutput, err 434 | } 435 | } else { 436 | _, err := fmt.Fprintln(secretTableOutput, internal.NoSecretsMessage) 437 | if err != nil { 438 | return secretTableOutput, err 439 | } 440 | } 441 | 442 | _, err = fmt.Fprint(secretTableOutput, internal.SecretsAutoDocEnd) 443 | if err != nil { 444 | return secretTableOutput, err 445 | } 446 | return secretTableOutput, nil 447 | } 448 | -------------------------------------------------------------------------------- /internal/utils/bytes_utils.go: -------------------------------------------------------------------------------- 1 | //Package utils is a package that contains all the utility functions 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package utils 18 | 19 | import ( 20 | "fmt" 21 | "regexp" 22 | ) 23 | 24 | // HasBytesInBetween checks if a byte array has a start and end byte array and returns true if and all occurrences of start and end 25 | func HasBytesInBetween(value, start, end []byte) (found bool, indices [][]int) { 26 | // Multiline regex 27 | findRegex := regexp.MustCompile(fmt.Sprintf(`(?s)%s(.*?)%s`, regexp.QuoteMeta(string(start)), regexp.QuoteMeta(string(end)))) 28 | indices = findRegex.FindAllIndex(value, -1) 29 | 30 | if len(indices) == 0 { 31 | return false, indices 32 | } 33 | 34 | return true, indices 35 | } 36 | 37 | // ReplaceBytesInBetween replaces a byte array between an array of start and end indices with a new byte array 38 | func ReplaceBytesInBetween(value []byte, indices [][]int, new []byte) []byte { 39 | t := make([]byte, 0, len(value)+len(new)*len(indices)) 40 | prevIndex := 0 41 | 42 | for _, v := range indices { 43 | t = append(t, value[prevIndex:v[0]]...) 44 | t = append(t, new...) 45 | prevIndex = v[1] 46 | } 47 | 48 | t = append(t, value[prevIndex:]...) 49 | return t 50 | } 51 | -------------------------------------------------------------------------------- /internal/utils/format_value.go: -------------------------------------------------------------------------------- 1 | //Package utils is a package that contains all the utility functions 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package utils 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | 23 | "github.com/tj-actions/auto-doc/v3/internal" 24 | ) 25 | 26 | // FormatValue formats a string that would be output as markdown 27 | func FormatValue(v string, escape bool, lineSeparator string) string { 28 | if len(v) == 0 { 29 | return "" 30 | } 31 | 32 | var inputDefault = v 33 | var defaultValue string 34 | var parts = strings.Split(inputDefault, internal.NewLineSeparator) 35 | 36 | if len(parts) > 1 && inputDefault != internal.NewLineSeparator { 37 | for _, part := range parts { 38 | if part != "" { 39 | if escape { 40 | defaultValue += "`\"" + part + "\"`" + lineSeparator 41 | } else { 42 | defaultValue += part + lineSeparator 43 | } 44 | } 45 | } 46 | } else { 47 | if strings.Contains(inputDefault, internal.PipeSeparator) { 48 | if escape { 49 | inputDefault = strings.Replace(inputDefault, internal.PipeSeparator, "\"\\"+internal.PipeSeparator+"\"", -1) 50 | } else { 51 | inputDefault = strings.Replace(inputDefault, internal.PipeSeparator, "\""+internal.PipeSeparator+"\"", -1) 52 | } 53 | } else { 54 | inputDefault = fmt.Sprintf("%#v", inputDefault) 55 | } 56 | if escape { 57 | defaultValue = "`" + inputDefault + "`" 58 | } else { 59 | defaultValue = inputDefault 60 | } 61 | } 62 | 63 | return defaultValue 64 | } 65 | -------------------------------------------------------------------------------- /internal/utils/get_latest_repository_tag.go: -------------------------------------------------------------------------------- 1 | //Package utils is a package that contains all the utility functions 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package utils 18 | 19 | import ( 20 | "encoding/json" 21 | "fmt" 22 | "io" 23 | "net/http" 24 | "strings" 25 | ) 26 | 27 | type Release struct { 28 | TagName string `json:"tag_name"` 29 | } 30 | 31 | type Tag struct { 32 | Object struct { 33 | SHA string `json:"sha"` 34 | } `json:"object"` 35 | } 36 | 37 | // GetTagCommitHash returns the commit hash of a tag 38 | func GetTagCommitHash(repository, tag, token string) (string, error) { 39 | tagURL := fmt.Sprintf("https://api.github.com/repos/%s/git/refs/tags/%s", repository, tag) 40 | req, err := http.NewRequest("GET", tagURL, nil) 41 | if err != nil { 42 | return "", err 43 | } 44 | if token != "" { 45 | req.Header.Set("Authorization", "token "+token) 46 | } 47 | 48 | client := &http.Client{} 49 | resp, err := client.Do(req) 50 | if err != nil { 51 | return "", err 52 | } 53 | defer func(Body io.ReadCloser) { 54 | err := Body.Close() 55 | if err != nil { 56 | panic(err) 57 | } 58 | }(resp.Body) 59 | 60 | body, err := io.ReadAll(resp.Body) 61 | if err != nil { 62 | return "", err 63 | } 64 | 65 | var tagObj Tag 66 | err = json.Unmarshal(body, &tagObj) 67 | if err != nil { 68 | return "", err 69 | } 70 | 71 | return tagObj.Object.SHA, nil 72 | } 73 | 74 | // GetLatestRepositoryTag returns the latest tag of a repository 75 | func GetLatestRepositoryTag(repository, token string, useMajorVersion bool, useTagCommitHash bool) (string, error) { 76 | url := fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", repository) 77 | req, err := http.NewRequest("GET", url, nil) 78 | if err != nil { 79 | return "", err 80 | } 81 | if token != "" { 82 | req.Header.Set("Authorization", "token "+token) 83 | } 84 | 85 | client := &http.Client{} 86 | resp, err := client.Do(req) 87 | if err != nil { 88 | return "", err 89 | } 90 | defer func(Body io.ReadCloser) { 91 | err := Body.Close() 92 | if err != nil { 93 | panic(err) 94 | } 95 | }(resp.Body) 96 | 97 | body, err := io.ReadAll(resp.Body) 98 | if err != nil { 99 | return "", err 100 | } 101 | 102 | var release Release 103 | err = json.Unmarshal(body, &release) 104 | if err != nil { 105 | return "", err 106 | } 107 | 108 | version := release.TagName 109 | 110 | if useMajorVersion && strings.Contains(version, ".") { 111 | version = strings.Split(version, ".")[0] 112 | } 113 | 114 | if useTagCommitHash { 115 | commitHash, err := GetTagCommitHash(repository, version, token) 116 | if err != nil { 117 | return "", err 118 | } 119 | version = fmt.Sprintf("%s # %s", commitHash, version) 120 | } 121 | 122 | return version, nil 123 | } 124 | -------------------------------------------------------------------------------- /internal/utils/markdown_link.go: -------------------------------------------------------------------------------- 1 | //Package utils is a package that contains all the utility functions 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package utils 18 | 19 | // MarkdownLink formats input, output and secret name to Markdown link (named anchor) and return the link 20 | func MarkdownLink(s string, t string) string { 21 | var link string 22 | var typeName = t + "_" + s 23 | 24 | link = "[" + s + "](#" + typeName + ")" 25 | 26 | return link 27 | } 28 | -------------------------------------------------------------------------------- /internal/utils/word_wrap.go: -------------------------------------------------------------------------------- 1 | //Package utils is a package that contains all the utility functions 2 | /* 3 | Copyright © 2021 Tonye Jack 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | package utils 18 | 19 | import ( 20 | "regexp" 21 | "strings" 22 | "unicode" 23 | ) 24 | 25 | // WordWrap wraps text at the specified number of columns and inserts a line separator 26 | func WordWrap(s string, limit int, lineSeparator string) string { 27 | if strings.TrimSpace(s) == "" || len(strings.Fields(s)) <= limit { 28 | return s 29 | } 30 | 31 | var ( 32 | linkIndices = getAllLinksIndex(s) 33 | codeBlockIndices = getAllCodeBlocksIndex(s) 34 | codeIndices = getAllCodeIndex(s) 35 | parenthesisIndices = getAllParenthesisIndex(s) 36 | italicIndices = getAllItalicIndex(s) 37 | start = 0 38 | ) 39 | 40 | // split the string into words that aren't between any of the links, code blocks, code and parenthesis 41 | strSlice := strings.FieldsFunc(s, func(r rune) bool { 42 | shouldExclude := isWithin(start, linkIndices) || isWithin(start, codeBlockIndices) || isWithin(start, codeIndices) || isWithin(start, parenthesisIndices) || isWithin(start, italicIndices) 43 | start++ 44 | return !shouldExclude && unicode.IsSpace(r) 45 | }) 46 | 47 | var result = "" 48 | 49 | for len(strSlice) >= 1 { 50 | // convert slice/array back to string 51 | // but insert line break at specified limit 52 | if len(strSlice) < limit { 53 | limit = len(strSlice) 54 | } 55 | 56 | result = result + strings.Join(strSlice[:limit], " ") + " " + lineSeparator 57 | 58 | // discard the elements that were copied over to result 59 | strSlice = strSlice[limit:] 60 | } 61 | 62 | // Trim the last
tag 63 | result = strings.TrimSuffix(result, lineSeparator) 64 | 65 | return result 66 | } 67 | 68 | func isWithin(index int, ranges [][]int) bool { 69 | for _, r := range ranges { 70 | if index >= r[0] && index < r[1] { 71 | return true 72 | } 73 | } 74 | 75 | return false 76 | } 77 | 78 | func getAllLinksIndex(s string) [][]int { 79 | linkRegex := regexp.MustCompile(`\[(.*?)\]\((.*?)\)`) 80 | 81 | return linkRegex.FindAllStringIndex(s, -1) 82 | } 83 | 84 | func getAllCodeBlocksIndex(s string) [][]int { 85 | codeBlockRegex := regexp.MustCompile("```[^`]*```") 86 | 87 | return codeBlockRegex.FindAllStringIndex(s, -1) 88 | } 89 | 90 | func getAllCodeIndex(s string) [][]int { 91 | codeRegex := regexp.MustCompile("`[^`]*`") 92 | 93 | return codeRegex.FindAllStringIndex(s, -1) 94 | } 95 | 96 | func getAllParenthesisIndex(s string) [][]int { 97 | parenthesisRegex := regexp.MustCompile(`\((.*?)\)`) 98 | 99 | return parenthesisRegex.FindAllStringIndex(s, -1) 100 | } 101 | 102 | func getAllItalicIndex(s string) [][]int { 103 | italicRegex := regexp.MustCompile(`\*(.*?)\*`) 104 | 105 | return italicRegex.FindAllStringIndex(s, -1) 106 | } 107 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Tonye Jack 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package main 17 | 18 | import "github.com/tj-actions/auto-doc/v3/cmd" 19 | 20 | func main() { 21 | cmd.Execute() 22 | } 23 | -------------------------------------------------------------------------------- /test/README-action-empty-markers-no-inputs-no-outputs.expected.md: -------------------------------------------------------------------------------- 1 | # test/action 2 | 3 | Test text ## Inputs 4 | 5 | ## Description 6 | 7 | No description. 8 | 9 | 10 | ## Inputs 11 | 12 | 13 | No inputs. 14 | 15 | 16 | ## Outputs 17 | 18 | 19 | No outputs. 20 | 21 | -------------------------------------------------------------------------------- /test/README-action-empty-markers.md: -------------------------------------------------------------------------------- 1 | # test/action 2 | 3 | ## Description 4 | 5 | 6 | No description. 7 | 8 | 9 | Test text ## Inputs 10 | 11 | ## Inputs 12 | 13 | 14 | No inputs. 15 | 16 | 17 | ## Outputs 18 | 19 | 20 | No outputs. 21 | 22 | -------------------------------------------------------------------------------- /test/README-codeBlocks.md: -------------------------------------------------------------------------------- 1 | ## Inputs 2 | 3 | 4 | ```yaml 5 | - uses: tj-actions/changed-files@v46.0.1 6 | id: changed-files 7 | with: 8 | # Specify a different base commit SHA 9 | # used for comparing changes 10 | # Type: string 11 | base_sha: '' 12 | 13 | # Exclude changes outside the current directory 14 | # and show path names relative to 15 | # it. **NOTE:** This requires you to 16 | # specify the top level directory via 17 | # the `path` input. 18 | # Type: string 19 | diff_relative: '' 20 | 21 | # Output unique changed directories instead of 22 | # filenames. **NOTE:** This returns `.` for 23 | # changed files located in the root 24 | # of the project. 25 | # Type: boolean 26 | # Default: "false" 27 | dir_names: '' 28 | 29 | # Maximum depth of directories to output. 30 | # e.g `test/test1/test2` with max depth of 31 | # `2` returns `test/test1`. 32 | # Type: string 33 | dir_names_max_depth: '' 34 | 35 | # Depth of additional branch history fetched. 36 | # **NOTE**: This can be adjusted to 37 | # resolve errors with insufficient history. 38 | # Type: string 39 | # Default: "50" 40 | fetch_depth: '' 41 | 42 | # File and directory patterns to detect 43 | # changes using only these list of 44 | # file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns 45 | # should not include quotes. 46 | # Type: string 47 | # Default: a.txt 48 | # b.txt 49 | # test.txt 50 | # 51 | files: '' 52 | 53 | # Source file(s) used to populate the 54 | # `files` input. 55 | # Type: string 56 | files_from_source_file: '' 57 | 58 | # Ignore changes to these file(s) **NOTE:** 59 | # Multiline file/directory patterns should not include 60 | # quotes. 61 | # Type: string 62 | files_ignore: '' 63 | 64 | # Source file(s) used to populate the 65 | # `files_ignore` input 66 | # Type: string 67 | files_ignore_from_source_file: '' 68 | 69 | # Separator used to split the `files_ignore` 70 | # input 71 | # Type: string 72 | # Default: "\n" 73 | files_ignore_separator: '' 74 | 75 | # Separator used to split the `files` 76 | # input 77 | # Type: string 78 | # Default: "\n" 79 | files_separator: '' 80 | 81 | # Include `all_old_new_renamed_files` output. Note this can 82 | # generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). 83 | # Type: boolean 84 | # Default: "false" 85 | include_all_old_new_renamed_files: '' 86 | 87 | # Output list of changed files in 88 | # a JSON formatted string which can 89 | # be used for matrix jobs. 90 | # Type: boolean 91 | # Default: "false" 92 | json: '' 93 | 94 | # Output list of changed files in 95 | # a raw format which means that 96 | # the output will not be surrounded 97 | # by quotes and special characters will 98 | # not be escaped. 99 | # Type: boolean 100 | # Default: "false" 101 | # Deprecated: Use `json_unescaped` instead. 102 | json_raw_format: '' 103 | 104 | # Output list of changed files in 105 | # a JSON formatted string without escaping 106 | # special characters. 107 | # Type: boolean 108 | # Default: "false" 109 | json_unescaped: '' 110 | 111 | # Boolean indicating whether to output input, 112 | # output and secret names as markdown 113 | # links 114 | # Type: boolean 115 | # Default: "false" 116 | markdown_links: '' 117 | 118 | # Indicates whether to include match directories 119 | # Type: boolean 120 | # Default: "true" 121 | match_directories: '' 122 | 123 | # Split character for old and new 124 | # renamed filename pairs. 125 | # Type: string 126 | # Default: " " 127 | old_new_files_separator: '' 128 | 129 | # Split character for old and new 130 | # filename pairs. 131 | # Type: string 132 | # Default: "," 133 | old_new_separator: '' 134 | 135 | # Directory to store output files. 136 | # Type: string 137 | # Default: ".github/outputs" 138 | output_dir: '' 139 | 140 | # Specify a relative path under `$GITHUB_WORKSPACE` 141 | # to locate the repository. 142 | # Type: string 143 | # Default: "." 144 | path: '' 145 | 146 | # Use non ascii characters to match 147 | # files and output the filenames completely 148 | # verbatim by setting this to `false` 149 | # Type: boolean 150 | # Default: "true" 151 | quotepath: '' 152 | 153 | # Split character for output strings. 154 | # Type: string 155 | # Default: "|" 156 | separator: '' 157 | 158 | # Specify a different commit SHA used 159 | # for comparing changes 160 | # Type: string 161 | sha: '' 162 | 163 | # Get changed files for commits whose 164 | # timestamp is older than the given 165 | # time. 166 | # Type: string 167 | since: '' 168 | 169 | # Use the last commit on the 170 | # remote branch as the `base_sha`. Defaults 171 | # to the last non merge commit 172 | # on the target branch for pull 173 | # request events and the previous remote 174 | # commit of the current branch for 175 | # push events. 176 | # Type: boolean 177 | # Default: "false" 178 | since_last_remote_commit: '' 179 | 180 | # The GitHub token to use for 181 | # authentication. 182 | # Type: string 183 | # Default: "${{ github.token }}" 184 | token: '' 185 | 186 | # Get changed files for commits whose 187 | # timestamp is earlier than the given 188 | # time. 189 | # Type: string 190 | until: '' 191 | 192 | # Write outputs to files in the 193 | # `.github/outputs` folder by default. 194 | # Type: boolean 195 | # Default: "false" 196 | write_output_files: '' 197 | 198 | ``` 199 | 200 | 201 | ## Outputs 202 | 203 | 204 | 205 | | OUTPUT | TYPE | DESCRIPTION | 206 | |--------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 207 | | added_files | string | Returns only files that are Added
(A). | 208 | | all_changed_and_modified_files | string | Returns all changed and modified files
i.e. *a combination of (ACMRDTUX)* | 209 | | all_changed_files | string | Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)* | 210 | | all_modified_files | string | Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*. | 211 | | all_old_new_renamed_files | string | Returns only files that are Renamed
and list their old and new
names. **NOTE:** This requires setting `include_all_old_new_renamed_files`
to `true` (R) | 212 | | any_changed | string | Returns `true` when any of the
filenames provided using the `files` input
has changed. If no `files` have
been specified,an empty string `''` is
returned. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. | 213 | | any_deleted | string | Returns `true` when any of the
filenames provided using the `files` input
has been deleted. If no `files`
have been specified,an empty string `''`
is returned. (D) | 214 | | any_modified | string | Returns `true` when any of the
filenames provided using the `files` input
has been modified. If no `files`
have been specified,an empty string `''`
is returned. i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*. | 215 | | copied_files | string | Returns only files that are Copied
(C). | 216 | | deleted_files | string | Returns only files that are Deleted
(D). | 217 | | modified_files | string | Returns only files that are Modified
(M). | 218 | | only_changed | string | Returns `true` when only files provided
using the `files` input has changed.
If no `files` have been specified,an
empty string `''` is returned. i.e.
*using a combination of all added, copied, modified and renamed files (ACMR)*. | 219 | | only_deleted | string | Returns `true` when only files provided
using the `files` input has been
deleted. If no `files` have been
specified,an empty string `''` is returned.
(D) | 220 | | only_modified | string | Returns `true` when only files provided
using the `files` input has been
modified. If no `files` have been
specified,an empty string `''` is returned.(ACMRD). | 221 | | other_changed_files | string | Returns all other changed files not
listed in the files input i.e.
*using a combination of all added, copied, modified and renamed files (ACMR)*. | 222 | | other_deleted_files | string | Returns all other deleted files not
listed in the files input i.e.
*a combination of all deleted files (D)* | 223 | | other_modified_files | string | Returns all other modified files not
listed in the files input i.e.
*a combination of all added, copied, modified, and deleted files (ACMRD)* | 224 | | renamed_files | string | Returns only files that are Renamed
(R). | 225 | | type_changed_files | string | Returns only files that have their
file type changed (T). | 226 | | unknown_files | string | Returns only files that are Unknown
(X). | 227 | | unmerged_files | string | Returns only files that are Unmerged
(U). | 228 | 229 | 230 | -------------------------------------------------------------------------------- /test/README-codeBlocksMajorVersion.md: -------------------------------------------------------------------------------- 1 | ## Inputs 2 | 3 | 4 | ```yaml 5 | - uses: tj-actions/changed-files@v46 6 | id: changed-files 7 | with: 8 | # Specify a different base commit SHA 9 | # used for comparing changes 10 | # Type: string 11 | base_sha: '' 12 | 13 | # Exclude changes outside the current directory 14 | # and show path names relative to 15 | # it. **NOTE:** This requires you to 16 | # specify the top level directory via 17 | # the `path` input. 18 | # Type: string 19 | diff_relative: '' 20 | 21 | # Output unique changed directories instead of 22 | # filenames. **NOTE:** This returns `.` for 23 | # changed files located in the root 24 | # of the project. 25 | # Type: boolean 26 | # Default: "false" 27 | dir_names: '' 28 | 29 | # Maximum depth of directories to output. 30 | # e.g `test/test1/test2` with max depth of 31 | # `2` returns `test/test1`. 32 | # Type: string 33 | dir_names_max_depth: '' 34 | 35 | # Depth of additional branch history fetched. 36 | # **NOTE**: This can be adjusted to 37 | # resolve errors with insufficient history. 38 | # Type: string 39 | # Default: "50" 40 | fetch_depth: '' 41 | 42 | # File and directory patterns to detect 43 | # changes using only these list of 44 | # file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns 45 | # should not include quotes. 46 | # Type: string 47 | # Default: a.txt 48 | # b.txt 49 | # test.txt 50 | # 51 | files: '' 52 | 53 | # Source file(s) used to populate the 54 | # `files` input. 55 | # Type: string 56 | files_from_source_file: '' 57 | 58 | # Ignore changes to these file(s) **NOTE:** 59 | # Multiline file/directory patterns should not include 60 | # quotes. 61 | # Type: string 62 | files_ignore: '' 63 | 64 | # Source file(s) used to populate the 65 | # `files_ignore` input 66 | # Type: string 67 | files_ignore_from_source_file: '' 68 | 69 | # Separator used to split the `files_ignore` 70 | # input 71 | # Type: string 72 | # Default: "\n" 73 | files_ignore_separator: '' 74 | 75 | # Separator used to split the `files` 76 | # input 77 | # Type: string 78 | # Default: "\n" 79 | files_separator: '' 80 | 81 | # Include `all_old_new_renamed_files` output. Note this can 82 | # generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). 83 | # Type: boolean 84 | # Default: "false" 85 | include_all_old_new_renamed_files: '' 86 | 87 | # Output list of changed files in 88 | # a JSON formatted string which can 89 | # be used for matrix jobs. 90 | # Type: boolean 91 | # Default: "false" 92 | json: '' 93 | 94 | # Output list of changed files in 95 | # a raw format which means that 96 | # the output will not be surrounded 97 | # by quotes and special characters will 98 | # not be escaped. 99 | # Type: boolean 100 | # Default: "false" 101 | # Deprecated: Use `json_unescaped` instead. 102 | json_raw_format: '' 103 | 104 | # Output list of changed files in 105 | # a JSON formatted string without escaping 106 | # special characters. 107 | # Type: boolean 108 | # Default: "false" 109 | json_unescaped: '' 110 | 111 | # Boolean indicating whether to output input, 112 | # output and secret names as markdown 113 | # links 114 | # Type: boolean 115 | # Default: "false" 116 | markdown_links: '' 117 | 118 | # Indicates whether to include match directories 119 | # Type: boolean 120 | # Default: "true" 121 | match_directories: '' 122 | 123 | # Split character for old and new 124 | # renamed filename pairs. 125 | # Type: string 126 | # Default: " " 127 | old_new_files_separator: '' 128 | 129 | # Split character for old and new 130 | # filename pairs. 131 | # Type: string 132 | # Default: "," 133 | old_new_separator: '' 134 | 135 | # Directory to store output files. 136 | # Type: string 137 | # Default: ".github/outputs" 138 | output_dir: '' 139 | 140 | # Specify a relative path under `$GITHUB_WORKSPACE` 141 | # to locate the repository. 142 | # Type: string 143 | # Default: "." 144 | path: '' 145 | 146 | # Use non ascii characters to match 147 | # files and output the filenames completely 148 | # verbatim by setting this to `false` 149 | # Type: boolean 150 | # Default: "true" 151 | quotepath: '' 152 | 153 | # Split character for output strings. 154 | # Type: string 155 | # Default: "|" 156 | separator: '' 157 | 158 | # Specify a different commit SHA used 159 | # for comparing changes 160 | # Type: string 161 | sha: '' 162 | 163 | # Get changed files for commits whose 164 | # timestamp is older than the given 165 | # time. 166 | # Type: string 167 | since: '' 168 | 169 | # Use the last commit on the 170 | # remote branch as the `base_sha`. Defaults 171 | # to the last non merge commit 172 | # on the target branch for pull 173 | # request events and the previous remote 174 | # commit of the current branch for 175 | # push events. 176 | # Type: boolean 177 | # Default: "false" 178 | since_last_remote_commit: '' 179 | 180 | # The GitHub token to use for 181 | # authentication. 182 | # Type: string 183 | # Default: "${{ github.token }}" 184 | token: '' 185 | 186 | # Get changed files for commits whose 187 | # timestamp is earlier than the given 188 | # time. 189 | # Type: string 190 | until: '' 191 | 192 | # Write outputs to files in the 193 | # `.github/outputs` folder by default. 194 | # Type: boolean 195 | # Default: "false" 196 | write_output_files: '' 197 | 198 | ``` 199 | 200 | -------------------------------------------------------------------------------- /test/README-codeBlocksWithCommitHash.md: -------------------------------------------------------------------------------- 1 | ## Inputs 2 | 3 | 4 | ```yaml 5 | - uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 6 | id: changed-files 7 | with: 8 | # Specify a different base commit SHA 9 | # used for comparing changes 10 | # Type: string 11 | base_sha: '' 12 | 13 | # Exclude changes outside the current directory 14 | # and show path names relative to 15 | # it. **NOTE:** This requires you to 16 | # specify the top level directory via 17 | # the `path` input. 18 | # Type: string 19 | diff_relative: '' 20 | 21 | # Output unique changed directories instead of 22 | # filenames. **NOTE:** This returns `.` for 23 | # changed files located in the root 24 | # of the project. 25 | # Type: boolean 26 | # Default: "false" 27 | dir_names: '' 28 | 29 | # Maximum depth of directories to output. 30 | # e.g `test/test1/test2` with max depth of 31 | # `2` returns `test/test1`. 32 | # Type: string 33 | dir_names_max_depth: '' 34 | 35 | # Depth of additional branch history fetched. 36 | # **NOTE**: This can be adjusted to 37 | # resolve errors with insufficient history. 38 | # Type: string 39 | # Default: "50" 40 | fetch_depth: '' 41 | 42 | # File and directory patterns to detect 43 | # changes using only these list of 44 | # file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns 45 | # should not include quotes. 46 | # Type: string 47 | # Default: a.txt 48 | # b.txt 49 | # test.txt 50 | # 51 | files: '' 52 | 53 | # Source file(s) used to populate the 54 | # `files` input. 55 | # Type: string 56 | files_from_source_file: '' 57 | 58 | # Ignore changes to these file(s) **NOTE:** 59 | # Multiline file/directory patterns should not include 60 | # quotes. 61 | # Type: string 62 | files_ignore: '' 63 | 64 | # Source file(s) used to populate the 65 | # `files_ignore` input 66 | # Type: string 67 | files_ignore_from_source_file: '' 68 | 69 | # Separator used to split the `files_ignore` 70 | # input 71 | # Type: string 72 | # Default: "\n" 73 | files_ignore_separator: '' 74 | 75 | # Separator used to split the `files` 76 | # input 77 | # Type: string 78 | # Default: "\n" 79 | files_separator: '' 80 | 81 | # Include `all_old_new_renamed_files` output. Note this can 82 | # generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). 83 | # Type: boolean 84 | # Default: "false" 85 | include_all_old_new_renamed_files: '' 86 | 87 | # Output list of changed files in 88 | # a JSON formatted string which can 89 | # be used for matrix jobs. 90 | # Type: boolean 91 | # Default: "false" 92 | json: '' 93 | 94 | # Output list of changed files in 95 | # a raw format which means that 96 | # the output will not be surrounded 97 | # by quotes and special characters will 98 | # not be escaped. 99 | # Type: boolean 100 | # Default: "false" 101 | # Deprecated: Use `json_unescaped` instead. 102 | json_raw_format: '' 103 | 104 | # Output list of changed files in 105 | # a JSON formatted string without escaping 106 | # special characters. 107 | # Type: boolean 108 | # Default: "false" 109 | json_unescaped: '' 110 | 111 | # Boolean indicating whether to output input, 112 | # output and secret names as markdown 113 | # links 114 | # Type: boolean 115 | # Default: "false" 116 | markdown_links: '' 117 | 118 | # Indicates whether to include match directories 119 | # Type: boolean 120 | # Default: "true" 121 | match_directories: '' 122 | 123 | # Split character for old and new 124 | # renamed filename pairs. 125 | # Type: string 126 | # Default: " " 127 | old_new_files_separator: '' 128 | 129 | # Split character for old and new 130 | # filename pairs. 131 | # Type: string 132 | # Default: "," 133 | old_new_separator: '' 134 | 135 | # Directory to store output files. 136 | # Type: string 137 | # Default: ".github/outputs" 138 | output_dir: '' 139 | 140 | # Specify a relative path under `$GITHUB_WORKSPACE` 141 | # to locate the repository. 142 | # Type: string 143 | # Default: "." 144 | path: '' 145 | 146 | # Use non ascii characters to match 147 | # files and output the filenames completely 148 | # verbatim by setting this to `false` 149 | # Type: boolean 150 | # Default: "true" 151 | quotepath: '' 152 | 153 | # Split character for output strings. 154 | # Type: string 155 | # Default: "|" 156 | separator: '' 157 | 158 | # Specify a different commit SHA used 159 | # for comparing changes 160 | # Type: string 161 | sha: '' 162 | 163 | # Get changed files for commits whose 164 | # timestamp is older than the given 165 | # time. 166 | # Type: string 167 | since: '' 168 | 169 | # Use the last commit on the 170 | # remote branch as the `base_sha`. Defaults 171 | # to the last non merge commit 172 | # on the target branch for pull 173 | # request events and the previous remote 174 | # commit of the current branch for 175 | # push events. 176 | # Type: boolean 177 | # Default: "false" 178 | since_last_remote_commit: '' 179 | 180 | # The GitHub token to use for 181 | # authentication. 182 | # Type: string 183 | # Default: "${{ github.token }}" 184 | token: '' 185 | 186 | # Get changed files for commits whose 187 | # timestamp is earlier than the given 188 | # time. 189 | # Type: string 190 | until: '' 191 | 192 | # Write outputs to files in the 193 | # `.github/outputs` folder by default. 194 | # Type: boolean 195 | # Default: "false" 196 | write_output_files: '' 197 | 198 | ``` 199 | 200 | 201 | ## Outputs 202 | 203 | 204 | 205 | | OUTPUT | TYPE | DESCRIPTION | 206 | |--------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 207 | | added_files | string | Returns only files that are Added
(A). | 208 | | all_changed_and_modified_files | string | Returns all changed and modified files
i.e. *a combination of (ACMRDTUX)* | 209 | | all_changed_files | string | Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)* | 210 | | all_modified_files | string | Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*. | 211 | | all_old_new_renamed_files | string | Returns only files that are Renamed
and list their old and new
names. **NOTE:** This requires setting `include_all_old_new_renamed_files`
to `true` (R) | 212 | | any_changed | string | Returns `true` when any of the
filenames provided using the `files` input
has changed. If no `files` have
been specified,an empty string `''` is
returned. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. | 213 | | any_deleted | string | Returns `true` when any of the
filenames provided using the `files` input
has been deleted. If no `files`
have been specified,an empty string `''`
is returned. (D) | 214 | | any_modified | string | Returns `true` when any of the
filenames provided using the `files` input
has been modified. If no `files`
have been specified,an empty string `''`
is returned. i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*. | 215 | | copied_files | string | Returns only files that are Copied
(C). | 216 | | deleted_files | string | Returns only files that are Deleted
(D). | 217 | | modified_files | string | Returns only files that are Modified
(M). | 218 | | only_changed | string | Returns `true` when only files provided
using the `files` input has changed.
If no `files` have been specified,an
empty string `''` is returned. i.e.
*using a combination of all added, copied, modified and renamed files (ACMR)*. | 219 | | only_deleted | string | Returns `true` when only files provided
using the `files` input has been
deleted. If no `files` have been
specified,an empty string `''` is returned.
(D) | 220 | | only_modified | string | Returns `true` when only files provided
using the `files` input has been
modified. If no `files` have been
specified,an empty string `''` is returned.(ACMRD). | 221 | | other_changed_files | string | Returns all other changed files not
listed in the files input i.e.
*using a combination of all added, copied, modified and renamed files (ACMR)*. | 222 | | other_deleted_files | string | Returns all other deleted files not
listed in the files input i.e.
*a combination of all deleted files (D)* | 223 | | other_modified_files | string | Returns all other modified files not
listed in the files input i.e.
*a combination of all added, copied, modified, and deleted files (ACMRD)* | 224 | | renamed_files | string | Returns only files that are Renamed
(R). | 225 | | type_changed_files | string | Returns only files that have their
file type changed (T). | 226 | | unknown_files | string | Returns only files that are Unknown
(X). | 227 | | unmerged_files | string | Returns only files that are Unmerged
(U). | 228 | 229 | 230 | -------------------------------------------------------------------------------- /test/README-codeBlocksWithCommitHashMajorVersion.md: -------------------------------------------------------------------------------- 1 | ## Inputs 2 | 3 | 4 | ```yaml 5 | - uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46 6 | id: changed-files 7 | with: 8 | # Specify a different base commit SHA 9 | # used for comparing changes 10 | # Type: string 11 | base_sha: '' 12 | 13 | # Exclude changes outside the current directory 14 | # and show path names relative to 15 | # it. **NOTE:** This requires you to 16 | # specify the top level directory via 17 | # the `path` input. 18 | # Type: string 19 | diff_relative: '' 20 | 21 | # Output unique changed directories instead of 22 | # filenames. **NOTE:** This returns `.` for 23 | # changed files located in the root 24 | # of the project. 25 | # Type: boolean 26 | # Default: "false" 27 | dir_names: '' 28 | 29 | # Maximum depth of directories to output. 30 | # e.g `test/test1/test2` with max depth of 31 | # `2` returns `test/test1`. 32 | # Type: string 33 | dir_names_max_depth: '' 34 | 35 | # Depth of additional branch history fetched. 36 | # **NOTE**: This can be adjusted to 37 | # resolve errors with insufficient history. 38 | # Type: string 39 | # Default: "50" 40 | fetch_depth: '' 41 | 42 | # File and directory patterns to detect 43 | # changes using only these list of 44 | # file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns 45 | # should not include quotes. 46 | # Type: string 47 | # Default: a.txt 48 | # b.txt 49 | # test.txt 50 | # 51 | files: '' 52 | 53 | # Source file(s) used to populate the 54 | # `files` input. 55 | # Type: string 56 | files_from_source_file: '' 57 | 58 | # Ignore changes to these file(s) **NOTE:** 59 | # Multiline file/directory patterns should not include 60 | # quotes. 61 | # Type: string 62 | files_ignore: '' 63 | 64 | # Source file(s) used to populate the 65 | # `files_ignore` input 66 | # Type: string 67 | files_ignore_from_source_file: '' 68 | 69 | # Separator used to split the `files_ignore` 70 | # input 71 | # Type: string 72 | # Default: "\n" 73 | files_ignore_separator: '' 74 | 75 | # Separator used to split the `files` 76 | # input 77 | # Type: string 78 | # Default: "\n" 79 | files_separator: '' 80 | 81 | # Include `all_old_new_renamed_files` output. Note this can 82 | # generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). 83 | # Type: boolean 84 | # Default: "false" 85 | include_all_old_new_renamed_files: '' 86 | 87 | # Output list of changed files in 88 | # a JSON formatted string which can 89 | # be used for matrix jobs. 90 | # Type: boolean 91 | # Default: "false" 92 | json: '' 93 | 94 | # Output list of changed files in 95 | # a raw format which means that 96 | # the output will not be surrounded 97 | # by quotes and special characters will 98 | # not be escaped. 99 | # Type: boolean 100 | # Default: "false" 101 | # Deprecated: Use `json_unescaped` instead. 102 | json_raw_format: '' 103 | 104 | # Output list of changed files in 105 | # a JSON formatted string without escaping 106 | # special characters. 107 | # Type: boolean 108 | # Default: "false" 109 | json_unescaped: '' 110 | 111 | # Boolean indicating whether to output input, 112 | # output and secret names as markdown 113 | # links 114 | # Type: boolean 115 | # Default: "false" 116 | markdown_links: '' 117 | 118 | # Indicates whether to include match directories 119 | # Type: boolean 120 | # Default: "true" 121 | match_directories: '' 122 | 123 | # Split character for old and new 124 | # renamed filename pairs. 125 | # Type: string 126 | # Default: " " 127 | old_new_files_separator: '' 128 | 129 | # Split character for old and new 130 | # filename pairs. 131 | # Type: string 132 | # Default: "," 133 | old_new_separator: '' 134 | 135 | # Directory to store output files. 136 | # Type: string 137 | # Default: ".github/outputs" 138 | output_dir: '' 139 | 140 | # Specify a relative path under `$GITHUB_WORKSPACE` 141 | # to locate the repository. 142 | # Type: string 143 | # Default: "." 144 | path: '' 145 | 146 | # Use non ascii characters to match 147 | # files and output the filenames completely 148 | # verbatim by setting this to `false` 149 | # Type: boolean 150 | # Default: "true" 151 | quotepath: '' 152 | 153 | # Split character for output strings. 154 | # Type: string 155 | # Default: "|" 156 | separator: '' 157 | 158 | # Specify a different commit SHA used 159 | # for comparing changes 160 | # Type: string 161 | sha: '' 162 | 163 | # Get changed files for commits whose 164 | # timestamp is older than the given 165 | # time. 166 | # Type: string 167 | since: '' 168 | 169 | # Use the last commit on the 170 | # remote branch as the `base_sha`. Defaults 171 | # to the last non merge commit 172 | # on the target branch for pull 173 | # request events and the previous remote 174 | # commit of the current branch for 175 | # push events. 176 | # Type: boolean 177 | # Default: "false" 178 | since_last_remote_commit: '' 179 | 180 | # The GitHub token to use for 181 | # authentication. 182 | # Type: string 183 | # Default: "${{ github.token }}" 184 | token: '' 185 | 186 | # Get changed files for commits whose 187 | # timestamp is earlier than the given 188 | # time. 189 | # Type: string 190 | until: '' 191 | 192 | # Write outputs to files in the 193 | # `.github/outputs` folder by default. 194 | # Type: boolean 195 | # Default: "false" 196 | write_output_files: '' 197 | 198 | ``` 199 | 200 | -------------------------------------------------------------------------------- /test/README-inputColumns.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | DESCRIPTION | 8 | |--------------------------------------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 9 | | base_sha | string | Specify a different base commit SHA
used for comparing changes | 10 | | diff_relative | string | Exclude changes outside the current directory
and show path names relative to
it. **NOTE:** This requires you to
specify the top level directory via
the `path` input. | 11 | | dir_names | string | Output unique changed directories instead of
filenames. **NOTE:** This returns `.` for
changed files located in the root
of the project. | 12 | | dir_names_max_depth | string | Maximum depth of directories to output.
e.g `test/test1/test2` with max depth of
`2` returns `test/test1`. | 13 | | fetch_depth | string | Depth of additional branch history fetched.
**NOTE**: This can be adjusted to
resolve errors with insufficient history. | 14 | | files | string | File and directory patterns to detect
changes using only these list of
file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns
should not include quotes. | 15 | | files_from_source_file | string | Source file(s) used to populate the
`files` input. | 16 | | files_ignore | string | Ignore changes to these file(s) **NOTE:**
Multiline file/directory patterns should not include
quotes. | 17 | | files_ignore_from_source_file | string | Source file(s) used to populate the
`files_ignore` input | 18 | | files_ignore_separator | string | Separator used to split the `files_ignore`
input | 19 | | files_separator | string | Separator used to split the `files`
input | 20 | | include_all_old_new_renamed_files | string | Include `all_old_new_renamed_files` output. Note this can
generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). | 21 | | json | string | Output list of changed files in
a JSON formatted string which can
be used for matrix jobs. | 22 | | ~~json_raw_format~~
Use `json_unescaped` instead. | string | **Deprecated:** Output list of changed files
in a raw format which means
that the output will not be
surrounded by quotes and special characters
will not be escaped. | 23 | | json_unescaped | string | Output list of changed files in
a JSON formatted string without escaping
special characters. | 24 | | markdown_links | string | Boolean indicating whether to output input,
output and secret names as markdown
links | 25 | | match_directories | string | Indicates whether to include match directories | 26 | | old_new_files_separator | string | Split character for old and new
renamed filename pairs. | 27 | | old_new_separator | string | Split character for old and new
filename pairs. | 28 | | output_dir | string | Directory to store output files. | 29 | | path | string | Specify a relative path under `$GITHUB_WORKSPACE`
to locate the repository. | 30 | | quotepath | string | Use non ascii characters to match
files and output the filenames completely
verbatim by setting this to `false` | 31 | | separator | string | Split character for output strings. | 32 | | sha | string | Specify a different commit SHA used
for comparing changes | 33 | | since | string | Get changed files for commits whose
timestamp is older than the given
time. | 34 | | since_last_remote_commit | string | Use the last commit on the
remote branch as the `base_sha`. Defaults
to the last non merge commit
on the target branch for pull
request events and the previous remote
commit of the current branch for
push events. | 35 | | token | string | The GitHub token to use for
authentication. | 36 | | until | string | Get changed files for commits whose
timestamp is earlier than the given
time. | 37 | | write_output_files | string | Write outputs to files in the
`.github/outputs` folder by default. | 38 | 39 | 40 | 41 | ## Outputs 42 | 43 | 44 | 45 | | OUTPUT | TYPE | DESCRIPTION | 46 | |--------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 47 | | added_files | string | Returns only files that are Added
(A). | 48 | | all_changed_and_modified_files | string | Returns all changed and modified files
i.e. *a combination of (ACMRDTUX)* | 49 | | all_changed_files | string | Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)* | 50 | | all_modified_files | string | Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*. | 51 | | all_old_new_renamed_files | string | Returns only files that are Renamed
and list their old and new
names. **NOTE:** This requires setting `include_all_old_new_renamed_files`
to `true` (R) | 52 | | any_changed | string | Returns `true` when any of the
filenames provided using the `files` input
has changed. If no `files` have
been specified,an empty string `''` is
returned. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. | 53 | | any_deleted | string | Returns `true` when any of the
filenames provided using the `files` input
has been deleted. If no `files`
have been specified,an empty string `''`
is returned. (D) | 54 | | any_modified | string | Returns `true` when any of the
filenames provided using the `files` input
has been modified. If no `files`
have been specified,an empty string `''`
is returned. i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*. | 55 | | copied_files | string | Returns only files that are Copied
(C). | 56 | | deleted_files | string | Returns only files that are Deleted
(D). | 57 | | modified_files | string | Returns only files that are Modified
(M). | 58 | | only_changed | string | Returns `true` when only files provided
using the `files` input has changed.
If no `files` have been specified,an
empty string `''` is returned. i.e.
*using a combination of all added, copied, modified and renamed files (ACMR)*. | 59 | | only_deleted | string | Returns `true` when only files provided
using the `files` input has been
deleted. If no `files` have been
specified,an empty string `''` is returned.
(D) | 60 | | only_modified | string | Returns `true` when only files provided
using the `files` input has been
modified. If no `files` have been
specified,an empty string `''` is returned.(ACMRD). | 61 | | other_changed_files | string | Returns all other changed files not
listed in the files input i.e.
*using a combination of all added, copied, modified and renamed files (ACMR)*. | 62 | | other_deleted_files | string | Returns all other deleted files not
listed in the files input i.e.
*a combination of all deleted files (D)* | 63 | | other_modified_files | string | Returns all other modified files not
listed in the files input i.e.
*a combination of all added, copied, modified, and deleted files (ACMRD)* | 64 | | renamed_files | string | Returns only files that are Renamed
(R). | 65 | | type_changed_files | string | Returns only files that have their
file type changed (T). | 66 | | unknown_files | string | Returns only files that are Unknown
(X). | 67 | | unmerged_files | string | Returns only files that are Unmerged
(U). | 68 | 69 | 70 | -------------------------------------------------------------------------------- /test/README-outputColumns.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | 8 | |--------------------------------------------------------|--------|----------|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 9 | | base_sha | string | false | | Specify a different base commit SHA
used for comparing changes | 10 | | diff_relative | string | false | | Exclude changes outside the current directory
and show path names relative to
it. **NOTE:** This requires you to
specify the top level directory via
the `path` input. | 11 | | dir_names | string | false | `"false"` | Output unique changed directories instead of
filenames. **NOTE:** This returns `.` for
changed files located in the root
of the project. | 12 | | dir_names_max_depth | string | false | | Maximum depth of directories to output.
e.g `test/test1/test2` with max depth of
`2` returns `test/test1`. | 13 | | fetch_depth | string | false | `"50"` | Depth of additional branch history fetched.
**NOTE**: This can be adjusted to
resolve errors with insufficient history. | 14 | | files | string | false | `"a.txt"`
`"b.txt"`
`"test.txt"`
| File and directory patterns to detect
changes using only these list of
file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns
should not include quotes. | 15 | | files_from_source_file | string | false | | Source file(s) used to populate the
`files` input. | 16 | | files_ignore | string | false | | Ignore changes to these file(s) **NOTE:**
Multiline file/directory patterns should not include
quotes. | 17 | | files_ignore_from_source_file | string | false | | Source file(s) used to populate the
`files_ignore` input | 18 | | files_ignore_separator | string | false | `"\n"` | Separator used to split the `files_ignore`
input | 19 | | files_separator | string | false | `"\n"` | Separator used to split the `files`
input | 20 | | include_all_old_new_renamed_files | string | false | `"false"` | Include `all_old_new_renamed_files` output. Note this can
generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). | 21 | | json | string | false | `"false"` | Output list of changed files in
a JSON formatted string which can
be used for matrix jobs. | 22 | | ~~json_raw_format~~
Use `json_unescaped` instead. | string | false | `"false"` | **Deprecated:** Output list of changed files
in a raw format which means
that the output will not be
surrounded by quotes and special characters
will not be escaped. | 23 | | json_unescaped | string | false | `"false"` | Output list of changed files in
a JSON formatted string without escaping
special characters. | 24 | | markdown_links | string | false | `"false"` | Boolean indicating whether to output input,
output and secret names as markdown
links | 25 | | match_directories | string | false | `"true"` | Indicates whether to include match directories | 26 | | old_new_files_separator | string | false | `" "` | Split character for old and new
renamed filename pairs. | 27 | | old_new_separator | string | false | `","` | Split character for old and new
filename pairs. | 28 | | output_dir | string | false | `".github/outputs"` | Directory to store output files. | 29 | | path | string | false | `"."` | Specify a relative path under `$GITHUB_WORKSPACE`
to locate the repository. | 30 | | quotepath | string | false | `"true"` | Use non ascii characters to match
files and output the filenames completely
verbatim by setting this to `false` | 31 | | separator | string | false | `"\|"` | Split character for output strings. | 32 | | sha | string | false | | Specify a different commit SHA used
for comparing changes | 33 | | since | string | false | | Get changed files for commits whose
timestamp is older than the given
time. | 34 | | since_last_remote_commit | string | true | `"false"` | Use the last commit on the
remote branch as the `base_sha`. Defaults
to the last non merge commit
on the target branch for pull
request events and the previous remote
commit of the current branch for
push events. | 35 | | token | string | false | `"${{ github.token }}"` | The GitHub token to use for
authentication. | 36 | | until | string | false | | Get changed files for commits whose
timestamp is earlier than the given
time. | 37 | | write_output_files | string | false | `"false"` | Write outputs to files in the
`.github/outputs` folder by default. | 38 | 39 | 40 | 41 | ## Outputs 42 | 43 | 44 | 45 | | OUTPUT | TYPE | 46 | |--------------------------------|--------| 47 | | added_files | string | 48 | | all_changed_and_modified_files | string | 49 | | all_changed_files | string | 50 | | all_modified_files | string | 51 | | all_old_new_renamed_files | string | 52 | | any_changed | string | 53 | | any_deleted | string | 54 | | any_modified | string | 55 | | copied_files | string | 56 | | deleted_files | string | 57 | | modified_files | string | 58 | | only_changed | string | 59 | | only_deleted | string | 60 | | only_modified | string | 61 | | other_changed_files | string | 62 | | other_deleted_files | string | 63 | | other_modified_files | string | 64 | | renamed_files | string | 65 | | type_changed_files | string | 66 | | unknown_files | string | 67 | | unmerged_files | string | 68 | 69 | 70 | -------------------------------------------------------------------------------- /test/README-reusable-inputColumns.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | DESCRIPTION | 8 | |-------------------------------------------|---------|------------------------------| 9 | | ~~bool_tested~~
Use `tested` instead | boolean | **Deprecated:** Test of bool | 10 | | config-path | string | The configuration path | 11 | | tested | boolean | Test of bool | 12 | | username | string | Username | 13 | 14 | 15 | 16 | ## Outputs 17 | 18 | 19 | 20 | | OUTPUT | VALUE | DESCRIPTION | 21 | |------------|---------------------------------------------|--------------------------| 22 | | firstword | `"${{ jobs.example_job.outputs.output1 }}"` | The first output string | 23 | | secondword | `"${{ jobs.example_job.outputs.output2 }}"` | The second output string | 24 | 25 | 26 | 27 | ## Secrets 28 | 29 | 30 | 31 | | SECRET | REQUIRED | DESCRIPTION | 32 | |--------|----------|-----------------------| 33 | | token | true | Repo scoped PAT token | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/README-reusable-markdownLinks.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | 8 | |-------------------------------------------------------------------------------------------------|---------|----------|-------------|------------------------------| 9 | | ~~[bool_tested](#input_bool_tested)~~
Use `tested` instead | boolean | false | `true` | **Deprecated:** Test of bool | 10 | | [config-path](#input_config-path) | string | true | | The configuration path | 11 | | [tested](#input_tested) | boolean | false | `false` | Test of bool | 12 | | [username](#input_username) | string | false | `"example"` | Username | 13 | 14 | 15 | 16 | ## Outputs 17 | 18 | 19 | 20 | | OUTPUT | VALUE | DESCRIPTION | 21 | |------------------------------------------------------------------|---------------------------------------------|--------------------------| 22 | | [firstword](#output_firstword) | `"${{ jobs.example_job.outputs.output1 }}"` | The first output string | 23 | | [secondword](#output_secondword) | `"${{ jobs.example_job.outputs.output2 }}"` | The second output string | 24 | 25 | 26 | 27 | ## Secrets 28 | 29 | 30 | 31 | | SECRET | REQUIRED | DESCRIPTION | 32 | |---------------------------------------------------|----------|-----------------------| 33 | | [token](#secret_token) | true | Repo scoped PAT token | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/README-reusable-outputColumns.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | 8 | |-------------------------------------------|---------|----------|-------------|------------------------------| 9 | | ~~bool_tested~~
Use `tested` instead | boolean | false | `true` | **Deprecated:** Test of bool | 10 | | config-path | string | true | | The configuration path | 11 | | tested | boolean | false | `false` | Test of bool | 12 | | username | string | false | `"example"` | Username | 13 | 14 | 15 | 16 | ## Outputs 17 | 18 | 19 | 20 | | OUTPUT | VALUE | 21 | |------------|---------------------------------------------| 22 | | firstword | `"${{ jobs.example_job.outputs.output1 }}"` | 23 | | secondword | `"${{ jobs.example_job.outputs.output2 }}"` | 24 | 25 | 26 | 27 | ## Secrets 28 | 29 | 30 | 31 | | SECRET | REQUIRED | DESCRIPTION | 32 | |--------|----------|-----------------------| 33 | | token | true | Repo scoped PAT token | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/README-reusable-secretColumns.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | 8 | |-------------------------------------------|---------|----------|-------------|------------------------------| 9 | | ~~bool_tested~~
Use `tested` instead | boolean | false | `true` | **Deprecated:** Test of bool | 10 | | config-path | string | true | | The configuration path | 11 | | tested | boolean | false | `false` | Test of bool | 12 | | username | string | false | `"example"` | Username | 13 | 14 | 15 | 16 | ## Outputs 17 | 18 | 19 | 20 | | OUTPUT | VALUE | DESCRIPTION | 21 | |------------|---------------------------------------------|--------------------------| 22 | | firstword | `"${{ jobs.example_job.outputs.output1 }}"` | The first output string | 23 | | secondword | `"${{ jobs.example_job.outputs.output2 }}"` | The second output string | 24 | 25 | 26 | 27 | ## Secrets 28 | 29 | 30 | 31 | | SECRET | DESCRIPTION | 32 | |--------|-----------------------| 33 | | token | Repo scoped PAT token | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/README-reusable.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | ## Inputs 4 | 5 | 6 | 7 | | INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | 8 | |-------------------------------------------|---------|----------|-------------|------------------------------| 9 | | ~~bool_tested~~
Use `tested` instead | boolean | false | `true` | **Deprecated:** Test of bool | 10 | | config-path | string | true | | The configuration path | 11 | | tested | boolean | false | `false` | Test of bool | 12 | | username | string | false | `"example"` | Username | 13 | 14 | 15 | 16 | ## Outputs 17 | 18 | 19 | 20 | | OUTPUT | VALUE | DESCRIPTION | 21 | |------------|---------------------------------------------|--------------------------| 22 | | firstword | `"${{ jobs.example_job.outputs.output1 }}"` | The first output string | 23 | | secondword | `"${{ jobs.example_job.outputs.output2 }}"` | The second output string | 24 | 25 | 26 | 27 | ## Secrets 28 | 29 | 30 | 31 | | SECRET | REQUIRED | DESCRIPTION | 32 | |--------|----------|-----------------------| 33 | | token | true | Repo scoped PAT token | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/README-workflow-empty-markers-no-inputs-no-outputs.expected.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | Test text ## Inputs 4 | 5 | ## Inputs 6 | 7 | 8 | No inputs. 9 | 10 | 11 | ## Outputs 12 | 13 | 14 | No outputs. 15 | 16 | 17 | ## Secrets 18 | 19 | 20 | No secrets. 21 | 22 | -------------------------------------------------------------------------------- /test/README-workflow-empty-markers.md: -------------------------------------------------------------------------------- 1 | # test 2 | 3 | Test text ## Inputs 4 | 5 | ## Inputs 6 | 7 | 8 | No inputs. 9 | 10 | 11 | ## Outputs 12 | 13 | 14 | No outputs. 15 | 16 | 17 | ## Secrets 18 | 19 | 20 | No secrets. 21 | 22 | -------------------------------------------------------------------------------- /test/action-no-inputs-no-outputs.yml: -------------------------------------------------------------------------------- 1 | name: Changed Files 2 | description: Get all Added, Copied, Modified, Deleted, Renamed, Type changed, Unmerged, Unknown files. 3 | author: tj-actions 4 | 5 | #inputs: [] 6 | 7 | runs: 8 | using: 'composite' 9 | steps: 10 | - run: | 11 | echo "Test" 12 | id: test 13 | shell: bash 14 | branding: 15 | icon: file-text 16 | color: white 17 | -------------------------------------------------------------------------------- /test/action.yml: -------------------------------------------------------------------------------- 1 | name: Changed Files 2 | description: Get all Added, Copied, Modified, Deleted, Renamed, Type changed, Unmerged, Unknown files and directories. 3 | author: tj-actions 4 | 5 | inputs: 6 | separator: 7 | description: "Split character for output strings." 8 | required: false 9 | default: "|" 10 | include_all_old_new_renamed_files: 11 | description: "Include `all_old_new_renamed_files` output. Note this can generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501)." 12 | required: false 13 | default: "false" 14 | old_new_separator: 15 | description: "Split character for old and new filename pairs." 16 | required: false 17 | default: "," 18 | old_new_files_separator: 19 | description: "Split character for old and new renamed filename pairs." 20 | required: false 21 | default: " " 22 | files_from_source_file: 23 | description: "Source file(s) used to populate the `files` input." 24 | required: false 25 | default: "" 26 | files: 27 | description: "File and directory patterns to detect changes using only these list of file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns should not include quotes." 28 | required: false 29 | default: | 30 | a.txt 31 | b.txt 32 | test.txt 33 | files_separator: 34 | description: "Separator used to split the `files` input" 35 | default: "\n" 36 | required: false 37 | files_ignore: 38 | description: "Ignore changes to these file(s) **NOTE:** Multiline file/directory patterns should not include quotes." 39 | required: false 40 | default: "" 41 | files_ignore_separator: 42 | description: "Separator used to split the `files_ignore` input" 43 | default: "\n" 44 | required: false 45 | files_ignore_from_source_file: 46 | description: "Source file(s) used to populate the `files_ignore` input" 47 | required: false 48 | default: "" 49 | sha: 50 | description: "Specify a different commit SHA used for comparing changes" 51 | required: false 52 | base_sha: 53 | description: "Specify a different base commit SHA used for comparing changes" 54 | required: false 55 | since: 56 | description: "Get changed files for commits whose timestamp is older than the given time." 57 | required: false 58 | default: "" 59 | until: 60 | description: "Get changed files for commits whose timestamp is earlier than the given time." 61 | required: false 62 | default: "" 63 | path: 64 | description: "Specify a relative path under `$GITHUB_WORKSPACE` to locate the repository." 65 | required: false 66 | default: "." 67 | quotepath: 68 | description: "Use non ascii characters to match files and output the filenames completely verbatim by setting this to `false`" 69 | default: "true" 70 | required: false 71 | diff_relative: 72 | description: "Exclude changes outside the current directory and show path names relative to it. **NOTE:** This requires you to specify the top level directory via the `path` input." 73 | required: false 74 | dir_names: 75 | default: "false" 76 | description: "Output unique changed directories instead of filenames. **NOTE:** This returns `.` for changed files located in the root of the project." 77 | required: false 78 | dir_names_max_depth: 79 | description: "Maximum depth of directories to output. e.g `test/test1/test2` with max depth of `2` returns `test/test1`." 80 | required: false 81 | json: 82 | description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs." 83 | required: false 84 | default: "false" 85 | json_raw_format: 86 | description: "Output list of changed files in a raw format which means that the output will not be surrounded by quotes and special characters will not be escaped." 87 | required: false 88 | default: "false" 89 | deprecationMessage: "Use `json_unescaped` instead." 90 | json_unescaped: 91 | description: "Output list of changed files in a JSON formatted string without escaping special characters." 92 | required: false 93 | default: "false" 94 | fetch_depth: 95 | description: "Depth of additional branch history fetched. **NOTE**: This can be adjusted to resolve errors with insufficient history." 96 | required: false 97 | default: "50" 98 | since_last_remote_commit: 99 | description: "Use the last commit on the remote branch as the `base_sha`. Defaults to the last non merge commit on the target branch for pull request events and the previous remote commit of the current branch for push events." 100 | required: true 101 | default: "false" 102 | write_output_files: 103 | description: "Write outputs to files in the `.github/outputs` folder by default." 104 | required: false 105 | default: "false" 106 | output_dir: 107 | description: "Directory to store output files." 108 | required: false 109 | default: ".github/outputs" 110 | match_directories: 111 | description: "Indicates whether to include match directories" 112 | default: "true" 113 | required: false 114 | markdown_links: 115 | description: "Boolean indicating whether to output input, output and secret names as markdown links" 116 | required: false 117 | default: "false" 118 | token: 119 | description: "The GitHub token to use for authentication." 120 | required: false 121 | default: ${{ github.token }} 122 | 123 | outputs: 124 | added_files: 125 | description: "Returns only files that are Added (A)." 126 | value: ${{ steps.changed-files.outputs.added_files }} 127 | copied_files: 128 | description: "Returns only files that are Copied (C)." 129 | value: ${{ steps.changed-files.outputs.copied_files }} 130 | deleted_files: 131 | description: "Returns only files that are Deleted (D)." 132 | value: ${{ steps.changed-files.outputs.deleted_files }} 133 | modified_files: 134 | description: "Returns only files that are Modified (M)." 135 | value: ${{ steps.changed-files.outputs.modified_files }} 136 | renamed_files: 137 | description: "Returns only files that are Renamed (R)." 138 | value: ${{ steps.changed-files.outputs.renamed_files }} 139 | all_old_new_renamed_files: 140 | description: "Returns only files that are Renamed and list their old and new names. **NOTE:** This requires setting `include_all_old_new_renamed_files` to `true` (R)" 141 | value: ${{ steps.changed-files.outputs.all_old_new_renamed_files }} 142 | type_changed_files: 143 | description: "Returns only files that have their file type changed (T)." 144 | value: ${{ steps.changed-files.outputs.type_changed_files }} 145 | unmerged_files: 146 | description: "Returns only files that are Unmerged (U)." 147 | value: ${{ steps.changed-files.outputs.unmerged_files }} 148 | unknown_files: 149 | description: "Returns only files that are Unknown (X)." 150 | value: ${{ steps.changed-files.outputs.unknown_files }} 151 | all_changed_and_modified_files: 152 | description: "Returns all changed and modified files i.e. *a combination of (ACMRDTUX)*" 153 | value: ${{ steps.changed-files.outputs.all_changed_and_modified_files }} 154 | all_changed_files: 155 | description: "Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)*" 156 | value: ${{ steps.changed-files.outputs.all_changed_files }} 157 | any_changed: 158 | description: "Returns `true` when any of the filenames provided using the `files` input has changed. If no `files` have been specified,an empty string `''` is returned. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*." 159 | value: ${{ steps.changed-files.outputs.any_changed }} 160 | only_changed: 161 | description: "Returns `true` when only files provided using the `files` input has changed. If no `files` have been specified,an empty string `''` is returned. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*." 162 | value: ${{ steps.changed-files.outputs.only_changed }} 163 | other_changed_files: 164 | description: "Returns all other changed files not listed in the files input i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*." 165 | value: ${{ steps.changed-files.outputs.other_changed_files }} 166 | all_modified_files: 167 | description: "Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*." 168 | value: ${{ steps.changed-files.outputs.all_modified_files }} 169 | any_modified: 170 | description: "Returns `true` when any of the filenames provided using the `files` input has been modified. If no `files` have been specified,an empty string `''` is returned. i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*." 171 | value: ${{ steps.changed-files.outputs.any_modified }} 172 | only_modified: 173 | description: "Returns `true` when only files provided using the `files` input has been modified. If no `files` have been specified,an empty string `''` is returned.(ACMRD)." 174 | value: ${{ steps.changed-files.outputs.only_modified }} 175 | other_modified_files: 176 | description: "Returns all other modified files not listed in the files input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)*" 177 | value: ${{ steps.changed-files.outputs.other_modified_files }} 178 | any_deleted: 179 | description: "Returns `true` when any of the filenames provided using the `files` input has been deleted. If no `files` have been specified,an empty string `''` is returned. (D)" 180 | value: ${{ steps.changed-files.outputs.any_deleted }} 181 | only_deleted: 182 | description: "Returns `true` when only files provided using the `files` input has been deleted. If no `files` have been specified,an empty string `''` is returned. (D)" 183 | value: ${{ steps.changed-files.outputs.only_deleted }} 184 | other_deleted_files: 185 | description: "Returns all other deleted files not listed in the files input i.e. *a combination of all deleted files (D)*" 186 | value: ${{ steps.changed-files.outputs.other_deleted_files }} 187 | 188 | 189 | runs: 190 | using: 'composite' 191 | steps: 192 | - run: | 193 | echo "Test" 194 | id: test 195 | shell: bash 196 | branding: 197 | icon: file-text 198 | color: white 199 | -------------------------------------------------------------------------------- /test/reusable-action.yml: -------------------------------------------------------------------------------- 1 | name: Reusable workflow example 2 | 3 | on: 4 | workflow_call: 5 | outputs: 6 | firstword: 7 | description: "The first output string" 8 | value: ${{ jobs.example_job.outputs.output1 }} 9 | secondword: 10 | description: "The second output string" 11 | value: ${{ jobs.example_job.outputs.output2 }} 12 | inputs: 13 | config-path: 14 | required: true 15 | type: string 16 | description: "The configuration path" 17 | username: 18 | required: false 19 | type: string 20 | description: "Username" 21 | default: "example" 22 | bool_tested: 23 | required: false 24 | type: boolean 25 | description: "Test of bool" 26 | deprecationMessage: "Use `tested` instead" 27 | default: true 28 | tested: 29 | required: false 30 | type: boolean 31 | description: "Test of bool" 32 | default: false 33 | secrets: 34 | token: 35 | required: true 36 | description: "Repo scoped PAT token" 37 | 38 | jobs: 39 | triage: 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/labeler@v4 43 | with: 44 | repo-token: ${{ secrets.token }} 45 | configuration-path: ${{ inputs.config-path }} 46 | example_job: 47 | name: Generate output 48 | runs-on: ubuntu-latest 49 | outputs: 50 | output1: ${{ steps.step1.outputs.firstword }} 51 | output2: ${{ steps.step2.outputs.secondword }} 52 | steps: 53 | - id: step1 54 | run: echo "::set-output name=firstword::hello" 55 | - id: step2 56 | run: echo "::set-output name=secondword::world" 57 | -------------------------------------------------------------------------------- /test/reusable-workflow-no-inputs-no-outputs.yml: -------------------------------------------------------------------------------- 1 | name: Reusable workflow example 2 | 3 | on: 4 | workflow_call: 5 | 6 | jobs: 7 | triage: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/labeler@v4 11 | with: 12 | repo-token: ${{ secrets.token }} 13 | configuration-path: ${{ inputs.config-path }} 14 | example_job: 15 | name: Generate output 16 | runs-on: ubuntu-latest 17 | outputs: 18 | output1: ${{ steps.step1.outputs.firstword }} 19 | output2: ${{ steps.step2.outputs.secondword }} 20 | steps: 21 | - id: step1 22 | run: echo "::set-output name=firstword::hello" 23 | - id: step2 24 | run: echo "::set-output name=secondword::world" 25 | --------------------------------------------------------------------------------