Product Release #33
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: Product Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| product: | |
| description: "Product name" | |
| required: true | |
| type: choice | |
| options: | |
| - connect | |
| - workbench | |
| - package-manager | |
| version: | |
| description: "Product version to set as appVersion (e.g. 2026.03.0)" | |
| required: true | |
| type: string | |
| python_version: | |
| description: "Python version baked into the server image (connect only, e.g. 3.14.6)" | |
| required: false | |
| type: string | |
| default: "" | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| update: | |
| name: Update ${{ inputs.product }} to ${{ inputs.version }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Map product to chart | |
| id: chart | |
| env: | |
| PRODUCT: ${{ inputs.product }} | |
| run: | | |
| case "$PRODUCT" in | |
| connect) | |
| echo "name=rstudio-connect" >> "$GITHUB_OUTPUT" | |
| echo "image=posit/connect" >> "$GITHUB_OUTPUT" | |
| echo "init-image=posit/connect-content-init" >> "$GITHUB_OUTPUT" | |
| echo "os-tag=ubuntu-24.04" >> "$GITHUB_OUTPUT" | |
| ;; | |
| workbench) | |
| echo "name=rstudio-workbench" >> "$GITHUB_OUTPUT" | |
| echo "image=posit/workbench" >> "$GITHUB_OUTPUT" | |
| echo "session-image=posit/workbench-session-init" >> "$GITHUB_OUTPUT" | |
| echo "os-tag=ubuntu-24.04" >> "$GITHUB_OUTPUT" | |
| ;; | |
| package-manager) | |
| echo "name=rstudio-pm" >> "$GITHUB_OUTPUT" | |
| echo "image=posit/package-manager" >> "$GITHUB_OUTPUT" | |
| echo "os-tag=ubuntu-24.04" >> "$GITHUB_OUTPUT" | |
| ;; | |
| *) | |
| echo "::error::Unknown product: $PRODUCT" | |
| exit 1 | |
| ;; | |
| esac | |
| - name: Generate GitHub App Token | |
| id: app-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| client-id: ${{ secrets.POSIT_PLATFORM_CLIENT_ID }} | |
| private-key: ${{ secrets.POSIT_PLATFORM_PEM }} | |
| permission-contents: write | |
| permission-pull-requests: write | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| - name: Validate and normalize app version | |
| id: app-version | |
| env: | |
| APP_VERSION: ${{ inputs.version }} | |
| run: | | |
| # Strip pre-release/build metadata | |
| APP_VERSION="${APP_VERSION%%[+-]*}" | |
| if [[ ! "$APP_VERSION" =~ ^[0-9]{4}\.[0-9]{2}\.[0-9]+$ ]]; then | |
| echo "::error::Invalid version format: $APP_VERSION (expected YYYY.MM.PATCH)" | |
| exit 1 | |
| fi | |
| echo "value=$APP_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Check current appVersion | |
| id: current | |
| env: | |
| CHART_NAME: ${{ steps.chart.outputs.name }} | |
| run: | | |
| CURRENT=$(yq '.appVersion' "charts/${CHART_NAME}/Chart.yaml") | |
| echo "app-version=$CURRENT" >> "$GITHUB_OUTPUT" | |
| - name: Skip (already up to date) | |
| if: steps.current.outputs.app-version == steps.app-version.outputs.value | |
| env: | |
| APP_VERSION: ${{ steps.app-version.outputs.value }} | |
| run: echo "::notice::appVersion is already ${APP_VERSION}, nothing to do" | |
| - name: Update Chart.yaml | |
| if: steps.current.outputs.app-version != steps.app-version.outputs.value | |
| id: update | |
| env: | |
| APP_VERSION: ${{ steps.app-version.outputs.value }} | |
| CHART_NAME: ${{ steps.chart.outputs.name }} | |
| IMAGE: ${{ steps.chart.outputs.image }} | |
| INIT_IMAGE: ${{ steps.chart.outputs.init-image }} | |
| SESSION_IMAGE: ${{ steps.chart.outputs.session-image }} | |
| OS_TAG: ${{ steps.chart.outputs.os-tag }} | |
| run: | | |
| CHART="charts/${CHART_NAME}/Chart.yaml" | |
| # Bump appVersion | |
| yq -i ".appVersion = \"$APP_VERSION\"" "$CHART" | |
| # Bump chart patch version | |
| CURRENT_VERSION=$(yq '.version' "$CHART") | |
| MAJOR=$(echo "$CURRENT_VERSION" | cut -d. -f1) | |
| MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2) | |
| PATCH=$(echo "$CURRENT_VERSION" | cut -d. -f3) | |
| NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))" | |
| yq -i ".version = \"$NEW_VERSION\"" "$CHART" | |
| # Update main image annotation ({version}-{os-tag} format) | |
| yq -i "(.annotations.\"artifacthub.io/images\" | select(. != null)) |= sub(\"${IMAGE}:[^\n]*\", \"${IMAGE}:${APP_VERSION}-${OS_TAG}\")" "$CHART" | |
| # connect-content-init is OS-agnostic; tag is just the version | |
| if [ -n "$INIT_IMAGE" ]; then | |
| yq -i "(.annotations.\"artifacthub.io/images\" | select(. != null)) |= sub(\"${INIT_IMAGE}:[^\n]*\", \"${INIT_IMAGE}:${APP_VERSION}\")" "$CHART" | |
| fi | |
| # Workbench session-init uses the same OS-suffixed format as the main image | |
| if [ -n "$SESSION_IMAGE" ]; then | |
| yq -i "(.annotations.\"artifacthub.io/images\" | select(. != null)) |= sub(\"${SESSION_IMAGE}:[^\n]*\", \"${SESSION_IMAGE}:${APP_VERSION}-${OS_TAG}\")" "$CHART" | |
| fi | |
| echo "chart-version=$NEW_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Sync Connect interpreter paths | |
| if: >- | |
| steps.current.outputs.app-version != steps.app-version.outputs.value && | |
| inputs.product == 'connect' && | |
| inputs.python_version != '' | |
| env: | |
| CHART_NAME: ${{ steps.chart.outputs.name }} | |
| PYTHON_VERSION: ${{ inputs.python_version }} | |
| run: | | |
| yq -i \ | |
| ".config.Python.Executable = [\"/opt/python/${PYTHON_VERSION}/bin/python\"]" \ | |
| "charts/${CHART_NAME}/values.yaml" | |
| - name: Add NEWS.md entry | |
| if: steps.current.outputs.app-version != steps.app-version.outputs.value | |
| env: | |
| APP_VERSION: ${{ steps.app-version.outputs.value }} | |
| PRODUCT: ${{ inputs.product }} | |
| CHART_NAME: ${{ steps.chart.outputs.name }} | |
| CHART_VERSION: ${{ steps.update.outputs.chart-version }} | |
| run: | | |
| NEWS="charts/${CHART_NAME}/NEWS.md" | |
| # Capitalize product name for changelog | |
| DISPLAY_NAME=$(echo "$PRODUCT" | sed 's/connect/Connect/;s/workbench/Workbench/;s/package-manager/Package Manager/') | |
| # Build the new entry and prepend it after the heading line | |
| { | |
| head -1 "$NEWS" | |
| echo "" | |
| echo "## ${CHART_VERSION}" | |
| echo "" | |
| echo "- Bump ${DISPLAY_NAME} version to ${APP_VERSION}" | |
| echo "" | |
| tail -n +3 "$NEWS" | |
| } > "${NEWS}.tmp" && mv "${NEWS}.tmp" "$NEWS" | |
| - name: Install Just | |
| if: steps.current.outputs.app-version != steps.app-version.outputs.value | |
| uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 | |
| - name: Generate docs | |
| if: steps.current.outputs.app-version != steps.app-version.outputs.value | |
| run: | | |
| just setup | |
| just docs | |
| - name: Create Pull Request | |
| if: steps.current.outputs.app-version != steps.app-version.outputs.value | |
| uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| branch: update-${{ inputs.product }}-${{ steps.app-version.outputs.value }} | |
| delete-branch: true | |
| title: "Update ${{ inputs.product }} to ${{ steps.app-version.outputs.value }}" | |
| body: | | |
| Automated update from `posit-dev/images-${{ inputs.product }}` production build. | |
| - Chart: `${{ steps.chart.outputs.name }}` | |
| - appVersion: `${{ steps.current.outputs.app-version }}` → `${{ steps.app-version.outputs.value }}` | |
| ${{ inputs.python_version != '' && format('- Python: `{0}`', inputs.python_version) || '' }} | |
| commit-message: "Update ${{ inputs.product }} appVersion to ${{ steps.app-version.outputs.value }}" | |
| base: main |