Skip to content

Commit 051f5fc

Browse files
committed
update
1 parent 96b6e4c commit 051f5fc

6 files changed

Lines changed: 217 additions & 167 deletions

File tree

.github/_README.md

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,72 @@
1-
# Workflow for Managing Pub.dev Packages
1+
# pub.dev_package_workflow
2+
3+
This repository provides a powerful and streamlined set of GitHub Actions workflows designed to automate the entire lifecycle of your Dart and Flutter packages—from version bumping and changelog generation to publishing on pub.dev and deploying examples to GitHub Pages.
4+
5+
---
6+
7+
## 🚀 Core Features
8+
9+
- **Automated Version Bumping:** Automatically update `CHANGELOG.md`, `README.md`, and other files when you're ready to release.
10+
- **Git Tagging:** Automatically create and push Git tags for new versions.
11+
- **Flexible Publishing Triggers:** Publish packages automatically via special commit messages or by creating a release in the GitHub UI.
12+
- **Example App Deployment:** An optional workflow to build and deploy a Flutter web example to GitHub Pages.
213

314
## Workflows
415

5-
**This repository contains GitHub Actions workflows that simplify the management of your pub.dev packages:**
16+
This project contains three key GitHub Actions workflows.
17+
18+
### 1. `process-package.yml`
19+
20+
This is the primary workflow for managing releases directly from your commit messages. It triggers on every push to your `main` branch.
21+
22+
- **Standard Commits:** For any normal commit message, the workflow does nothing.
23+
- **Prepare a Release (`+`):** If your commit message starts with a single plus sign (e.g., `+Added new feature`), the workflow will:
24+
- Run `dart format` and `dart fix --apply`.
25+
- Update your `CHANGELOG.md` with the commit message.
26+
- Generate a standardized `README.md` from a central template.
27+
- Commit these automated changes with the message `ci: bump version to v[version]`.
28+
- Create and push a Git tag for the new version.
29+
- **Prepare and Publish (`++`):** If your commit message starts with two plus signs (e.g., `++Major performance improvements`), the workflow will do **everything above** and then automatically **publish the package to pub.dev** if properly configured. See https://dart.dev/tools/pub/automated-publishing.
30+
31+
### 2. `publish.yml`
32+
33+
This workflow provides a manual trigger for publishing. It activates **only** when you create a new release in the GitHub UI. This is perfect for when you want to review changes on the `main` branch before deciding to publish.
634

7-
- The `prepare.yaml` workflow triggers on every push to the main branch. It automatically updates the CHANGELOG.md, formats the Dart code, and applies Dart fixes with each push.
8-
- The `publish.yaml` workflow activates upon the creation of a new release, automatically handling the package's publication to pub.dev.
35+
### 3. `deploy-example.yml` (Optional)
936

10-
## Setup Instructions
37+
If your project contains a Flutter web example in a `hosted_example` directory, this workflow will automatically build it and deploy it to GitHub Pages on every push to the `main` branch. This is great for providing live demos of your package.
1138

12-
**1. Navigate to your project:**
39+
---
40+
41+
## 🛠️ Setup Instructions
42+
43+
Setting up these workflows in your own package repository is simple.
44+
45+
**1. Navigate to Your Project's Root Directory**
46+
47+
Open your terminal and `cd` into the root of your Dart or Flutter package.
1348

1449
```zsh
15-
cd your_project
50+
cd /path/to/your_project
1651
```
1752

18-
**2. Clone this repo into a `.github/` folder:**
53+
**2. Clone this Workflow Repository**
54+
55+
Clone this repository directly into a `.github` folder. This will create `.github/workflows` and `.github/scripts` for you.
1956

2057
```zsh
2158
git clone https://github.com/dev-cetera/pub.dev_package_workflow.git .github
2259
```
2360

24-
**3. Remove the `/.git` folder to include it to your project:**
61+
**3. Remove the Nested `.git` Directory**
2562

26-
_On macOS and Linux:_
63+
To make these workflow files part of your own project's Git history, you must delete the nested `.git` directory that was just cloned.
2764

28-
```zsh
29-
rm -rf .github/.git/
30-
```
65+
**4. Configure `pub.dev` for Automated Publishing**
3166

32-
_On Windows:_
67+
For the `publish.yml` workflow to work, you must authorize GitHub Actions on `pub.dev`.
3368

34-
```cmd
35-
rmdir /s /q .github/.git/
36-
```
69+
- Go to your package's page on `pub.dev` and click the **Admin** tab.
70+
- Under **Automated publishing**, click **Enable publishing from GitHub Actions**.
71+
- Set the **Repository** to your `username/repository_name`.
72+
- Set the **Tag pattern** to `v{{version}}`.

.github/scripts/update_changelog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import 'dart:io';
1616

