Regenerate Lockfiles #44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Regenerate Lockfiles | |
| permissions: | |
| actions: read | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| resolves: | |
| description: Regenerate lockfiles only for the resolves in this comma-separated list, or for all resolves if this is empty. | |
| required: false | |
| type: string | |
| default: "" | |
| pr: | |
| description: Push regenerated lockfiles to the branch of this PR (Use 'new' to open a new PR). | |
| required: true | |
| type: string | |
| env: | |
| # logs and screenshots go in {OUTPUT_BASE_DIR}/lockfile-{resolve}/ (where "lockfile-{resolve}" is the artifact name) | |
| OUTPUT_BASE_DIR: dist/lockfiles # /dist/ is in .gitignore | |
| # We upload the diff image(s) (terminal screenshot(s)) to S3 so we can use it in GitHub flavored markdown. | |
| AWS_REGION: us-west-2 # Oregon | |
| AWS_ACCOUNT_ID: "053075847820" | |
| AWS_S3_BUCKET: st2-gha | |
| AWS_S3_BUCKET_ROOT: ${{ github.repository }}/runs/${{ github.run_id }} | |
| defaults: | |
| run: | |
| shell: bash | |
| #working-directory: # defaults to ${{ github.workspace }} | |
| jobs: | |
| resolves: | |
| name: Preprocess input var - resolves | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| JSON: ${{ steps.resolves.outputs.JSON }} | |
| LOCKFILES: ${{ steps.resolves.outputs.LOCKFILES }} | |
| steps: | |
| - name: Validate input var - resolves | |
| run: | | |
| if [[ "${{ inputs.resolves }}" =~ ^([a-z0-9-]+(,[a-z0-9-]+)*|)$ ]]; then | |
| echo "VALID INPUT: resolves" | |
| exit 0 | |
| else | |
| echo "INVALID INPUT: resolves" | |
| echo "resolves must be a comma separated list of resolve names, or an empty string" | |
| exit 1 | |
| fi | |
| - name: Get resolves in JSON | |
| id: resolves | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| pants_toml=$( | |
| gh api -X GET \ | |
| 'repos/${{ github.repository }}/contents/pants.toml' \ | |
| -f 'ref=${{ github.sha }}' \ | |
| --jq $'.content' | base64 -d | |
| ) | |
| LOCKFILES=$(yq -e -p toml '.python.resolves' -o json -I 0 <<< "${pants_toml}") | |
| if [[ "${{ inputs.resolves }}" != "" ]]; then | |
| JSON=$(jq -c '.|split(",")' <<< '"${{ inputs.resolves }}"') | |
| else | |
| # Pull pants.toml from the branch that the workflow runs from | |
| JSON=$(yq -e -p toml '.python.resolves|keys' -o json -I 0 <<< "${pants_toml}") | |
| fi | |
| echo "JSON=${JSON}" | tee -a "${GITHUB_OUTPUT}" | |
| echo "LOCKFILES=${LOCKFILES}" | tee -a "${GITHUB_OUTPUT}" | |
| pr: | |
| name: Preprocess input var - pr | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| JSON: ${{ steps.pr.outputs.JSON }} | |
| CHECKOUT_REF: ${{ steps.pr.outputs.CHECKOUT_REF }} | |
| PR_REPO: ${{ steps.pr.outputs.PR_REPO }} | |
| PR_REF: ${{ steps.pr.outputs.PR_REF }} | |
| PR_BASE_REF: ${{ steps.pr.outputs.PR_BASE_REF }} | |
| steps: | |
| - name: Validate input var - pr | |
| run: | | |
| if [ "${{ inputs.pr }}" = new ]; then | |
| echo "VALID INPUT: pr" | |
| echo "The next step will collect some data for PR creation." | |
| exit 0 | |
| elif [[ "${{ inputs.pr }}" =~ ^[0-9]+$ ]]; then | |
| echo "VALID INPUT: pr" | |
| echo "The next step will validate that PR #${{ inputs.pr }} exists." | |
| exit 0 | |
| else | |
| echo "INVALID INPUT: pr" | |
| echo "pr must be a PR number, or the magic string 'new'." | |
| exit 1 | |
| fi | |
| - name: Get pr in JSON | |
| id: pr | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_FIELDS: "\ | |
| id,\ | |
| number,\ | |
| url,\ | |
| closed,\ | |
| author,\ | |
| maintainerCanModify,\ | |
| headRepositoryOwner,\ | |
| headRepository,\ | |
| headRefName,\ | |
| baseRefName" | |
| run: | | |
| if [[ "${{ inputs.pr }}" == new ]]; then | |
| echo "Planning new Pull Request metadata ..." | |
| PR=$( | |
| yq -e -p yaml . -o json -I 0 \ | |
| <<HEREYAML | |
| id: "" | |
| number: "new" | |
| url: "" | |
| closed: false | |
| author: # see https://api.github.com/users/github-actions[bot] | |
| id: 41898282 | |
| is_bot: true | |
| login: "github-actions[bot]" | |
| name: "github-actions[bot]" | |
| maintainerCanModify: true | |
| headRepositoryOwner: | |
| id: "${GITHUB_REPOSITORY_OWNER_ID}" | |
| login: "${GITHUB_REPOSITORY_OWNER}" | |
| headRepository: | |
| id: "${GITHUB_REPOSITORY_ID}" | |
| name: "${GITHUB_REPOSITORY#*/}" | |
| headRefName: "regen-lockfiles-${GITHUB_RUN_ID}" | |
| baseRefName: "${GITHUB_REF_NAME}" | |
| HEREYAML | |
| ) | |
| CHECKOUT_REF="${GITHUB_REF}" | |
| else | |
| CHECKOUT_REF="refs/pull/${{ inputs.pr }}/merge" | |
| echo "Searching for Pull Request #${{ inputs.pr }} ..." | |
| PR=$(gh pr view "${{ inputs.pr }}" --json "${PR_FIELDS}") | |
| pr_search_rc=$? | |
| if [ ${pr_search_rc} -gt 0 ]; then | |
| echo "Pull Request #${{ inputs.pr }} not found!" | |
| exit 2 | |
| elif (jq -e .closed <<< "${PR}" >/dev/null); then | |
| echo "Pull Request #${{ inputs.pr }} is closed!" | |
| exit 3 | |
| elif ! (jq -e .maintainerCanModify <<< "${PR}" >/dev/null); then | |
| echo "Pull Request #${{ inputs.pr }} does not allow maintainer modification!" | |
| exit 4 | |
| fi | |
| echo "Found Pull Request #${{ inputs.pr }} by @$(jq -r .author.login <<< "${PR}")" | |
| echo "URL: $(jq -r .url <<< "${PR}")" | |
| fi | |
| echo "JSON=${PR}" | tee -a "${GITHUB_OUTPUT}" | |
| echo "CHECKOUT_REF=${CHECKOUT_REF}" | tee -a "${GITHUB_OUTPUT}" | |
| PR_REPO=$(jq -r '.headRepositoryOwner.login + "/" + .headRepository.name' <<< "${PR}") | |
| PR_REF=$(jq -r '.headRefName' <<< "${PR}") | |
| PR_BASE_REF=$(jq -r '.baseRefName' <<< "${PR}") | |
| echo "PR_REPO=${PR_REPO}" | tee -a "${GITHUB_OUTPUT}" | |
| echo "PR_REF=${PR_REF}" | tee -a "${GITHUB_OUTPUT}" | |
| echo "PR_BASE_REF=${PR_BASE_REF}" | tee -a "${GITHUB_OUTPUT}" | |
| echo "Pull from ${PR_REPO}:${PR_REF} into ${PR_BASE_REF}" | |
| regenerate: | |
| name: Regenerate ${{ matrix.resolve }} lockfile | |
| needs: [resolves, pr] | |
| runs-on: ubuntu-22.04 | |
| strategy: | |
| matrix: | |
| resolve: ${{ fromJSON(needs.resolves.outputs.JSON) }} | |
| env: | |
| LOCKFILE: ${{ fromJSON(needs.resolves.outputs.LOCKFILES)[matrix.resolve] }} | |
| # see also the 'Setup env' step | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # a test uses a submodule, and pants needs access to it to calculate deps. | |
| submodules: 'true' | |
| ref: ${{ needs.pr.outputs.CHECKOUT_REF }} | |
| - name: Initialize Pants and its GHA caches | |
| uses: ./.github/actions/init-pants | |
| with: | |
| # To ignore a bad cache, bump the cache* integer. | |
| gha-cache-key: cache0-BUILD | |
| # This step exists because we cannot use the 'env' context in 'jobs.<job>.env.*'. | |
| - name: Setup env | |
| # We only need stderr, because generate-lockfiles puts the diff on stderr. | |
| # Nothing else should be on stderr because Pants disables logging to stderr when | |
| # it detects the stderr redirection. (NOTE: stdout should be empty.) | |
| run: | | |
| echo "OUTPUT_DIR=${{ env.OUTPUT_BASE_DIR }}/lockfile-${{ matrix.resolve }}" >> ${GITHUB_ENV} | |
| echo "STDERR_LOG=${{ env.OUTPUT_BASE_DIR }}/lockfile-${{ matrix.resolve }}/stderr.log" >> ${GITHUB_ENV} | |
| - name: Regenerate ${{ matrix.resolve }} lockfile | |
| id: lockfile | |
| env: | |
| PR_BASE_REF: ${{ needs.pr.outputs.PR_BASE_REF }} | |
| PANTS_STATS_LOG: 'False' | |
| PANTS_LEVEL: warn # skip info-level log messages | |
| run: | | |
| mkdir -p "${OUTPUT_DIR}/" | |
| git checkout "${{ env.PR_BASE_REF }}" -- "${LOCKFILE}" # diff is for whole PR not just a commit. | |
| pants generate-lockfiles '--resolve=${{ matrix.resolve }}' 2> >(tee "${STDERR_LOG}" >&2 ) | |
| cp "${LOCKFILE}" "${OUTPUT_DIR}/" | |
| CHANGED=$( | |
| if git diff "${{ env.PR_BASE_REF }}" --exit-code --quiet -- "${LOCKFILE}"; then | |
| echo "false" | |
| else | |
| echo "true" | |
| fi | |
| ) | |
| echo "CHANGED=${CHANGED}" | tee -a "${GITHUB_OUTPUT}" | |
| # The last job's outputs overwrite the outputs of other jobs in matrix. | |
| # So, matrix jobs should not use job outputs. Workaround: use artifacts. | |
| echo "${CHANGED}" > "${OUTPUT_DIR}/$(basename "${LOCKFILE}").CHANGED" | |
| - name: Install rsvg-convert and JetBrains Mono font for freeze | |
| if: steps.lockfile.outputs.CHANGED == 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| # rsvg-convert doesn't cause a panic like the resvg lib freeze uses, and it's faster. | |
| # But, rsvg-convert doesn't handle woff font freeze embeds in the svg, so install the font. | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Use-Pty=0 install librsvg2-bin | |
| # Font install based on: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/install_manual.sh | |
| gh release download "v2.304" \ | |
| -R "JetBrains/JetBrainsMono" \ | |
| --pattern "JetBrainsMono-*.zip" \ | |
| --output "${RUNNER_TEMP}/JetBrainsMono.zip" | |
| mkdir -p ~/.local/share/fonts | |
| unzip -o "${RUNNER_TEMP}/JetBrainsMono.zip" -d ~/.local/share/fonts | |
| fc-cache -f | |
| - name: Install freeze | |
| if: steps.lockfile.outputs.CHANGED == 'true' | |
| env: | |
| VERSION: '0.2.2' | |
| GOARCH: ${{ fromJSON('{"X86":"i386","X64":"x86_64","ARM":"arm","ARM64":"arm64"}')[runner.arch] }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| gh release download "v${VERSION}" \ | |
| -R "charmbracelet/freeze" \ | |
| --pattern "freeze_*_${RUNNER_OS}_${GOARCH}.tar.gz" \ | |
| --output "${RUNNER_TEMP}/freeze.tar.gz" | |
| tar xzf "${RUNNER_TEMP}/freeze.tar.gz" \ | |
| -C ~/.local/bin \ | |
| --strip-components=1 \ | |
| --wildcards \ | |
| '*/freeze' | |
| [[ -x ~/.local/bin/freeze ]] || chmod +x ~/.local/bin/freeze | |
| - name: Freeze lockfile diff as picture | |
| if: steps.lockfile.outputs.CHANGED == 'true' | |
| # For samples of the themes freeze can use when generating a "terminal screenshot", see: | |
| # - "charm" theme (default): https://github.com/charmbracelet/freeze | |
| # - all other themes: https://xyproto.github.io/splash/docs/ | |
| env: | |
| # Freeze processes the output line-by-line, so the ansi escape sequences | |
| # that span multiple lines only apply to the first line. | |
| # This sed script repeats those ansi escape sequences on each line. | |
| SED_SCRIPT: | | |
| s/^\x1B\[4m \+$/\0\x1B[0m/ # append ansi reset on line above heading | |
| s/^== .* ==$/\x1B[4m\0\x1B[0m/ # add ansi underline to headling | |
| s/^\x1b\[0m$// # drop ansi reset after the heading | |
| run: | | |
| for theme in github github-dark; do | |
| for ext in svg png; do | |
| # The diff output applies ansi underlines across multiple lines, but freeze formats | |
| # each line separately. So, use sed to repeat ansi chars per line. | |
| sed -e "${SED_SCRIPT}" "${STDERR_LOG}" \ | |
| | freeze --config full --language ansi --theme "${theme}" --width 720 \ | |
| --output "${STDERR_LOG}.${theme}.${ext}" - | |
| done | |
| done | |
| - name: Configure AWS Credentials | |
| uses: aws-actions/configure-aws-credentials@v5.0.0 | |
| with: | |
| aws-region: ${{ env.AWS_REGION }} | |
| role-session-name: GitHubActions-${{ github.run_id }} | |
| role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/GitHubActions@org=${{ github.repository_owner }},repo=${{ github.event.repository.name }} | |
| allowed-account-ids: ${{ env.AWS_ACCOUNT_ID }} | |
| # This should be the minimal set of permissions needed by this workflow. | |
| inline-session-policy: >- | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Sid": "AllowPutObject", | |
| "Effect": "Allow", | |
| "Action": ["s3:PutObject", "s3:PutObjectTagging"], | |
| "Resource": ["arn:aws:s3:::${{ env.AWS_S3_BUCKET }}/${{ env.AWS_S3_BUCKET_ROOT }}/*"] | |
| } | |
| ] | |
| } | |
| - name: Upload lockfile diff picture to S3 | |
| # GitHub flavored markdown does not accept data:image/png URIs for images. | |
| # And GitHub does not provide any convenient APIs for uploading image assets. | |
| # So, we upload to AWS and save the URI for in generated markdown below. | |
| if: steps.lockfile.outputs.CHANGED == 'true' | |
| # NOTE: The packaged s3 actions are too old, incomplete, or do not allow setting content-type + tags. | |
| env: | |
| AWS_S3_PATH: ${{ env.AWS_S3_BUCKET_ROOT }}/lockfile-${{ matrix.resolve }} | |
| run: | | |
| aws s3 cp \ | |
| "${STDERR_LOG}.github-dark.png" \ | |
| "s3://${{ env.AWS_S3_BUCKET }}/${{ env.AWS_S3_PATH }}/" \ | |
| --content-type image/png | |
| aws s3api put-object-tagging \ | |
| --expected-bucket-owner "${AWS_ACCOUNT_ID}" \ | |
| --bucket "${{ env.AWS_S3_BUCKET }}" \ | |
| --key "${{ env.AWS_S3_PATH }}/$(basename ${STDERR_LOG}.github-dark.png)" \ | |
| --tagging '{"TagSet":[{"Key":"Service","Value":"GitHub Actions"}]}' | |
| - name: Prepare text-only lockfile diff for commit message | |
| if: steps.lockfile.outputs.CHANGED == 'true' | |
| env: | |
| # This sed script replaces ansi escape chars with unicode for use in the commit msg. | |
| SED_SCRIPT: | | |
| /^\x1B\[4m\( \+\)\(\x1B\[0m\)\?$/{ # line above headings (spaces with ansi underline) | |
| s/ /_/g; # use underline char instead of space | |
| } | |
| # the next one adds a line of overline chars to replace the ansi overline | |
| /^== .* ==$/{ # heading text line (the matched line goes in pattern space) | |
| h; # save copy of heading line in "hold" space | |
| s/./‾/g; # make an line of overline chars to replace the heading's ansi underline | |
| H; # update "hold" space: append newline and line of overline chars | |
| g # replace the original line with lines from the "hold" space | |
| } | |
| /^\x1B\[0m$/d # drop blank line after heading (replaced with line of overline chars) | |
| s/\x1B\[[0-9;]\+m//g # strip out ansi escapes | |
| run: | | |
| sed -e "${SED_SCRIPT}" "${STDERR_LOG}" | tee "${STDERR_LOG}.txt" | head -n5 | |
| echo ... | |
| - name: Prepare Job Summary | |
| env: | |
| IMG_BASE_URI: 'https://${{ env.AWS_S3_BUCKET }}.s3.${{ env.AWS_REGION }}.amazonaws.com/${{ env.AWS_S3_BUCKET_ROOT }}/lockfile-${{ matrix.resolve }}' | |
| run: | | |
| ( | |
| echo '## ${{ matrix.resolve }} Lockfile Diff' | |
| echo | |
| if [ "${{ steps.lockfile.outputs.CHANGED }}" != true ]; then | |
| echo 'No changes required for ${{ env.LOCKFILE }}' | |
| else | |
| echo -n '![Terminal screenshot of lockfile diff in color. The text from the image is included below.]' | |
| echo "(${IMG_BASE_URI}/$(basename ${STDERR_LOG}.github-dark.png))" | |
| echo | |
| echo '<details>' | |
| echo ' <summary>Lockfile diff: ${{ env.LOCKFILE }} (plain text)</summary>' | |
| echo | |
| echo '```' | |
| cat "${STDERR_LOG}.txt" | |
| echo '```' | |
| fi | |
| echo | |
| ) | tee -a "${STDERR_LOG}.md" >> "${GITHUB_STEP_SUMMARY}" | |
| ( | |
| echo '> [!NOTE]' | |
| echo '> Diff base (git ref): *${{ needs.pr.outputs.PR_BASE_REF }}*' | |
| echo | |
| ) >> "${GITHUB_STEP_SUMMARY}" # only add this note to the job summary | |
| if [ "${{ steps.lockfile.outputs.CHANGED }}" == true ]; then | |
| ( | |
| echo '</details>' | |
| echo | |
| ) | tee -a "${STDERR_LOG}.md" >> "${GITHUB_STEP_SUMMARY}" | |
| fi | |
| - name: Upload lockfile and lockfile diff files | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lockfile-${{ matrix.resolve }} | |
| path: ${{ env.OUTPUT_DIR }} | |
| - name: Upload pants log | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: pants-log-${{ matrix.resolve }} | |
| path: .pants.d/pants.log | |
| if: always() # We want the log even on failures. | |
| commit: | |
| name: Commit regenerated ${{ matrix.resolve }} lockfile(s) | |
| needs: [resolves, pr, regenerate] | |
| runs-on: ubuntu-22.04 | |
| env: | |
| # preserve the order of resolves from input (eg pants.toml has st2 first, before tools) | |
| RESOLVES: "'${{ join(fromJSON(needs.resolves.outputs.JSON), ''' ''') }}'" | |
| RESOLVES_CSV: ${{ join(fromJSON(needs.resolves.outputs.JSON), ', ') }} | |
| LOCKFILES: ${{ needs.resolves.outputs.LOCKFILES }} | |
| # see also the 'Setup env' step | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # a test uses a submodule, and pants needs access to it to calculate deps. | |
| submodules: 'true' | |
| ref: ${{ needs.pr.outputs.CHECKOUT_REF }} | |
| - name: Create branch for new PR | |
| if: inputs.pr == 'new' | |
| run: | | |
| git config --local user.name "github-actions[bot]" | |
| git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git checkout -b "${{ needs.pr.outputs.PR_REF }}" FETCH_HEAD | |
| - name: Download lockfiles and lockfile diff files | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: lockfile-* # lockfile-{resolve} | |
| path: ${{ env.OUTPUT_BASE_DIR }} | |
| merge-multiple: false # unpack in {path}/{artifact_name}/ | |
| # This step exists because we cannot use the 'env' context in 'jobs.<job>.env.*', | |
| # and because we cannot rely on 'jobs.<job>.outputs.*' for matrix jobs. | |
| - name: Setup env | |
| run: | | |
| echo "COMMIT_MSG=${{ env.OUTPUT_BASE_DIR }}/commit_msg.txt" >> "${GITHUB_ENV}" | |
| echo "PR_COMMENT=${{ env.OUTPUT_BASE_DIR }}/pr_comment.md" >> "${GITHUB_ENV}" | |
| for resolve in ${{ env.RESOLVES }}; do | |
| LOCKFILE=$(jq -r '.["'"${resolve}"'"]' <<< "${LOCKFILES}") | |
| ARTIFACT_DIR="${{ env.OUTPUT_BASE_DIR }}/lockfile-${resolve}" | |
| # Add a symlink when actions/aritifact-download skips making subdir for only one artifact | |
| [ "'${resolve}'" == "${RESOLVES}" ] && ln -s "." "${ARTIFACT_DIR}" | |
| CHANGED_FILE="${ARTIFACT_DIR}/$(basename "${LOCKFILE}").CHANGED" | |
| if [ -e "${CHANGED_FILE}" ] && [ "$(cat "${CHANGED_FILE}" | tr -d '[:space:]')" == true ]; then | |
| CHANGED="true" | |
| echo "${LOCKFILE} was modified" | |
| else | |
| echo "${LOCKFILE} was NOT modified" | |
| fi | |
| done | |
| echo "CHANGED=${CHANGED:-false}" | tee -a "${GITHUB_ENV}" | |
| - name: Prepare commit | |
| if: env.CHANGED == 'true' | |
| run: | | |
| echo "pants generate-lockfiles: ${RESOLVES_CSV}" > "${COMMIT_MSG}" | |
| echo >> "${COMMIT_MSG}" | |
| for resolve in ${{ env.RESOLVES }}; do | |
| LOCKFILE=$(jq -r '.["'"${resolve}"'"]' <<< "${LOCKFILES}") | |
| cp "${{ env.OUTPUT_BASE_DIR }}/lockfile-${resolve}/$(basename ${LOCKFILE})" "${LOCKFILE}" | |
| git add "${LOCKFILE}" | |
| STDERR_LOG="${{ env.OUTPUT_BASE_DIR }}/lockfile-${resolve}/stderr.log" | |
| if [ -e "${STDERR_LOG}.txt" ]; then | |
| cat "${STDERR_LOG}.txt" >> "${COMMIT_MSG}" | |
| else | |
| echo "${STDERR_LOG}.txt is missing" | |
| echo "No changes to: ${LOCKFILE}" >> "${COMMIT_MSG}" | |
| echo >> "${COMMIT_MSG}" | |
| fi | |
| done | |
| - name: Prepare PR comment | |
| env: | |
| RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| run: | | |
| echo "# Lockfile Diffs" > "${PR_COMMENT}" | |
| echo >> "${PR_COMMENT}" | |
| for resolve in ${{ env.RESOLVES }}; do | |
| LOCKFILE=$(jq -r '.["'"${resolve}"'"]' <<< "${LOCKFILES}") | |
| STDERR_LOG="${{ env.OUTPUT_BASE_DIR }}/lockfile-${resolve}/stderr.log" | |
| if [ -e "${STDERR_LOG}.md" ]; then | |
| cat "${STDERR_LOG}.md" >> "${PR_COMMENT}" | |
| else | |
| echo "${STDERR_LOG}.md is missing" | |
| echo 'No changes to: `'"${LOCKFILE}"'`' >> "${PR_COMMENT}" | |
| echo >> "${PR_COMMENT}" | |
| fi | |
| done | |
| echo ":robot: [GitHub Actions Workflow Run](${RUN_LINK})" >> "${PR_COMMENT}" | |
| - name: Commit and push | |
| if: env.CHANGED == 'true' | |
| # git push --force is for workflow re-runs, but only for new PRs. | |
| run: | | |
| git commit -F "${COMMIT_MSG}" | |
| git push${{ inputs.pr == 'new' && ' --force' || '' }} \ | |
| -u origin "${{ needs.pr.outputs.PR_REF }}" | |
| - name: Create new PR | |
| if: inputs.pr == 'new' && env.CHANGED == 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: > | |
| ( | |
| echo '## New PR'; echo; | |
| gh pr create | |
| --base "${{ needs.pr.outputs.PR_BASE_REF }}" | |
| --title "pants generate-lockfiles: ${RESOLVES_CSV}" | |
| --body-file "${PR_COMMENT}" | |
| --assignee "${{ github.event.sender.login }}" | |
| --label "external dependency" | |
| --label "python3" | |
| ) | tee -a "${GITHUB_STEP_SUMMARY}" | |
| # github.token cannot be given read access to organizations.teams, | |
| # so, setting reviewer to a team would mean managing a PAT or similar. | |
| # --reviewer "${{ github.repository_owner }}/Maintainers" | |
| - name: Update or Add Comment on existing PR | |
| if: inputs.pr != 'new' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: > | |
| ( | |
| echo '## Add/Update PR Comment'; echo; | |
| gh pr comment "${{ inputs.pr }}" | |
| --body-file "${PR_COMMENT}" | |
| --edit-last | |
| --create-if-none | |
| ) | tee -a "${GITHUB_STEP_SUMMARY}" |