diff --git a/.github/workflows/build-and-review-pr.yml b/.github/workflows/build-and-review-pr.yml index dc22fa0..8d1dfa7 100644 --- a/.github/workflows/build-and-review-pr.yml +++ b/.github/workflows/build-and-review-pr.yml @@ -38,7 +38,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -103,16 +103,16 @@ jobs: - name: Checkout if: env.HAS_CODE_CHANGES == 'true' - uses: actions/checkout@v3 + uses: actions/checkout@v4 # ----------------------------------- # Check if action has been recompiled # ----------------------------------- - - name: If action has build step - Setup Node 16.x - uses: actions/setup-node@v3 + - name: If action has build step - Setup Node 20.x + uses: actions/setup-node@v4 if: env.HAS_CODE_CHANGES == 'true' && env.HAS_BUILD_STEP == 'true' with: - node-version: 16.x + node-version: 20.x - name: If action has build step - Build the action if: env.HAS_CODE_CHANGES == 'true' && env.HAS_BUILD_STEP == 'true' @@ -156,7 +156,7 @@ jobs: - name: Fail the workflow if there are any outstanding changes if: env.HAS_CODE_CHANGES == 'true' && (env.NEEDS_BUILD_COMMIT == 'true' || env.NEEDS_README_COMMIT == 'true') id: summary - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | @@ -224,7 +224,7 @@ jobs: NEXT_MAJOR_VERSION_NO_PREFIX: '' # Info for the repo we'll be testing git-version-lite against - TESTING_REPO: 'im-open/internal-repo-for-testing' + TESTING_REPO: 'im-open/internal-repo-for-testing-purple-actions' TEST_BRANCH: 'my-test-branch' # These is based on the fetch-depth not being set. git-version-lite starts from 0.0.0 when calculating the next version @@ -252,16 +252,16 @@ jobs: - name: Setup - Checkout testing repo in the root directory if: always() - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: main repository: ${{ env.TESTING_REPO }} ssh-key: ${{ secrets.SSH_KEY_TESTING_REPO }} - # fetch-depth: 0 # Do not use this because we want to test what happens when fetch-depth is not set + fetch-depth: 0 - name: Setup - Checkout this action (git-version-lite) into a 'gvl' subdirectory if: always() - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ./gvl @@ -326,10 +326,7 @@ jobs: - name: '-------------------------------------------------------------------------------------------------------' run: echo "" - - name: When a repo has all of its tags locally - run: git fetch -t - - - name: And a new version is requested with fallback-to-no-prefix set + - name: When a new version is requested with fallback-to-no-prefix set if: always() uses: ./gvl id: fallback @@ -396,7 +393,7 @@ jobs: NEXT_MAJOR_VERSION_NO_PREFIX: '' # Info for the repo we'll be testing git-version-lite against - TESTING_REPO: 'im-open/internal-repo-for-testing' + TESTING_REPO: 'im-open/internal-repo-for-testing-purple-actions' TEST_BRANCH: 'my-test-branch' # These NEXT tags are set based on the fetch-depth not being set, so @@ -422,7 +419,7 @@ jobs: - name: Setup - Checkout testing repo in the root directory if: always() - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: main repository: ${{ env.TESTING_REPO }} @@ -431,7 +428,7 @@ jobs: - name: Setup - Checkout this action (git-version-lite) into a 'gvl' subdirectory if: always() - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ./gvl @@ -598,7 +595,7 @@ jobs: NEXT_MAJOR_VERSION_NO_PREFIX: '' # Info for the repo we'll be testing git-version-lite against - TESTING_REPO: 'im-open/internal-repo-for-testing' + TESTING_REPO: 'im-open/internal-repo-for-testing-purple-actions' TEST_BRANCH: 'my-test-branch' # All the remaining tags are for TESTING_REPO. If anything changes tag-wise in that repo, these values need to be updated. @@ -705,7 +702,7 @@ jobs: - name: Setup - Checkout testing repo in the root directory if: always() - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: main repository: ${{ env.TESTING_REPO }} @@ -714,7 +711,7 @@ jobs: - name: Setup - Checkout this action (git-version-lite) into a 'gvl' subdirectory if: always() - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ./gvl diff --git a/.github/workflows/increment-version-on-merge.yml b/.github/workflows/increment-version-on-merge.yml index 971e57e..0d6812c 100644 --- a/.github/workflows/increment-version-on-merge.yml +++ b/.github/workflows/increment-version-on-merge.yml @@ -1,120 +1,120 @@ -name: Increment Version on Merge -run-name: "${{ github.event.pull_request.merged && 'Increment version for' || 'Closing' }} PR #${{ github.event.pull_request.number }}" -on: - # https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ - # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token - # - # GitHub's standard pull_request workflow trigger prevents write permissions and - # secrets access when the PR is from a public fork. PRs from branches and forks of - # internal/private repos are not limited the same way for the pull_request trigger. - # - # The pull_request_target trigger (which this workflow is using) relaxes some of those - # restrictions and allows PRs from public forks to have write permissions through the - # GH_TOKEN which we need in order to push new tags to the repo through this workflow. - # - # For this workflow, the elevated permissions should not be a problem because: - # • This workflow is only triggered when a PR is closed and the reusable workflow it - # calls only executes if it has been merged to the default branch. This means the PR - # has been reviewed and approved by a CODEOWNER and merged by someone with Write - # access before this workflow with its elevated permissions gets executed. Any code - # that doesn't meet our standards should be caught before it gets to this point. - # • The "Require approval for all outside collaborators" setting is set at the org-level. - # Before a workflow can execute for a PR generated by an outside collaborator, a user - # with Write access must manually approve the request to execute the workflow run. - # Prior to doing so they should have had a chance to review any changes in the PR - pull_request_target: - types: [closed] - # paths: - # Do not include specific paths here. reusable-increment-version-on-merge.yml will decide - # if this action should be incremented and if new tags should be pushed to the repo based - # on the same criteria used in the build-and-review-pr.yml workflow. - - -# ------------------------------------------------------------------------------------ -# NOTE: This repo duplicates the reusable increment workflow in im-open/.github that -# the rest of the actions use. If changes are needed in this workflow they -# should also be made in im-open/.github. This workflow is duplicated because -# it uses the local copy of itself in the workflow which allows us to test the -# increment build with git-version-lite changes before we merge those changes. -# ------------------------------------------------------------------------------------ - -jobs: - increment-version: - runs-on: ubuntu-latest - env: - MERGE_TO_MAIN: 'false' - - steps: - - name: Check if merge to default branch - id: merge - uses: actions/github-script@v6 - with: - script: | - const defaultBranch = 'main'; - const baseRef = '${{ github.event.pull_request.base.ref }}'; - const merged = ${{ github.event.pull_request.merged }}; - - if (!merged){ - console.log('PR is not merged. Skipping subsequent steps.'); - core.exportVariable('MERGE_TO_MAIN', false); - return; - } - if (baseRef !== defaultBranch){ - console.log(`PR is merged to ${baseRef} and not ${defaultBranch}. Skipping subsequent steps.`); - core.exportVariable('MERGE_TO_MAIN', false); - return; - } - console.log(`PR is merged to ${defaultBranch}. Proceed with subsequent steps.`); - core.exportVariable('MERGE_TO_MAIN', true); - - - name: Checkout - if: env.MERGE_TO_MAIN == 'true' - uses: actions/checkout@v3 - - - name: If PR is merged to main - Check for code changes to the action source code - if: env.MERGE_TO_MAIN == 'true' - id: source-code - uses: im-open/did-custom-action-code-change@v1 - with: - files-with-code: 'action.yml,package.json,package-lock.json' - folders-with-code: 'src,dist' - token: ${{ secrets.GITHUB_TOKEN }} - - - name: If PR is merged to main - Print whether Action Source Code Changed (open for details) - if: env.MERGE_TO_MAIN == 'true' - run: | - if [ "${{ steps.source-code.outputs.HAS_CHANGES }}" == "true" ]; then - echo "This PR changes the action's source code. Proceed with subsequent steps." - else - echo "This PR does not change the action's source code. Skipping subsequent steps." - fi - - - name: If PR is merged to main & PR has source code changes - Checkout - if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' - uses: actions/checkout@v3 - with: - ref: main - fetch-depth: 0 - - - name: If PR is merged to main & PR has source code changes - Get the next version for the repo - if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' - id: version - uses: ./ - - - name: If PR is merged to main & PR has source code changes - Print action version (${{ steps.version.outputs.NEXT_VERSION || 'N/A'}}) - if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' - run: echo "The next action version will be - ${{ steps.version.outputs.NEXT_VERSION }}" - - - name: If PR is merged to main & PR has source code changes - Push tags to repo - if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' - run: | - git config user.name github-actions - git config user.email github-actions@github.com - - git tag ${{ steps.version.outputs.NEXT_VERSION }} ${{ github.sha }} - git tag -f ${{ steps.version.outputs.NEXT_MAJOR_VERSION }} ${{ github.sha }} - git tag -f ${{ steps.version.outputs.NEXT_MINOR_VERSION }} ${{ github.sha }} - - git push origin ${{ steps.version.outputs.NEXT_VERSION }} - git push origin ${{ steps.version.outputs.NEXT_MAJOR_VERSION }} -f - git push origin ${{ steps.version.outputs.NEXT_MINOR_VERSION }} -f +name: Increment Version on Merge +run-name: "${{ github.event.pull_request.merged && 'Increment version for' || 'Closing' }} PR #${{ github.event.pull_request.number }}" +on: + # https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ + # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token + # + # GitHub's standard pull_request workflow trigger prevents write permissions and + # secrets access when the PR is from a public fork. PRs from branches and forks of + # internal/private repos are not limited the same way for the pull_request trigger. + # + # The pull_request_target trigger (which this workflow is using) relaxes some of those + # restrictions and allows PRs from public forks to have write permissions through the + # GH_TOKEN which we need in order to push new tags to the repo through this workflow. + # + # For this workflow, the elevated permissions should not be a problem because: + # • This workflow is only triggered when a PR is closed and the reusable workflow it + # calls only executes if it has been merged to the default branch. This means the PR + # has been reviewed and approved by a CODEOWNER and merged by someone with Write + # access before this workflow with its elevated permissions gets executed. Any code + # that doesn't meet our standards should be caught before it gets to this point. + # • The "Require approval for all outside collaborators" setting is set at the org-level. + # Before a workflow can execute for a PR generated by an outside collaborator, a user + # with Write access must manually approve the request to execute the workflow run. + # Prior to doing so they should have had a chance to review any changes in the PR + pull_request_target: + types: [closed] + # paths: + # Do not include specific paths here. reusable-increment-version-on-merge.yml will decide + # if this action should be incremented and if new tags should be pushed to the repo based + # on the same criteria used in the build-and-review-pr.yml workflow. + + +# ------------------------------------------------------------------------------------ +# NOTE: This repo duplicates the reusable increment workflow in im-open/.github that +# the rest of the actions use. If changes are needed in this workflow they +# should also be made in im-open/.github. This workflow is duplicated because +# it uses the local copy of itself in the workflow which allows us to test the +# increment build with git-version-lite changes before we merge those changes. +# ------------------------------------------------------------------------------------ + +jobs: + increment-version: + runs-on: ubuntu-latest + env: + MERGE_TO_MAIN: 'false' + + steps: + - name: Check if merge to default branch + id: merge + uses: actions/github-script@v7 + with: + script: | + const defaultBranch = 'main'; + const baseRef = '${{ github.event.pull_request.base.ref }}'; + const merged = ${{ github.event.pull_request.merged }}; + + if (!merged){ + console.log('PR is not merged. Skipping subsequent steps.'); + core.exportVariable('MERGE_TO_MAIN', false); + return; + } + if (baseRef !== defaultBranch){ + console.log(`PR is merged to ${baseRef} and not ${defaultBranch}. Skipping subsequent steps.`); + core.exportVariable('MERGE_TO_MAIN', false); + return; + } + console.log(`PR is merged to ${defaultBranch}. Proceed with subsequent steps.`); + core.exportVariable('MERGE_TO_MAIN', true); + + - name: Checkout + if: env.MERGE_TO_MAIN == 'true' + uses: actions/checkout@v4 + + - name: If PR is merged to main - Check for code changes to the action source code + if: env.MERGE_TO_MAIN == 'true' + id: source-code + uses: im-open/did-custom-action-code-change@v1 + with: + files-with-code: 'action.yml,package.json,package-lock.json' + folders-with-code: 'src,dist' + token: ${{ secrets.GITHUB_TOKEN }} + + - name: If PR is merged to main - Print whether Action Source Code Changed (open for details) + if: env.MERGE_TO_MAIN == 'true' + run: | + if [ "${{ steps.source-code.outputs.HAS_CHANGES }}" == "true" ]; then + echo "This PR changes the action's source code. Proceed with subsequent steps." + else + echo "This PR does not change the action's source code. Skipping subsequent steps." + fi + + - name: If PR is merged to main & PR has source code changes - Checkout + if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + + - name: If PR is merged to main & PR has source code changes - Get the next version for the repo + if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' + id: version + uses: ./ + + - name: If PR is merged to main & PR has source code changes - Print action version (${{ steps.version.outputs.NEXT_VERSION || 'N/A'}}) + if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' + run: echo "The next action version will be - ${{ steps.version.outputs.NEXT_VERSION }}" + + - name: If PR is merged to main & PR has source code changes - Push tags to repo + if: env.MERGE_TO_MAIN == 'true' && steps.source-code.outputs.HAS_CHANGES == 'true' + run: | + git config user.name github-actions + git config user.email github-actions@github.com + + git tag ${{ steps.version.outputs.NEXT_VERSION }} ${{ github.sha }} + git tag -f ${{ steps.version.outputs.NEXT_MAJOR_VERSION }} ${{ github.sha }} + git tag -f ${{ steps.version.outputs.NEXT_MINOR_VERSION }} ${{ github.sha }} + + git push origin ${{ steps.version.outputs.NEXT_VERSION }} + git push origin ${{ steps.version.outputs.NEXT_MAJOR_VERSION }} -f + git push origin ${{ steps.version.outputs.NEXT_MINOR_VERSION }} -f diff --git a/README.md b/README.md index fa0bd05..f19a3ab 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # git-version-lite -This template can be used to calculate a release or pre-release version. +This template can be used to calculate a release or pre-release version. ## Index @@ -28,7 +28,7 @@ This action relies on git history in order to determine the next version. This ## Release vs Pre-release -You can control whether the action will generate a release or pre-release next version with the `calculate-prerelease-version` flag. The pre-release versions are intended for use with branches and a branch name is required to generate one. +You can control whether the action will generate a release or pre-release next version with the `calculate-prerelease-version` flag. The pre-release versions are intended for use with branches and a branch name is required to generate one. - Release version format: `major.minor.patch` (`1.0.0`) - Pre-release version format: `major.minor.patch-.` (`0.1.0-my-branch.210907164247`) @@ -92,15 +92,15 @@ Each of the outputs are available as environment variables and as action outputs - The `github-token` input was removed - This was only needed to create a ref on the repository so it is no longer needed. - The `NEXT_VERSION_SHA` output was removed - - Workflows can use the value that git-version-lite outputted directly. - - For `pull_request` workflow triggers the value was `github.event.pull_request.head.sha`. + - Workflows can use the value that git-version-lite outputted directly. + - For `pull_request` workflow triggers the value was `github.event.pull_request.head.sha`. - For all other workflow triggers the value was `github.sha` ## Usage Examples ```yml on: - pull_request: + pull_request: jobs: get-prerelease-version: @@ -110,20 +110,20 @@ jobs: NEXT_VERSION: ${{ steps.get-version.outputs.NEXT_VERSION }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Includes all history for all branches and tags - id: get-version # You may also reference just the major version. - uses: im-open/git-version-lite@v3.0.0 + uses: im-open/git-version-lite@v3.1.0 with: calculate-prerelease-version: true branch-name: ${{ github.head_ref }} # github.head_ref works when the trigger is pull_request tag-prefix: v # Prepend a v to any calculated release/pre-release version fallback-to-no-prefix-search: true # Set to true can be helpful when starting to add tag prefixes default-release-type: major # If no tags are found, default to doing a major increment - + - run: | echo "The next version is ${{ env.NEXT_VERSION }}" echo "The next version without the prefix is ${{ steps.get-version.outputs.NEXT_VERSION_NO_PREFIX }}" @@ -154,7 +154,7 @@ This repo uses [git-version-lite] in its workflows to examine commit messages to ### Source Code Changes -The files and directories that are considered source code are listed in the `files-with-code` and `dirs-with-code` arguments in both the [build-and-review-pr] and [increment-version-on-merge] workflows. +The files and directories that are considered source code are listed in the `files-with-code` and `dirs-with-code` arguments in both the [build-and-review-pr] and [increment-version-on-merge] workflows. If a PR contains source code changes, the README.md should be updated with the latest action version and the action should be recompiled. The [build-and-review-pr] workflow will ensure these steps are performed when they are required. The workflow will provide instructions for completing these steps if the PR Author does not initially complete them. @@ -175,7 +175,7 @@ If changes are made to the action's [source code], the [usage examples] section ### Tests -The [build-and-review-pr] workflow includes tests which are linked to a status check. That status check needs to succeed before a PR is merged to the default branch. When a PR comes from a branch, the workflow has access to secrets which are required to run the tests successfully. +The [build-and-review-pr] workflow includes tests which are linked to a status check. That status check needs to succeed before a PR is merged to the default branch. When a PR comes from a branch, the workflow has access to secrets which are required to run the tests successfully. When a PR comes from a fork, the workflow cannot access any secrets, so the tests won't have the necessary permissions to run. When a PR comes from a fork, the changes should be reviewed, then merged into an intermediate branch by repository owners so tests can be run against the PR changes. Once the tests have passed, changes can be merged into the default branch. diff --git a/action.yml b/action.yml index c0da68e..79f2cbc 100644 --- a/action.yml +++ b/action.yml @@ -26,32 +26,32 @@ inputs: description: 'The default release type that should be used when no tags are detected. Defaults to major. Accepted values: major|minor|patch' required: false default: 'major' - + outputs: NEXT_VERSION: description: 'The calculated next version.' - + NEXT_VERSION_NO_PREFIX: description: 'The calculated next version without the tag prefix.' - + NEXT_MINOR_VERSION: description: 'The next major.minor version.' - + NEXT_MINOR_VERSION_NO_PREFIX: description: 'The next major.minor version without the tag prefix.' - + NEXT_MAJOR_VERSION: description: 'The next major version.' - + NEXT_MAJOR_VERSION_NO_PREFIX: description: 'The next major version without the tag prefix.' - + PRIOR_VERSION: description: 'The previous major.minor.patch version.' - + PRIOR_VERSION_NO_PREFIX: description: 'The previous major.minor.patch version without the tag prefix.' runs: - using: 'node16' + using: 'node20' main: 'dist/index.js'