Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
934bf61
add: dart pub outdatedの結果をパースし、アップデートが必要なパッケージmdの表形式で出力する処理を作成
r0227n Apr 25, 2025
1bba5ec
add: dart pub outdated のエラーハンドリングを追加
r0227n Apr 25, 2025
2e72be4
add: パッケージ監視パイプラインの叩き台作成
r0227n May 9, 2025
0a09094
chore: GitHubへの権限変更
r0227n May 9, 2025
f5c8cc5
chore: issue作成ログを削除
r0227n May 9, 2025
f1197cb
add: template fileを追加
r0227n May 9, 2025
31a74cb
chore: labelを設定
r0227n May 9, 2025
37bc611
chore: jobの名前をdependbotに変更
r0227n May 9, 2025
a6f19d2
chore: error messageが表示されないため削除
r0227n May 9, 2025
3ea0bb2
chore: onをcronに変更し、毎週月曜9:00に実行するように変更
r0227n May 9, 2025
f8530cc
chore: ifの間にある不要なスペースを削除
r0227n May 9, 2025
2b62130
add: labels.ymlにpackage_updatedを追加
r0227n May 9, 2025
2b6fc3a
chore: mdのテンプレートフォーマット修正
r0227n May 9, 2025
0b1e97f
fix: reviewdogの修正
r0227n May 9, 2025
c38f95a
fix: reviewdogの指摘事項対応
r0227n May 9, 2025
b52a447
Merge branch 'main' into feature/35-update-package
r0227n May 14, 2025
0e8ec1d
fix: PackageInfoのsort_constructors_first を修正
r0227n May 14, 2025
8654b1d
fix: Package のsort_constructors_firstを修正
r0227n May 14, 2025
aaa521e
fix: Package.fromJson内のkindプロパティの型を明示的にし、argument_type_not_assignableを修正
r0227n May 14, 2025
d5ba809
fix: Versionのsort_constructors_firstを修正
r0227n May 14, 2025
c412cfb
fix: tools/update-page.dart lines_longer_than_80_chars fix
r0227n May 14, 2025
fb8d64d
fix: avoid_redundant_argument_valuesを修正
r0227n May 14, 2025
db3ec9d
typo: コメントのタイポを修正
r0227n May 14, 2025
5a5b4a6
Merge branch 'main' into feature/35-update-package
r0227n May 14, 2025
d0905b2
add: 最新のコメントを取得し、内容が同じなら処理をスキップするようにした
r0227n May 15, 2025
bff7c14
fix: $つけ忘れ修正
r0227n May 15, 2025
66bfeba
fix: commentの内容をファイル出力し、参照する形に修正
r0227n May 15, 2025
917d6a0
Merge branch 'main' into feature/35-update-package
r0227n May 15, 2025
db2d62b
add: 同じlabelが複数設定されているのは予期しない状態の旨をコメント追記
r0227n May 15, 2025
072b6e1
delete: 検証用のpushイベントを削除
r0227n May 15, 2025
d3da480
add: timeout を追加
r0227n May 15, 2025
cf44bf0
Merge branch 'main' into feature/35-update-package
r0227n May 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
color: "ffffff"
description: "This will not be worked on"

- name: "package_updated"
color: "0e8a16"
description: "Packages that need to be updated"

# <!-- This is an auto-generated label -->
- name: "@apps/catalog"
color: d4f227
Expand Down
101 changes: 101 additions & 0 deletions .github/workflows/issue-dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Issue-Dependbot

on:
schedule:
- cron: "0 0 * * 1" # 日本標準時間 毎週月曜日の朝9:00

env:
ISSUE_LABEL: package_update

jobs:
dependbot:
runs-on: ubuntu-22.04
permissions:
issues: write
timeout-minutes: 5
steps:
# https://github.com/marketplace/actions/checkout
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup Application Runtime
uses: ./.github/actions/setup-application-runtime

