-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat: add github action to cut release and preserve distribution cache #50112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 7 commits
b109982
c99fc5e
f29b6db
adce266
9c74036
d2f4cc7
af27376
c66a075
98dccea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| --- | ||
| name: Apply sync hold | ||
| # this is fine since gha runs with yaml 1.2 | ||
| on: # yamllint disable-line rule:truthy | ||
| workflow_dispatch: | ||
| inputs: | ||
| distribution: | ||
| description: 'Which distribution is in sync hold?' | ||
| required: true | ||
| type: choice | ||
| options: | ||
| - 'jazzy' | ||
| - 'kilted' | ||
| - 'lyrical' | ||
| - 'rolling' | ||
| default: 'rolling' | ||
| jobs: | ||
| apply-sync-hold: | ||
| permissions: | ||
| pull-requests: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| - name: Add a sync hold label to PRs | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| TARGET_FILE: "${{ inputs.distribution }}/distribution.yaml" | ||
| LABEL_TO_ADD: "held for ${{ inputs.distribution }} sync" | ||
| run: | | ||
| # Find all PRs that touch the target file ... | ||
| PR_NUMBERS=$(gh pr list --state open --json number,files | \ | ||
| jq -r --arg FILE "${{ env.TARGET_FILE }}" '.[] | select(.files[].path == $FILE) | .number') | ||
|
|
||
| # Special case: nothing needs to be held for sync so bail early. | ||
| if [ -z "$PR_NUMBERS" ]; then | ||
| echo "No PRs found touching ${{ env.TARGET_FILE }}" | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Loop through and remove the label | ||
| for PR in $PR_NUMBERS; do | ||
| echo "Processing PR #$PR..." | ||
| gh pr edit $PR --add-label "${{ env.LABEL_TO_ADD }}" || echo "Label not found on #$PR" | ||
| done | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| --- | ||
| name: Cut a new ROS release | ||
| # this is fine since gha runs with yaml 1.2 | ||
| on: # yamllint disable-line rule:truthy | ||
| workflow_dispatch: | ||
| inputs: | ||
| distribution: | ||
| description: 'Which distribution is the release for?' | ||
| required: true | ||
| type: choice | ||
| options: | ||
| - 'jazzy' | ||
| - 'kilted' | ||
| - 'lyrical' | ||
| - 'rolling' | ||
| default: 'rolling' | ||
| date: | ||
| description: 'Release in YYYY-MM-DD. Leave empty for new.' | ||
| required: false | ||
| type: string | ||
| remove_held_for_sync_tags: | ||
| description: 'Remove all held-for-sync labels?' | ||
| required: true | ||
| type: boolean | ||
| default: true | ||
| jobs: | ||
| cut-new-release: | ||
| permissions: | ||
| pull-requests: write | ||
| contents: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| # Add any missing inputs. | ||
| - name: Calculate final inputs | ||
| env: | ||
| OLD_CACHE_URL_BASE: "http://repo.ros2.org/rosdistro_cache" | ||
| NEW_CACHE_URL_BASE: "https://github.com/ros/rosdistro/releases/download" | ||
| run: | | ||
| USER_INPUT="${{ inputs.date }}" | ||
| if [ -z "$USER_INPUT" ]; then | ||
| FINAL_DATE=$(TZ="America/Los_Angeles" date +%Y-%m-%d) | ||
| FINAL_REF=master | ||
| echo "Date used: $FINAL_DATE (branch: $FINAL_REF, must exist)" | ||
| else | ||
| FINAL_DATE=$USER_INPUT | ||
| FINAL_REF=${{ inputs.distribution }}/$FINAL_DATE | ||
| echo "Date provided: $FINAL_DATE (tag: $FINAL_REF, must exist)" | ||
| fi | ||
| OLD_URL_SUFFIX=${{ inputs.distribution }}-cache.yaml.gz | ||
| NEW_URL_SUFFIX=${{ inputs.distribution }}/$FINAL_DATE/${{ inputs.distribution }}-cache.yaml.gz | ||
| echo "RELEASE_DISTRIBUTION=${{ inputs.distribution }}" >> $GITHUB_ENV | ||
| echo "RELEASE_DATE=$FINAL_DATE" >> $GITHUB_ENV | ||
| echo "RELEASE_REF=$FINAL_REF" >> $GITHUB_ENV | ||
| echo "RELEASE_TAG=${{ inputs.distribution }}/$FINAL_DATE" >> $GITHUB_ENV | ||
| echo "RELEASE_CACHE_OLD_URL=${{ env.OLD_CACHE_URL_BASE }}/$OLD_URL_SUFFIX" >> $GITHUB_ENV | ||
| echo "RELEASE_CACHE_NEW_URL=${{ env.NEW_CACHE_URL_BASE }}/$NEW_URL_SUFFIX" >> $GITHUB_ENV | ||
|
|
||
| # Echo the release information to console. | ||
| - name: Print release information | ||
| run: | | ||
| echo "Ref: ${{ env.RELEASE_REF }}" | ||
| echo "Distribution: ${{ env.RELEASE_DISTRIBUTION }}" | ||
| echo "Date: ${{ env.RELEASE_DATE }}" | ||
| echo "Tag: ${{ env.RELEASE_TAG }}" | ||
| echo "Old cache URL: ${{ env.RELEASE_CACHE_OLD_URL }}" | ||
| echo "New cache URL: ${{ env.RELEASE_CACHE_NEW_URL }}" | ||
|
|
||
| # Checkout the repository master branch. | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ env.RELEASE_REF }} | ||
|
|
||
| # Set up a clean Python environment (Avoids OS-level pip blocks) | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.11' | ||
| cache: 'pip' | ||
|
|
||
| # Install dependencies for the rosdistro_build_cache tool. | ||
| - name: Install extra tools via pip | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install rosdistro | ||
|
|
||
| # Rebuild the cache from scratch. | ||
| - name: Rebuild cache | ||
| run: | | ||
| cd ${{ env.RELEASE_DISTRIBUTION }} | ||
| sed -i "s|https://github.com/ros-gbp|https://github.com/ros2-gbp|g" distribution.yaml | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This workaround can't make it into production. If there's a bug in the index, it should be fixed.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great point. I forgot about this step in the workflow. It won't be needed going forward as the GBP repos are correct on master. I needed this workaround when trying to rebuild a distribution cache for an older release in 2025. Fixing the error in the way you suggest would be rewriting git history, which I assume can't happen. Is it ok if I just remove this step completely? |
||
| rosdistro_build_cache ../index-v4.yaml ${{ env.RELEASE_DISTRIBUTION }} | ||
| cd .. | ||
|
|
||
| # Commit the change to the distribution file and push the tagged orphaned commit. | ||
| - name: Tag orphaned commit for the release | ||
| run: | | ||
| git config --global user.name "github-actions[bot]" | ||
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | ||
| sed -i "s|${{ env.RELEASE_CACHE_OLD_URL }}|${{ env.RELEASE_CACHE_NEW_URL }}|g" index.yaml | ||
| sed -i "s|${{ env.RELEASE_CACHE_OLD_URL }}|${{ env.RELEASE_CACHE_NEW_URL }}|g" index-v4.yaml | ||
| git add index.yaml index-v4.yaml | ||
| git commit -m "chore: update cache entry for ${{ env.RELEASE_DISTRIBUTION }}" | ||
| git tag -f ${{ env.RELEASE_TAG }} | ||
| git push -f origin tags/${{ env.RELEASE_TAG }} | ||
|
|
||
| # Force-push the release. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we force-pushing to rosdistro?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To overwrite an existing tag from the past if we choose to update it to include the distribution cache artifacts. If we plan to use this action strictly for future releases then it should be fine to remove the force in this command. Would that work for you? |
||
| - name: Push release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| tag_name: ${{ env.RELEASE_TAG }} | ||
| files: | | ||
| ${{ env.RELEASE_DISTRIBUTION }}/${{ env.RELEASE_DISTRIBUTION }}-cache.yaml.gz | ||
|
|
||
| # Find all PRs with the sync label and remove them. | ||
| - name: Remove all held for sync labels on PRs | ||
| if: ${{ inputs.remove_held_for_sync_tags == true }} | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| LABEL_TO_REMOVE: "held for ${{ inputs.distribution }} sync" | ||
| run: | | ||
| # Get all open PRs that have a held for sync label matching the current release. | ||
| PR_NUMBERS=$(gh pr list --state open --label "${{ env.LABEL_TO_REMOVE }}" --json number --jq '.[].number') | ||
|
|
||
| # Special case: nothing was held for sync so bail early. | ||
| if [ -z "$PR_NUMBERS" ]; then | ||
| echo "No PRs found with label: ${{ env.LABEL_TO_REMOVE }}" | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Loop through PRs that match and remove the label. | ||
| for PR in $PR_NUMBERS; do | ||
| echo "Processing PR #$PR..." | ||
| gh pr edit $PR --remove-label "${{ env.LABEL_TO_REMOVE }}" || echo "Label not found on #$PR" | ||
| done | ||
Uh oh!
There was an error while loading. Please reload this page.