Skip to content

Create Package Release #7

Create Package Release

Create Package Release #7

Workflow file for this run

name: Create Package Release
on:
workflow_dispatch:
inputs:
package:
description: "Package to release"
required: true
default: changelog_cli
type: choice
options:
- changelog_cli
- slack_cli
- disk_analyzer_cli
- git_chain
dry_run:
description: "Dry run (do not create tag/release)"
required: false
default: false
type: boolean
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
package_dir: ${{ steps.package_config.outputs.package_dir }}
executable_name: ${{ steps.package_config.outputs.executable_name }}
build_mode: ${{ steps.package_config.outputs.build_mode }}
build_matrix: ${{ steps.package_config.outputs.build_matrix }}
tag_name: ${{ steps.tag_check.outputs.tag_name }}
version: ${{ steps.version_pubspec.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Dart
uses: dart-lang/setup-dart@v1
- name: Install and activate changelog_cli
run: |
cd changelog_cli
dart pub get
dart pub global activate --source=path .
- name: Resolve package configuration
id: package_config
run: |
PACKAGE="${{ inputs.package }}"
case "$PACKAGE" in
changelog_cli)
echo "package_dir=changelog_cli" >> "$GITHUB_OUTPUT"
echo "executable_name=changelog_cli" >> "$GITHUB_OUTPUT"
echo "build_mode=exe" >> "$GITHUB_OUTPUT"
echo 'build_matrix={"include":[{"os":"ubuntu-latest","artifact_name":"changelog_cli_linux","binary_name":"changelog_cli_linux"},{"os":"windows-latest","artifact_name":"changelog_cli_windows_x64","binary_name":"changelog_cli.exe"},{"os":"macos-latest","artifact_name":"changelog_cli_macos_arm64","binary_name":"changelog_cli_macos"},{"os":"macos-13","artifact_name":"changelog_cli_macos_x64","binary_name":"changelog_cli_macos_x86"}]}' >> "$GITHUB_OUTPUT"
;;
slack_cli)
echo "package_dir=slack_cli" >> "$GITHUB_OUTPUT"
echo "executable_name=slack_cli" >> "$GITHUB_OUTPUT"
echo "build_mode=exe" >> "$GITHUB_OUTPUT"
echo 'build_matrix={"include":[{"os":"ubuntu-latest","artifact_name":"slack_cli_linux","binary_name":"slack_cli_linux"},{"os":"windows-latest","artifact_name":"slack_cli_windows_x64","binary_name":"slack_cli.exe"},{"os":"macos-latest","artifact_name":"slack_cli_macos_arm64","binary_name":"slack_cli_macos"},{"os":"macos-13","artifact_name":"slack_cli_macos_x64","binary_name":"slack_cli_macos_x86"}]}' >> "$GITHUB_OUTPUT"
;;
disk_analyzer_cli)
echo "package_dir=disk_analyzer_cli" >> "$GITHUB_OUTPUT"
echo "executable_name=disk_analyzer_cli" >> "$GITHUB_OUTPUT"
echo "build_mode=bundle" >> "$GITHUB_OUTPUT"
echo 'build_matrix={"include":[{"os":"ubuntu-latest","artifact_name":"disk_analyzer_cli_linux_x64"},{"os":"windows-latest","artifact_name":"disk_analyzer_cli_windows_x64"},{"os":"macos-latest","artifact_name":"disk_analyzer_cli_macos_arm64"}]}' >> "$GITHUB_OUTPUT"
;;
git_chain)
echo "package_dir=git_chain" >> "$GITHUB_OUTPUT"
echo "executable_name=git_chain" >> "$GITHUB_OUTPUT"
echo "build_mode=bundle" >> "$GITHUB_OUTPUT"
echo 'build_matrix={"include":[{"os":"ubuntu-latest","artifact_name":"git_chain_linux_x64"},{"os":"windows-latest","artifact_name":"git_chain_windows_x64"},{"os":"macos-latest","artifact_name":"git_chain_macos_arm64"}]}' >> "$GITHUB_OUTPUT"
;;
esac
- name: Read version from pubspec.yaml
id: version_pubspec
run: |
PACKAGE_DIR="${{ steps.package_config.outputs.package_dir }}"
VERSION=$(grep '^version:' "$PACKAGE_DIR/pubspec.yaml" | sed 's/version: //')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Version from pubspec.yaml: $VERSION"
- name: Read version from version.dart if present
id: version_dart
run: |
PACKAGE_DIR="${{ steps.package_config.outputs.package_dir }}"
VERSION_FILE="$PACKAGE_DIR/lib/src/version.dart"
if [ -f "$VERSION_FILE" ]; then
VERSION=$(grep 'const packageVersion' "$VERSION_FILE" | sed "s/const packageVersion = '\(.*\)';/\1/")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Version from version.dart: $VERSION"
else
echo 'version=' >> "$GITHUB_OUTPUT"
echo "No version.dart for $PACKAGE_DIR, using pubspec.yaml only"
fi
- name: Verify versions match
run: |
if [ -n "${{ steps.version_dart.outputs.version }}" ] && [ "${{ steps.version_dart.outputs.version }}" != "${{ steps.version_pubspec.outputs.version }}" ]; then
echo "ERROR: Version mismatch!"
echo "version.dart: ${{ steps.version_dart.outputs.version }}"
echo "pubspec.yaml: ${{ steps.version_pubspec.outputs.version }}"
exit 1
fi
echo "✅ Release version: ${{ steps.version_pubspec.outputs.version }}"
- name: Get latest tag
id: latest_tag
run: |
PACKAGE="${{ inputs.package }}"
LATEST_TAG=$(git tag -l "$PACKAGE-v*" | sort -V | tail -n 1)
if [ -z "$LATEST_TAG" ]; then
echo "No previous tags found for $PACKAGE, using initial commit"
LATEST_TAG=$(git rev-list --max-parents=0 HEAD)
fi
echo "latest_tag=$LATEST_TAG" >> "$GITHUB_OUTPUT"
echo "Latest tag: $LATEST_TAG"
- name: Check if tag already exists
id: tag_check
run: |
TAG_NAME="${{ inputs.package }}-v${{ steps.version_pubspec.outputs.version }}"
if git tag -l | grep -q "^$TAG_NAME$"; then
echo 'exists=true' >> "$GITHUB_OUTPUT"
echo "❌ Tag $TAG_NAME already exists"
else
echo 'exists=false' >> "$GITHUB_OUTPUT"
echo "✅ Tag $TAG_NAME does not exist"
fi
echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT"
- name: Fail if tag exists
if: steps.tag_check.outputs.exists == 'true'
run: |
echo "ERROR: Tag ${{ steps.tag_check.outputs.tag_name }} already exists!"
echo "Please update the version before releasing ${{ inputs.package }}"
exit 1
- name: Generate changelog and update CHANGELOG.md
id: changelog
run: |
PACKAGE_DIR="${{ steps.package_config.outputs.package_dir }}"
VERSION="${{ steps.version_pubspec.outputs.version }}"
echo "Generating changelog for $PACKAGE_DIR from ${{ steps.latest_tag.outputs.latest_tag }} to HEAD"
changelog_cli generate \
--start "${{ steps.latest_tag.outputs.latest_tag }}" \
--end HEAD \
--path "$PACKAGE_DIR" \
--version "$VERSION" \
--output "$PACKAGE_DIR/CHANGELOG.md"
changelog_cli generate \
--start "${{ steps.latest_tag.outputs.latest_tag }}" \
--end HEAD \
--path "$PACKAGE_DIR" \
--version "$VERSION" \
--output /tmp/new_changelog.md
{
echo 'content<<EOF'
cat /tmp/new_changelog.md
echo 'EOF'
} >> "$GITHUB_OUTPUT"
echo "✅ Updated $PACKAGE_DIR/CHANGELOG.md with version $VERSION"
- name: Setup Git
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- name: Commit updated CHANGELOG.md
run: |
PACKAGE_DIR="${{ steps.package_config.outputs.package_dir }}"
VERSION="${{ steps.version_pubspec.outputs.version }}"
git add "$PACKAGE_DIR/CHANGELOG.md"
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "chore($PACKAGE_DIR): update CHANGELOG.md for v$VERSION"
echo "✅ Committed CHANGELOG.md changes"
fi
- name: Push changes
if: ${{ !inputs.dry_run }}
run: git push origin main
- name: Create and push tag
if: ${{ !inputs.dry_run }}
run: |
TAG_NAME="${{ steps.tag_check.outputs.tag_name }}"
git tag -a "$TAG_NAME" -m "Release $TAG_NAME"
git push origin "$TAG_NAME"
echo "✅ Created and pushed tag: $TAG_NAME"
- name: Create GitHub Release
if: ${{ !inputs.dry_run }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG_NAME="${{ steps.tag_check.outputs.tag_name }}"
gh release create "$TAG_NAME" \
--title "$TAG_NAME" \
--notes-file /tmp/new_changelog.md \
--draft
echo "✅ Created GitHub release: $TAG_NAME"
echo "The release is created as draft and will be published after artifacts are uploaded"
- name: Dry run summary
if: ${{ inputs.dry_run }}
run: |
echo "🔍 DRY RUN SUMMARY:"
echo "- Package: ${{ steps.package_config.outputs.package_dir }}"
echo "- Version: ${{ steps.version_pubspec.outputs.version }}"
echo "- Tag that would be created: ${{ steps.tag_check.outputs.tag_name }}"
echo "- Latest tag found: ${{ steps.latest_tag.outputs.latest_tag }}"
echo "- CHANGELOG.md would be updated with new content"
echo "- No actual tag or release would be created"
echo ""
echo "📝 Generated changelog content:"
cat /tmp/new_changelog.md
build_assets:
needs: release
if: ${{ !inputs.dry_run }}
runs-on: ${{ matrix.os }}
strategy:
matrix: ${{ fromJson(needs.release.outputs.build_matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Dart
uses: dart-lang/setup-dart@v1
- name: Install dependencies
run: |
cd "${{ needs.release.outputs.package_dir }}"
dart pub get
- name: Build executable
if: ${{ needs.release.outputs.build_mode == 'exe' }}
run: |
cd "${{ needs.release.outputs.package_dir }}"
mkdir -p "build/${{ matrix.artifact_name }}"
dart compile exe "bin/${{ needs.release.outputs.executable_name }}.dart" -o "build/${{ matrix.artifact_name }}/${{ matrix.binary_name }}"
- name: Upload executable artifact
if: ${{ needs.release.outputs.build_mode == 'exe' }}
uses: actions/upload-artifact@v4
with:
name: asset-${{ matrix.artifact_name }}
path: ${{ needs.release.outputs.package_dir }}/build/${{ matrix.artifact_name }}/${{ matrix.binary_name }}
- name: Build CLI bundle
if: ${{ needs.release.outputs.build_mode == 'bundle' }}
run: |
cd "${{ needs.release.outputs.package_dir }}"
dart build cli --target "bin/${{ needs.release.outputs.executable_name }}.dart" --output "build/${{ matrix.artifact_name }}"
- name: Upload bundle artifact
if: ${{ needs.release.outputs.build_mode == 'bundle' }}
uses: actions/upload-artifact@v4
with:
name: asset-${{ matrix.artifact_name }}
path: ${{ needs.release.outputs.package_dir }}/build/${{ matrix.artifact_name }}/bundle
upload_artifacts:
needs: [release, build_assets]
if: ${{ !inputs.dry_run }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
path: release-assets
pattern: asset-*
- name: Package release bundles
if: ${{ needs.release.outputs.build_mode == 'bundle' }}
run: |
mkdir -p dist
for bundle_dir in release-assets/asset-*; do
asset_name="${bundle_dir#release-assets/asset-}"
(
cd "$bundle_dir"
zip -r "../../dist/${asset_name}.zip" bin lib
)
done
- name: Upload executable artifacts to existing release
if: ${{ needs.release.outputs.build_mode == 'exe' }}
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release.outputs.tag_name }}
files: release-assets/asset-*/*
draft: false
- name: Upload bundle archives to existing release
if: ${{ needs.release.outputs.build_mode == 'bundle' }}
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release.outputs.tag_name }}
files: dist/*.zip
draft: false