- name: Check for package updates
id: package
run: |
update=$(dart run ./tools/update_package.dart)

if [ -z "$update" ]; then
echo "No update"
exit 0;
fi

path="$GITHUB_WORKSPACE/package_$(date +%Y%m%d%H%M%S)"
echo "$update" > "$path"
echo "path=$path" >> "$GITHUB_OUTPUT"

- name: Get Issue Number
id: issue
if: "${{ steps.package.outputs.path != '' }}"
run: |
getIssueNumber() {
issue_numbers=$(gh issue list --label "$ISSUE_LABEL" --json number | jq '.[].number')

issue_numbers_length=$(echo "$issue_numbers" | grep -c .)
if [ "$issue_numbers_length" -gt 1 ]; then
echo "Multiple issues exist. Please check the issue."
exit 1
elif [ "$issue_numbers_length" -eq 0 ]; then
issue_url=$(gh issue create --title "Update package" --label "$ISSUE_LABEL" --body-file ./tools/templates/issue_improve.md)
issue_number=$(echo "$issue_url" | sed -E 's/.*\/issues\/([0-9]+)$/\1/')
echo "$issue_number"
else
echo "$issue_numbers"
fi
}

issue_number=$(getIssueNumber)

echo "Issue Number: $issue_number"
echo "number=$issue_number" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Get the latest issue comment
id: latest
run: |
comment=$(gh issue view "${{ steps.issue.outputs.number }}" --json comments -q '.comments | last.body')

path="$GITHUB_WORKSPACE/comment_$(date +%Y%m%d%H%M%S)"
echo "$comment" > "$path"
echo "path=$path" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check if the latest comment is the same as the current comment
id: comment_check
run: |
package_comment=$(cat "${{ steps.package.outputs.path }}")
latest_comment=$(cat "${{ steps.latest.outputs.path }}")

if [[ "$package_comment" == "$latest_comment" ]]; then
echo "The latest comment is the same as the current comment"
exit 0
fi
Comment on lines +82 to +85

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️


echo "The latest comment is different from the current comment"
echo "changed=true" >> "$GITHUB_OUTPUT"

- name: Comment
if: ${{ steps.comment_check.outputs.changed == 'true' }}
run: gh issue comment "${{ steps.issue.outputs.number }}" --body-file "${{ steps.package.outputs.path }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}







137 changes: 137 additions & 0 deletions tools/model/package_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
enum Kind {
transitive,
dev,
direct;

const Kind();

factory Kind.fromString(String value) {
for (final kind in Kind.values) {
if (value == kind.name) {
return kind;
}
}

throw ArgumentError('Kind donse not have $value');
}
}

extension ExtString on String {
String substringIgnores({List<String> ignores = const ['-', '+']}) {
for (final pattern in ignores) {
final index = indexOf(pattern);
if (index != -1) {
return substring(0, index);
}
}

return this;
}
}

class PackageInfo {
const PackageInfo({required this.packages});

factory PackageInfo.fromJson(Map<String, dynamic> data) => PackageInfo(
Comment thread
den0206 marked this conversation as resolved.
packages: (data['packages'] as List<dynamic>)
.map((e) => Package.fromJson(e as Map<String, dynamic>))
.toList(),
);

final List<Package> packages;

Map<String, dynamic> toJson() => {
'packages': packages.map((e) => e.toJson()).toList(),
};
}

