diff --git a/.github/actions/update-vscode-extensions/action.yml b/.github/actions/update-vscode-extensions/action.yml index 6104154e..4fad07ad 100644 --- a/.github/actions/update-vscode-extensions/action.yml +++ b/.github/actions/update-vscode-extensions/action.yml @@ -11,9 +11,9 @@ outputs: updated-dependencies: description: JSON array with the names of the updated dependencies value: ${{ steps.update-extensions.outputs.updated-dependencies }} - markdown-summary: - description: Markdown summary of update result - value: ${{ steps.update-extensions.outputs.markdown-summary }} + markdown-summary-file: + description: Path to a file containing the markdown summary of update result + value: ${{ steps.update-extensions.outputs.markdown-summary-file }} runs: using: composite @@ -24,13 +24,7 @@ runs: sudo npm install -g @vscode/vsce shell: bash - run: | - EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) - echo "markdown-summary<<${EOF}" >> "${GITHUB_OUTPUT}" - echo "$(${GITHUB_ACTION_PATH}/update-vscode-extensions.sh ${INPUT_FILE})" >> "${GITHUB_OUTPUT}" - echo "${EOF}" >> "${GITHUB_OUTPUT}" - - echo "updated-dependencies=$(cat updated-extensions.json)" >> "${GITHUB_OUTPUT}" - rm updated-extensions.json + "${GITHUB_ACTION_PATH}/update-vscode-extensions.sh" "${INPUT_FILE}" id: update-extensions shell: bash env: diff --git a/.github/actions/update-vscode-extensions/update-vscode-extensions.sh b/.github/actions/update-vscode-extensions/update-vscode-extensions.sh index f8d08e50..0df817d6 100755 --- a/.github/actions/update-vscode-extensions/update-vscode-extensions.sh +++ b/.github/actions/update-vscode-extensions/update-vscode-extensions.sh @@ -2,8 +2,8 @@ set -Eeuo pipefail -FILE=${1:?} -JSON=$(cat $FILE) +FILE=${1:?"Usage: $0 "} +JSON=$(cat "$FILE") EXTENSIONS= UPDATE_DETAILS_MARKDOWN= UPDATED_EXTENSIONS_JSON="[]" @@ -20,48 +20,74 @@ prevent_github_at_mentions() { get_github_releasenotes() { local GITHUB_URL=${1:?} - local CURRENT_RELEASE=${2:?} - - gh release list --exclude-drafts --exclude-pre-releases -R $GITHUB_URL --json name,tagName --jq '.[]' | while read -r RELEASE; - do - NAME=$(echo "$RELEASE" | jq -r '.name') - TAG=$(echo "$RELEASE" | jq -r '.tagName') - - if [[ $NAME == *$CURRENT_RELEASE* || $TAG == v$CURRENT_RELEASE ]]; - then - break; - fi - - printf "%s\n\n" "$(gh release view --json body --jq '.body' -R $GITHUB_URL $TAG)" + local CURRENT_VERSION_DATE=${2:?} + + # Fetch all releases newer than the current version's publish date + # This approach works regardless of versioning scheme (semver, date-based, etc.) + gh release list --exclude-drafts --exclude-pre-releases -R "$GITHUB_URL" \ + --json tagName,publishedAt \ + --jq ".[] | select(.publishedAt > \"$CURRENT_VERSION_DATE\") | .tagName" | \ + while read -r TAG; do + printf "%s\n\n" "$(gh release view --json body --jq '.body' -R "$GITHUB_URL" "$TAG")" done } -for EXTENSION in $(echo $JSON | jq -r '.customizations.vscode.extensions | flatten[]'); do +while IFS= read -r EXTENSION; do + [[ -z "$EXTENSION" ]] && continue + NAME="${EXTENSION%%@*}" CURRENT_VERSION="${EXTENSION#*@}" - LATEST_NON_PRERELEASE_VERSION_JSON=$(vsce show --json $NAME | jq '[ .versions[] | select(.properties) | select(any(.properties[].key; contains("Microsoft.VisualStudio.Code.PreRelease")) | not) ][0]') - LATEST_NON_PRERELEASE_VERSION=$(echo $LATEST_NON_PRERELEASE_VERSION_JSON | jq -r '.version') + # Fetch all non-prerelease versions with their dates + ALL_VERSIONS_JSON=$(vsce show --json "$NAME" | jq '[ .versions[] | select(.properties) | select(any(.properties[].key; contains("Microsoft.VisualStudio.Code.PreRelease")) | not) ]') + LATEST_NON_PRERELEASE_VERSION_JSON=$(echo "$ALL_VERSIONS_JSON" | jq '.[0]') + LATEST_NON_PRERELEASE_VERSION=$(echo "$LATEST_NON_PRERELEASE_VERSION_JSON" | jq -r '.version') - if [[ $CURRENT_VERSION != $LATEST_NON_PRERELEASE_VERSION ]]; + if [[ $CURRENT_VERSION != "$LATEST_NON_PRERELEASE_VERSION" ]]; then - GITHUB_URL=$(echo $LATEST_NON_PRERELEASE_VERSION_JSON | jq -r '.properties | map(select(.key == "Microsoft.VisualStudio.Services.Links.GitHub"))[] | .value') + GITHUB_URL=$(echo "$LATEST_NON_PRERELEASE_VERSION_JSON" | jq -r '.properties | map(select(.key == "Microsoft.VisualStudio.Services.Links.GitHub"))[] | .value') if [[ -n "$GITHUB_URL" && "$GITHUB_URL" != "null" ]]; then - RELEASE_DETAILS=$(get_github_releasenotes $GITHUB_URL $CURRENT_VERSION | prevent_github_backlinks | prevent_github_at_mentions) - UPDATE_DETAILS_MARKDOWN=$(printf "Updates \`%s\` from %s to %s\n
\nRelease notes\n
\n\n%s\n
\n
\n\n%s" $NAME $CURRENT_VERSION $LATEST_NON_PRERELEASE_VERSION "$RELEASE_DETAILS" "$UPDATE_DETAILS_MARKDOWN") + # Get the publish date of the current version for date-based release matching + CURRENT_VERSION_DATE=$(echo "$ALL_VERSIONS_JSON" | jq -r --arg version "$CURRENT_VERSION" 'map(select(.version == $version))[0].lastUpdated // empty') + + if [[ -n "$CURRENT_VERSION_DATE" ]]; then + RELEASE_DETAILS=$(get_github_releasenotes "$GITHUB_URL" "$CURRENT_VERSION_DATE" | prevent_github_backlinks | prevent_github_at_mentions) + else + echo "::warning::Could not find publish date for $NAME@$CURRENT_VERSION, skipping release notes" + RELEASE_DETAILS="" + fi + UPDATE_DETAILS_MARKDOWN=$(printf "Updates \`%s\` from %s to %s\n
\nRelease notes\n
\n\n%s\n
\n
\n\n%s" "$NAME" "$CURRENT_VERSION" "$LATEST_NON_PRERELEASE_VERSION" "$RELEASE_DETAILS" "$UPDATE_DETAILS_MARKDOWN") else - UPDATE_DETAILS_MARKDOWN=$(printf "Updates \`%s\` from %s to %s\n\n%s" $NAME $CURRENT_VERSION $LATEST_NON_PRERELEASE_VERSION "$UPDATE_DETAILS_MARKDOWN") + UPDATE_DETAILS_MARKDOWN=$(printf "Updates \`%s\` from %s to %s\n\n%s" "$NAME" "$CURRENT_VERSION" "$LATEST_NON_PRERELEASE_VERSION" "$UPDATE_DETAILS_MARKDOWN") fi - UPDATED_EXTENSIONS_JSON=$(echo $UPDATED_EXTENSIONS_JSON | jq -c '. += ["'$NAME'"]') + UPDATED_EXTENSIONS_JSON=$(echo "$UPDATED_EXTENSIONS_JSON" | jq -c --arg name "$NAME" '. += [$name]') fi EXTENSIONS="\"$NAME@$LATEST_NON_PRERELEASE_VERSION\",$EXTENSIONS" -done +done < <(echo "$JSON" | jq -r '.customizations.vscode.extensions | flatten[]') -EXTENSIONS=$(echo "[${EXTENSIONS::-1}]" | jq 'sort_by(. | ascii_downcase)') -echo $JSON | jq '.customizations.vscode.extensions = $extensions' --argjson extensions "$EXTENSIONS" > $FILE +if [[ -n "$EXTENSIONS" ]]; then + EXTENSIONS=$(echo "[${EXTENSIONS::-1}]" | jq 'sort_by(. | ascii_downcase)') +else + EXTENSIONS="[]" +fi +echo "$JSON" | jq '.customizations.vscode.extensions = $extensions' --argjson extensions "$EXTENSIONS" > "$FILE" + +echo "::group::๐Ÿ“„ Changes to $FILE" +git diff --color=always -- "$FILE" || true +echo "::endgroup::" + +echo "::group::VS Code Extensions Update Details" echo "$UPDATE_DETAILS_MARKDOWN" -echo "$UPDATED_EXTENSIONS_JSON" > updated-extensions.json +echo "::endgroup::" + +MARKDOWN_SUMMARY_FILE=$(mktemp "${RUNNER_TEMP:-/tmp}/markdown-summary.XXXXXX.md") +echo "$UPDATE_DETAILS_MARKDOWN" > "${MARKDOWN_SUMMARY_FILE}" + +if [[ -n "${GITHUB_OUTPUT:-}" ]]; then + echo "markdown-summary-file=${MARKDOWN_SUMMARY_FILE}" >> "${GITHUB_OUTPUT}" + echo "updated-dependencies=${UPDATED_EXTENSIONS_JSON}" >> "${GITHUB_OUTPUT}" +fi diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index e9470914..bebb2257 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -1,7 +1,8 @@ --- -name: Update Dependencies +name: ๐Ÿ“ฆ Update on: + pull_request: schedule: - cron: "30 2 * * 0" workflow_dispatch: @@ -10,9 +11,10 @@ permissions: {} jobs: update-apt-dependencies: - name: Update APT Dependencies (๐Ÿจ ${{ matrix.flavor }}) + name: ${{ github.event_name == 'pull_request' && '๐Ÿงช' || '' }} OS (๐Ÿจ ${{ matrix.flavor }}) runs-on: ubuntu-latest strategy: + fail-fast: false matrix: flavor: ["base", "cpp", "rust"] # Using our own container is required since we need all package sources @@ -31,13 +33,15 @@ jobs: - uses: ./.github/actions/update-apt-packages id: update-packages with: - input-file: .devcontainer/${{ matrix.flavor }}/apt-requirements-*.json + input-file: .devcontainer/${{ matrix.flavor }}/apt-requirements*.json - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 id: token + if: github.event_name != 'pull_request' with: app-id: ${{ vars.FOREST_RELEASER_APP_ID }} private-key: ${{ secrets.FOREST_RELEASER_APP_PRIVATE_KEY }} - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + if: github.event_name != 'pull_request' with: commit-message: "Update ${{ join(fromJson(steps.update-packages.outputs.updated-dependencies), ', ') }}" branch: feature/amp-devcontainer-${{ matrix.flavor }}/update-apt-packages @@ -47,9 +51,10 @@ jobs: sign-commits: true update-vscode-extensions: - name: Update VS Code Extensions (๐Ÿจ ${{ matrix.flavor }}, ${{ matrix.file }}) + name: ${{ github.event_name == 'pull_request' && '๐Ÿงช' || '' }} Extensions (๐Ÿจ ${{ matrix.flavor }}, ${{ matrix.file }}) runs-on: ubuntu-latest strategy: + fail-fast: false matrix: flavor: ["cpp", "rust"] file: ["devcontainer-metadata.json", "devcontainer.json"] @@ -67,20 +72,28 @@ jobs: id: update-extensions with: input-file: .devcontainer/${{ matrix.flavor }}/${{ matrix.file }} + - name: Generate PR body + run: | + { + echo "> [!NOTE]" + echo "> Before merging this PR, please conduct a manual test checking basic functionality of the updated plug-ins. There are limited automated tests for the VS Code Extension updates." + echo "" + cat "$MARKDOWN_SUMMARY_FILE" + } >> "${RUNNER_TEMP}/pull-request-body.md" + env: + MARKDOWN_SUMMARY_FILE: ${{ steps.update-extensions.outputs.markdown-summary-file }} - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 id: token + if: github.event_name != 'pull_request' with: app-id: ${{ vars.FOREST_RELEASER_APP_ID }} private-key: ${{ secrets.FOREST_RELEASER_APP_PRIVATE_KEY }} - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + if: github.event_name != 'pull_request' with: commit-message: "Update ${{ join(fromJson(steps.update-extensions.outputs.updated-dependencies), ', ') }} in ${{ matrix.file }}" branch: feature/amp-devcontainer-${{ matrix.flavor }}/update-vscode-extensions-${{ matrix.file }} - body: | - > [!NOTE] - > Before merging this PR, please conduct a manual test checking basic functionality of the updated plug-ins. There are limited automated tests for the VS Code Extension updates. - - ${{ steps.update-extensions.outputs.markdown-summary }} + body-path: ${{ runner.temp }}/pull-request-body.md title: "chore(deps, ${{ matrix.flavor }}): update ${{ join(fromJson(steps.update-extensions.outputs.updated-dependencies), ', ') }} in ${{ matrix.file }}" labels: dependencies,vscode-extensions token: ${{ steps.token.outputs.token }}