1717
void main(List<String> args) {
1818
final version = args.isNotEmpty ? args[0] : '0.1.0';
19-
final comitMesssage = args.length > 1 ? args[1].replaceFirst('+', '') : '';
19+
final comitMesssage = args.length > 1 ? args[1].replaceFirst(RegExp(r'^\++'), '') : '';
2020
final changelogPath = 'CHANGELOG.md';
2121
final file = File(changelogPath);
2222
if (!file.existsSync()) {

.github/workflows/deploy.yml_REMOVE_TO_ENABLE renamed to .github/workflows/deploy-examplet.yml_REMOVE_TO_ENABLE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
## ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
1111
##.title~
1212

13-
name: Deploy hosted_example to GitHub Pages
13+
name: Deploy Example on Commit
1414

1515
## -----------------------------------------------------------------------------
1616

.github/workflows/prepare.yml

Lines changed: 0 additions & 120 deletions
This file was deleted.
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
##.title
2+
## ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
3+
##
4+
## Dart/Flutter (DF) Packages by dev-cetera.com & contributors. The use of this
5+
## source code is governed by an MIT-style license described in the LICENSE
6+
## file located in this project's root directory.
7+
##
8+
## See: https://opensource.org/license/mit
9+
##
10+
## ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
11+
##.title~
12+
13+
name: Process Package
14+
15+
## -----------------------------------------------------------------------------
16+
17+
# Defines the events that trigger the workflow
18+
on:
19+
push:
20+
branches:
21+
- main # Workflow runs when code is pushed to the 'main' branch
22+
23+
## -----------------------------------------------------------------------------
24+
25+
# Defines the jobs to be executed in the workflow
26+
jobs:
27+
# JOB 1: Prepares files and creates a Git tag for ANY '+' commit
28+
prepare:
29+
runs-on: ubuntu-latest # Specifies the environment (Ubuntu) for the job
30+
permissions:
31+
contents: write # To push commits and tags
32+
# Defines the outputs of this job, so the next job can use them
33+
outputs:
34+
should_create_full_release: ${{ steps.check_message.outputs.IS_FULL_RELEASE }}
35+
version: ${{ steps.get_package_info.outputs.PUBSPEC_VERSION }}
36+
release_notes: ${{ steps.get_package_info.outputs.RELEASE_NOTES }}
37+
38+
steps:
39+
# Step 1: Checkout the full repository history
40+
- name: Checkout code
41+
uses: actions/checkout@v3 # Uses the checkout action to clone the repository
42+
with:
43+
fetch-depth: 0 # Fetches the entire commit history for accurate versioning
44+
45+
# Step 2: Get the first line of the latest commit message
46+
- name: Get commit message
47+
id: get_commit # Assigns an ID to reference outputs later
48+
run: |
49+
# Extracts the first line of the latest commit message
50+
COMMIT_MSG=$(git log --format=%B -n 1 HEAD | head -n 1)
51+
# Stores the commit message in the GitHub Actions output
52+
echo "COMMIT_MSG=$COMMIT_MSG" >> $GITHUB_OUTPUT
53+
54+
# Step 3: Check for release/publish triggers
55+
- name: Check for release triggers
56+
id: check_message # Assigns an ID to reference outputs later
57+
run: |
58+
COMMIT_MSG="${{ steps.get_commit.outputs.COMMIT_MSG }}"
59+
# Checks if the commit message starts with one or more '+' to trigger preparation
60+
if [[ "$COMMIT_MSG" == +* ]]; then echo "SHOULD_PREPARE=true" >> $GITHUB_OUTPUT; else echo "SHOULD_PREPARE=false" >> $GITHUB_OUTPUT; fi
61+
# Checks if the commit message starts with exactly '++' to trigger a full release
62+
if [[ "$COMMIT_MSG" == ++* ]]; then echo "IS_FULL_RELEASE=true" >> $GITHUB_OUTPUT; else echo "IS_FULL_RELEASE=false" >> $GITHUB_OUTPUT; fi
63+
64+
# Step 4: Extract package info from pubspec.yaml and clean release notes
65+
- name: Extract package info
66+
if: steps.check_message.outputs.SHOULD_PREPARE == 'true' # Only runs if preparation is triggered
67+
id: get_package_info
68+
run: |
69+
# Extracts the version number from pubspec.yaml
70+
VERSION=$(grep "version:" pubspec.yaml | sed 's/version: //')
71+
# Extracts the package name from pubspec.yaml
72+
PACKAGE_NAME=$(grep "name:" pubspec.yaml | sed 's/name: //')
73+
# Cleans the commit message for use as release notes
74+
RELEASE_NOTES=$(echo "${{ steps.get_commit.outputs.COMMIT_MSG }}" | sed 's/^\++//' | xargs)
75+
# Stores all extracted info in GitHub Actions output
76+
echo "PUBSPEC_VERSION=$VERSION" >> $GITHUB_OUTPUT
77+
echo "PACKAGE_NAME=$PACKAGE_NAME" >> $GITHUB_OUTPUT
78+
echo "RELEASE_NOTES=$RELEASE_NOTES" >> $GITHUB_OUTPUT
79+
80+
# Step 5: Set up Dart environment
81+
- name: Set up Dart
82+
if: steps.check_message.outputs.SHOULD_PREPARE == 'true' # Only runs if preparation is triggered
83+
uses: dart-lang/setup-dart@v1 # Installs the Dart SDK for subsequent steps
84+
85+
# Step 6: Fetch _README_TEMPLATE.md
86+
- name: Fetch README Template
87+
if: steps.check_message.outputs.SHOULD_PREPARE == 'true' # Only runs if preparation is triggered
88+
id: fetch_template
89+
run: |
90+
# Clones the Dart package template repository to access the README template
91+
git clone --depth 1 https://github.com/dev-cetera/dart_package_template.git /tmp/dart_package_template
92+
# Stores the path to the README template in this step's output
93+
echo "TEMPLATE_PATH=/tmp/dart_package_template/_README_TEMPLATE.md" >> $GITHUB_OUTPUT
94+
95+
# Step 7: Format, Fix, and Update Documentation
96+
- name: Format, Fix, and Update Docs
97+
if: steps.check_message.outputs.SHOULD_PREPARE == 'true' # Only runs if preparation is triggered
98+
run: |
99+
# Runs Dart formatter to standardize code formatting
100+
dart format .
101+
# Applies automatic fixes to Dart code for consistency
102+
dart fix --apply
103+
# Runs a Dart script to update the changelog with the version and release notes
104+
dart run .github/scripts/update_changelog.dart "${{ steps.get_package_info.outputs.PUBSPEC_VERSION }}" "${{ steps.get_package_info.outputs.RELEASE_NOTES }}"
105+
# Runs a Dart script to generate README.md using the template, package name, and version
106+
dart run .github/scripts/update_readme.dart "${{ steps.fetch_template.outputs.TEMPLATE_PATH }}" "${{ steps.get_package_info.outputs.PACKAGE_NAME }}" "${{ steps.get_package_info.outputs.PUBSPEC_VERSION }}"
107+
108+
# Step 8: Commit and Push automated changes
109+
- name: Commit and Push Changes
110+
if: steps.check_message.outputs.SHOULD_PREPARE == 'true' # Only runs if preparation is triggered
111+
run: |
112+
# Configures Git user for the automated commit
113+
git config user.name "github-actions[bot]"
114+
git config user.email "github-actions[bot]@users.noreply.github.com"
115+
# Stages all changes
116+
git add .
117+
# Commits changes only if there are staged changes
118+
if ! git diff --staged --quiet; then
119+
git commit -m "ci: bump version to v${{ steps.get_package_info.outputs.PUBSPEC_VERSION }}"
120+
# Rebases local changes to avoid race conditions before pushing
121+
git pull --rebase
122+
# Pushes the updated main branch to the remote repository
123+
git push origin main
124+
else
125+
echo "No changes to commit."
126+
fi
127+
128+
# Step 9: Create and Push Git Tag
129+
- name: Create and Push Git Tag
130+
if: steps.check_message.outputs.SHOULD_PREPARE == 'true' # Only runs if preparation is triggered
131+
run: |
132+
# Defines the tag name based on the package version
133+
TAG_NAME="v${{ steps.get_package_info.outputs.PUBSPEC_VERSION }}"
134+
echo "Creating tag ${TAG_NAME}..."
135+
# Creates or updates the tag with an annotated message, forcing overwrite if it exists locally
136+
git tag -a -f "$TAG_NAME" -m "Release version ${TAG_NAME}"
137+
# Pushes the tag to the remote repository, forcing overwrite if it exists there
138+
git push origin "$TAG_NAME" --force
139+
echo "Successfully pushed tag ${TAG_NAME}."
140+
141+
# # JOB 2: Creates the GitHub Release ONLY for '++' commits
142+
# create_release:
143+
# needs: prepare # This job depends on the 'prepare' job finishing successfully.
144+
# if: needs.prepare.outputs.should_create_full_release == 'true' # This entire job will ONLY RUN if the commit started with '++'.
145+
# runs-on: ubuntu-latest
146+
# permissions:
147+
# contents: write # To create the release
148+
149+
# steps:
150+
# # This job's only step is to create a formal GitHub Release from the tag pushed by the 'prepare' job.
151+
# - name: Create GitHub Release from existing tag
152+
# env:
153+
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Provides authentication for the GitHub CLI
154+
# run: |
155+
# # Get the tag name from the previous job's output
156+
# TAG_NAME="v${{ needs.prepare.outputs.version }}"
157+
# echo "Found full release trigger. Creating GitHub Release from tag ${TAG_NAME}..."
158+
# # Uses the GitHub CLI to create a release from the existing tag.
159+
# # This action will trigger the separate 'publish.yml' workflow.
160+
# gh release create "$TAG_NAME" \
161+
# --title "Release ${TAG_NAME}" \
162+
# --notes "${{ needs.prepare.outputs.release_notes }}"

0 commit comments

Comments
 (0)