Release Workflow #126
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: Release Workflow | |
on: | |
workflow_dispatch: | |
permissions: | |
contents: write | |
jobs: | |
release: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v3 | |
- name: Install Dependencies | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y jq | |
- name: Setup Node.js and pnpm | |
uses: pnpm/action-setup@v4 | |
- name: Setup Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: '20' | |
cache: 'pnpm' | |
- name: Authenticate GitHub CLI | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
gh auth status | |
- name: Get the latest tag or set initial version | |
id: get_latest_tag | |
run: | | |
# Clean any local tags | |
git tag -l | xargs git tag -d | |
# Fetch all tags from remote | |
git fetch --prune --tags origin | |
LATEST_TAG=$(git tag -l "v*" --sort=-v:refname | head -n 1 || echo "v0.0.0") | |
echo "latest_tag=$LATEST_TAG" >> $GITHUB_ENV | |
echo "Found latest tag: $LATEST_TAG" | |
# Debug output | |
echo "All available tags:" | |
git tag -l | |
- name: Calculate new version | |
run: | | |
echo "latest_tag=${{ env.latest_tag }}" | |
# Split version into components and increment patch | |
LATEST_TAG_NO_V="${{ env.latest_tag }}" | |
LATEST_TAG_NO_V=${LATEST_TAG_NO_V#v} # Remove 'v' prefix | |
IFS='.' read -r MAJOR MINOR PATCH <<< "$LATEST_TAG_NO_V" | |
PATCH=$((PATCH + 1)) | |
NEW_VERSION="v$MAJOR.$MINOR.$PATCH" | |
# Output the new version | |
echo "Final new version: $NEW_VERSION" | |
echo "new_version=$NEW_VERSION" >> $GITHUB_ENV | |
- name: Generate changelog | |
id: changelog | |
run: | | |
CHANGES=$(git log "${{ env.latest_tag }}"..HEAD --pretty=format:"- %s (%h) by %an") | |
echo "$CHANGES" > changes.txt | |
echo "Changes written to changes.txt" | |
- name: Fetch PR data as JSON | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
# Get the timestamp of the last tag | |
LAST_TAG_DATE=$(git log -1 --format=%ct ${{ env.latest_tag }}) | |
LAST_TAG_ISO=$(date -u --date="@$LAST_TAG_DATE" +"%Y-%m-%dT%H:%M:%SZ") | |
# Get PRs merged after the last tag | |
gh pr list --state merged --base main --search "merged:>$LAST_TAG_ISO" \ | |
--json number,title,body,author,mergedAt,labels > prs.json | |
echo "PR data saved to prs.json" | |
- name: Format PR data | |
run: | | |
jq -r '.[] | "- PR #\(.number): \(.title) by \(.author.login)\n> [!IMPORTANT]\n> \(.body // "No description provided.")\n"' prs.json > formatted_prs.txt | |
echo "Formatted PR data saved to formatted_prs.txt" | |
- name: Combine changelog and PR data | |
run: | | |
echo "Changes from git log:\n" > changelog.txt | |
cat changes.txt >> changelog.txt | |
echo "\nChanges from PRs:\n" >> changelog.txt | |
cat formatted_prs.txt >> changelog.txt | |
echo "Combined changelog written to changelog.txt" | |
- name: Extract PR titles and important lines | |
id: parse_changelog | |
run: | | |
awk -v repo_url="https://github.com/openintegrations/openint" ' | |
BEGIN { | |
last_pr_number = ""; | |
} | |
/^- PR #[0-9]+:/ { | |
match($0, /^- PR #([0-9]+):/, pr); | |
pr_title = $0; | |
pr_number = pr[1]; | |
} | |
/> \[!IMPORTANT\]/ { | |
getline; | |
important_line = $0; | |
if (pr_number != last_pr_number) { | |
last_pr_number = pr_number; | |
print pr_title " (" repo_url "/pull/" pr_number ") -- " important_line; | |
} | |
}' changelog.txt > formatted_release_notes.txt | |
echo "Formatted Release Notes:" | |
cat formatted_release_notes.txt | |
- name: Summarize PR changes with OpenAI | |
id: summarize | |
env: | |
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
run: | | |
FORMATTED_OUTPUT=$(cat formatted_release_notes.txt | jq -Rsa .) | |
RESPONSE=$(curl -s -X POST https://api.openai.com/v1/chat/completions \ | |
-H "Content-Type: application/json" \ | |
-H "Authorization: Bearer $OPENAI_API_KEY" \ | |
-d "$(jq -n --arg changelog "$FORMATTED_OUTPUT" '{ | |
model: "gpt-4", | |
messages: [ | |
{role: "system", content: "You are an assistant that generates concise and clear release summaries for software projects."}, | |
{role: "user", content: ("Summarize the following PR changes into a single two-liner summary highlighting important changes in casual tone of voice:\n\n" + $changelog)} | |
], | |
temperature: 0.7 | |
}')") | |
echo "OpenAI API Response:" | |
echo "$RESPONSE" | |
SUMMARY=$(echo "$RESPONSE" | jq -r '.choices[0].message.content // "No summary generated"') | |
echo "summary=$SUMMARY" >> $GITHUB_ENV | |
echo "$SUMMARY" > summary_output.txt | |
- name: Create Release Notes | |
run: | | |
SUMMARY=$(cat summary_output.txt) | |
echo -e "### Summary\n\n$SUMMARY\n\n### PR Breakdown:\n" > release_notes.txt | |
cat formatted_release_notes.txt >> release_notes.txt | |
echo "Release notes written to release_notes.txt" | |
- name: Push spec and config to Stainless and output documented spec | |
uses: stainless-api/upload-openapi-spec-action@main | |
with: | |
stainless_api_key: ${{ secrets.STAINLESS_API_KEY }} | |
input_path: 'packages/api-v1/__generated__/openapi.json' | |
output_path: 'packages/api-v1/__generated__/openapi.documented.json' | |
project_name: 'openint' | |
commit_message: 'feat(docs): updating documented docs for stainless' | |
- name: Update main & production branches | |
env: | |
GH_TOKEN: ${{ secrets.AP_GH_PAT }} | |
run: | | |
git config user.name "Amadeo Pellicce (Automated PR)" | |
git config user.email "[email protected]" | |
git fetch | |
# Add all generated files using pattern matching | |
git add -f "packages/api-v1/__generated__/*" "docs/mintlify.oas.yml" 2>/dev/null || true | |
# Check if there are changes to commit | |
if git diff --staged --quiet; then | |
echo "No changes to commit, skipping commit step" | |
else | |
git commit -m "feat(docs): updating documented docs for stainless" | |
git push origin main --force | |
fi | |
# Always update production branch regardless of whether there were changes | |
git checkout production | |
git reset --hard origin/main | |
git push origin production --force | |
- uses: UnlyEd/github-action-await-vercel@v1 | |
id: await-vercel | |
env: | |
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} | |
with: | |
deployment-url: v1-git-main-openint-dev.vercel.app # TODO Replace by the domain you want to test | |
timeout: 10 # Wait for 10 seconds before failing | |
poll-interval: 1 # Wait for 1 second before each retry | |
# - name: Stably Runner Action | |
# id: stably-runner | |
# uses: stablyhq/stably-runner-action@v3 | |
# with: | |
# api-key: ${{ secrets.STABLY_API_KEY }} | |
# test-group-id: cm5g8i6nc0005l103urkixuxz |