class Package {
const Package({
required this.package,
required this.kind,
required this.isDiscontinued,
required this.isCurrentRetracted,
required this.isCurrentAffectedByAdvisory,
required this.current,
required this.upgradable,
required this.resolvable,
required this.latest,
});

factory Package.fromJson(Map<String, dynamic> data) => Package(
Comment thread
den0206 marked this conversation as resolved.
package: data['package'] as String,
kind: Kind.fromString(data['kind'] as String),
isDiscontinued: data['isDiscontinued'] as bool,
isCurrentRetracted: data['isCurrentRetracted'] as bool,
isCurrentAffectedByAdvisory:
data['isCurrentAffectedByAdvisory'] as bool,
current: data['current'] == null
? null
: Version.fromJson(data['current'] as Map<String, dynamic>),
upgradable:
Version.fromJson(data['upgradable'] as Map<String, dynamic>),
resolvable:
Version.fromJson(data['resolvable'] as Map<String, dynamic>),
latest: Version.fromJson(data['latest'] as Map<String, dynamic>),
);

final String package;
final Kind kind;
final bool isDiscontinued;
final bool isCurrentRetracted;
final bool isCurrentAffectedByAdvisory;
final Version? current;
final Version upgradable;
final Version resolvable;
final Version latest;

Map<String, dynamic> toJson() => {
'package': package,
'kind': kind,
'isDiscontinued': isDiscontinued,
'isCurrentRetracted': isCurrentRetracted,
'isCurrentAffectedByAdvisory': isCurrentAffectedByAdvisory,
'current': current?.toJson(),
'upgradable': upgradable.toJson(),
'resolvable': resolvable.toJson(),
'latest': latest.toJson(),
};
}

class Version implements Comparable<Version> {
const Version({required this.version});

factory Version.fromJson(Map<String, dynamic> data) => Version(
Comment thread
den0206 marked this conversation as resolved.
version: data['version'] as String,
);

final String version;

Map<String, dynamic> toJson() => {
'version': version,
};

@override
int compareTo(Version other) {
final currentVersion = version.substringIgnores().split('.');

final resolvableVersion = other.version.substringIgnores().split('.');
if (resolvableVersion.length != 3) {
throw ArgumentError('${other.version} is not forma: x.x.x');
}

for (var index = 0; index < 3; index++) {
final currentNum = int.parse(currentVersion[index]);
final resolvableNum = int.parse(resolvableVersion[index]);

final compare = currentNum.compareTo(resolvableNum);
if (compare == 0) {
continue;
}

return compare;
}

return 0;
}
}
18 changes: 18 additions & 0 deletions tools/templates/issue_improve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## これに関する既存の Issue はありますか?

検索して、既存の Issue の有無を確認してください。

- [x] 既存の Issue はありませんでした (必須)

---

## 背景

パッケージのversionが古く、セキュリティリスクや新機能による改善ができない状況です。

---

## 提案の詳細

どのように改善するかについて、具体的に説明してください。
`github-actions` が作成した最新のコメントに記載されたパッケージを更新してください。
54 changes: 54 additions & 0 deletions tools/update_package.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'dart:convert';
import 'dart:io';
import 'model/package_info.dart';

/// dart pub outdated を時加工し、パッケージの更新有無を取得する
Future<void> main() async {
const executable = 'dart';
const arguments = ['pub', 'outdated', '--json'];

final json = await Process.run(executable, arguments).then(
(e) => e.stdout as String,
);

if (json.isEmpty) {
throw ProcessException(
executable,
arguments,
'Failed to execute $executable $arguments',
);
}

final packageInfo =
PackageInfo.fromJson(jsonDecode(json) as Map<String, dynamic>);

final shouldUpdatePkg = packageInfo.packages.where((pkg) {
if (pkg.current != null && pkg.kind != Kind.transitive) {
// 依存関係で追加されたパッケージ以外 && パッケージが最新以外の内容を取得
return pkg.current!.compareTo(pkg.resolvable) != 0;
}

return false;
});

if (shouldUpdatePkg.isEmpty) {
return;
}

final rows = [
'''
## Update package
| package | current | resolvable |
| :--- | :--- | :--- |
'''
];

for (final pkg in shouldUpdatePkg) {
final row =
'''| ${pkg.package} | ${pkg.current?.version ?? 'null'} | ${pkg.resolvable.version} | \n''';

rows.add(row);
}

stdout.writeln(rows.join().trim());
}