From 6588a47cfa3a49b24fd258d391c15ec3b6c71fbe Mon Sep 17 00:00:00 2001 From: rcskosir Date: Tue, 11 Feb 2025 11:28:59 -0500 Subject: [PATCH] adding the yml and go files for update changelog --- .github/workflows/update_changelog.yml | 136 +++++++++++++++++++++++++ scripts/update_changelog.go | 128 +++++++++++++++++++++++ 2 files changed, 264 insertions(+) create mode 100644 .github/workflows/update_changelog.yml create mode 100644 scripts/update_changelog.go diff --git a/.github/workflows/update_changelog.yml b/.github/workflows/update_changelog.yml new file mode 100644 index 000000000000..7ffa8e8ae793 --- /dev/null +++ b/.github/workflows/update_changelog.yml @@ -0,0 +1,136 @@ +name: Update Changelog with new commit + +permissions: + pull-requests: write + contents: write + +on: + pull_request: + # Inputs the workflow accepts. + types: [closed] + +jobs: + pull-commit-message: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + outputs: + message: ${{ steps.pull.outputs.message }} + steps: + - uses: actions/checkout@v4 + continue-on-error: true + - name: get merge commit message + id: pull + run: | + pull_number="$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")" + commit_message="$(git log --pretty="format:%b")" + echo message="$commit_message [GH-$pull_number]" >> $GITHUB_OUTPUT + # check-for-changelog-entry + changelog-entry: + # if contains to check for bug, enhancement, feature + if: ${{ contains(needs.pull-commit-message.outputs.message, '[BUG]') || contains(needs.pull-commit-message.outputs.message, '[ENHANCEMENT]') || contains(needs.pull-commit-message.outputs.message, '[FEATURE]') }} + runs-on: ubuntu-latest + needs: pull-commit-message + outputs: + optIn: ${{ steps.in.outputs.bool }} + entry: ${{ needs.pull-commit-message.outputs.message }} + steps: + - name: changelog entry opt in + id: in + continue-on-error: true + run: echo "opted in to changelog entry" | echo bool="true" >> $GITHUB_OUTPUT + # if there is a changelog entry, check for PR Open + update-changelog: + if: needs.changelog-entry.outputs.optIn + runs-on: ubuntu-latest + needs: changelog-entry + steps: + - name: Check if PR exists + id: check + continue-on-error: true + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + prs=$(gh pr list \ + --repo "$GITHUB_REPOSITORY" \ + --json title \ + --label "changelog" \ + --jq 'length') + if [[ $prs -gt 0 ]]; then + echo "existing=true" >> "$GITHUB_OUTPUT" + fi + - uses: actions/checkout@v4 + - name: check for branch + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + run: | + BRANCH=automated-changelog + if gh api repos/hashicorp/terraform-provider-azurerm/branches/$BRANCH > /dev/null 2>&1; then + echo "Branch exists on remote..." + git fetch origin $BRANCH + git checkout $BRANCH + else + echo "Branch does not exist on remote, creating locally..." + git checkout -b $BRANCH + fi + + - name: Create pull request + #if changelog PR isn't already open, open one + #create a new PR, start with appending the release number and (unreleased) + if: '!steps.check.outputs.existing' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + run: | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + + #new pull request for new release needs the headers all added to the top + FILE="CHANGELOG.md" + version=$(head -n 1 "$FILE") + IFS='.' read major minor patch <<< "$version" + ((minor++)) + patch=$(echo $patch | sed 's/ (.*)//') + new_version="${major}.$minor.${patch} (Unreleased)" + headers="${new_version}\n\nENHANCEMENTS:\n\nFEATURES:\n\nBUG FIXES:\n" + temp_file=$(mktemp) + echo -e "$headers" > "$temp_file" + cat "$FILE" >> "$temp_file" + mv "$temp_file" "$FILE" + echo "File has been updated." + + major=$(echo $major | sed 's/## //') + RELEASENUM="${major}.$minor.${patch}" + + git add CHANGELOG.md + git commit -m "staring new changelog PR" + git push --set-upstream origin automated-changelog + echo "Creating a new pull request" + gh pr create \ + --repo "$GITHUB_REPOSITORY" \ + --base main \ + --head automated-changelog \ + -l "changelog" \ + -t "CHANGELOG.md for $RELEASENUM" \ + -b "Automated changelog for next release, $RELEASENUM" + + - name: Set up Go + uses: actions/setup-go@v3 # Set up go + with: + go-version: '1.20' + + - name: Add commit message to changelog pull request + # at this point a PR is opened for sure, now add entry + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + run: | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + + go run scripts/update_changelog.go CHANGELOG.md '${{ needs.changelog-entry.outputs.entry }}' + + git add CHANGELOG.md + git commit -m "Update changelog" + git push --set-upstream origin automated-changelog + diff --git a/scripts/update_changelog.go b/scripts/update_changelog.go new file mode 100644 index 000000000000..a7adfc0a693c --- /dev/null +++ b/scripts/update_changelog.go @@ -0,0 +1,128 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +// Function to find the header and return its index +func findHeaderIndex(lines []string, header string) int { + for i, line := range lines { + if strings.HasPrefix(line, header) { + return i + } + } + return -1 +} + +// Function to append the new entry under the appropriate header in alphabetical order +func appendUnderHeader(filePath string, newEntry, header string) error { + // Open the file for reading and appending + file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return err + } + defer file.Close() + + // Read the file content + var lines []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + return err + } + + // Find the correct header section + headerIndex := findHeaderIndex(lines, header) + + // Now append the new entry under the correct header + // Check if the next line is empty or not for proper formatting + insertIndex := headerIndex + 1 + for i := headerIndex + 1; i < len(lines); i++ { + // Look for the next header to break the section + if strings.HasPrefix(lines[i], "[") { + insertIndex = i + break + } + } + + // Remove the header prefix from the new entry + // Trim the header prefix based on which one it matches + var trimmedEntry string + if strings.HasPrefix(newEntry, "[BUG]") { + trimmedEntry = strings.TrimPrefix(newEntry, "[BUG] ") + } else if strings.HasPrefix(newEntry, "[ENHANCEMENT]") { + trimmedEntry = strings.TrimPrefix(newEntry, "[ENHANCEMENT] ") + } else if strings.HasPrefix(newEntry, "[FEATURE]") { + trimmedEntry = strings.TrimPrefix(newEntry, "[FEATURE] ") + } else { + // If the entry doesn't match one of the expected headers, print an error + fmt.Println("Error: New entry must start with one of the headers [BUG], [ENHANCEMENT], or [FEATURE].") + return nil + } + + // Insert the new entry under the header + var section []string + for i := headerIndex + 1; i < insertIndex; i++ { + section = append(section, lines[i]) + } + section = append(section, trimmedEntry) + + // Rebuild the file content + lines = append(lines[:headerIndex+1], append(section, lines[insertIndex:]...)...) + + // Open the file for writing and overwrite the content + file, err = os.OpenFile(filePath, os.O_RDWR|os.O_TRUNC, 0644) + if err != nil { + return err + } + defer file.Close() + + // Write the updated content back to the file + writer := bufio.NewWriter(file) + for _, line := range lines { + _, err := writer.WriteString(line + "\n") + if err != nil { + return err + } + } + return writer.Flush() +} + +func main() { + if len(os.Args) != 3 { + fmt.Println("Usage: go run update_changelog.go CHANGELOG.md ") + return + } + + filePath := os.Args[1] + newEntry := os.Args[2] + + // Validate and determine the correct header for the new entry + var selectedHeader string + if strings.HasPrefix(newEntry, "[BUG]") { + selectedHeader = "BUG FIXES:" + } else if strings.HasPrefix(newEntry, "[ENHANCEMENT]") { + selectedHeader = "ENHANCEMENTS:" + } else if strings.HasPrefix(newEntry, "[FEATURE]") { + selectedHeader = "FEATURES:" + } else { + // If the entry doesn't match one of the expected headers, print an error + fmt.Println("Error: New entry must start with one of the headers [BUG], [ENHANCEMENT], or [FEATURE].") + return + } + + // Call the function to append under the appropriate header + err := appendUnderHeader(filePath, newEntry, selectedHeader) + if err != nil { + fmt.Println("Error appending to file:", err) + return + } + + fmt.Println("Successfully appended the new entry under the", selectedHeader, "header.") +}