-
Notifications
You must be signed in to change notification settings - Fork 9
[35]更新が必要なパッケージ情報をIssueに起票するPIpelineの作成 #409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
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 1bba5ec
add: dart pub outdated のエラーハンドリングを追加
r0227n 2e72be4
add: パッケージ監視パイプラインの叩き台作成
r0227n 0a09094
chore: GitHubへの権限変更
r0227n f5c8cc5
chore: issue作成ログを削除
r0227n f1197cb
add: template fileを追加
r0227n 31a74cb
chore: labelを設定
r0227n 37bc611
chore: jobの名前をdependbotに変更
r0227n a6f19d2
chore: error messageが表示されないため削除
r0227n 3ea0bb2
chore: onをcronに変更し、毎週月曜9:00に実行するように変更
r0227n f8530cc
chore: ifの間にある不要なスペースを削除
r0227n 2b62130
add: labels.ymlにpackage_updatedを追加
r0227n 2b6fc3a
chore: mdのテンプレートフォーマット修正
r0227n 0b1e97f
fix: reviewdogの修正
r0227n c38f95a
fix: reviewdogの指摘事項対応
r0227n b52a447
Merge branch 'main' into feature/35-update-package
r0227n 0e8ec1d
fix: PackageInfoのsort_constructors_first を修正
r0227n 8654b1d
fix: Package のsort_constructors_firstを修正
r0227n aaa521e
fix: Package.fromJson内のkindプロパティの型を明示的にし、argument_type_not_assignableを修正
r0227n d5ba809
fix: Versionのsort_constructors_firstを修正
r0227n c412cfb
fix: tools/update-page.dart lines_longer_than_80_chars fix
r0227n fb8d64d
fix: avoid_redundant_argument_valuesを修正
r0227n db3ec9d
typo: コメントのタイポを修正
r0227n 5a5b4a6
Merge branch 'main' into feature/35-update-package
r0227n d0905b2
add: 最新のコメントを取得し、内容が同じなら処理をスキップするようにした
r0227n bff7c14
fix: $つけ忘れ修正
r0227n 66bfeba
fix: commentの内容をファイル出力し、参照する形に修正
r0227n 917d6a0
Merge branch 'main' into feature/35-update-package
r0227n db2d62b
add: 同じlabelが複数設定されているのは予期しない状態の旨をコメント追記
r0227n 072b6e1
delete: 検証用のpushイベントを削除
r0227n d3da480
add: timeout を追加
r0227n cf44bf0
Merge branch 'main' into feature/35-update-package
r0227n File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| 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 | ||
|
|
||
| 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 }} | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
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
| 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( | ||
|
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( | ||
|
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( | ||
|
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; | ||
| } | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| ## これに関する既存の Issue はありますか? | ||
|
|
||
| 検索して、既存の Issue の有無を確認してください。 | ||
|
|
||
| - [x] 既存の Issue はありませんでした (必須) | ||
|
|
||
| --- | ||
|
|
||
| ## 背景 | ||
|
|
||
| パッケージのversionが古く、セキュリティリスクや新機能による改善ができない状況です。 | ||
|
|
||
| --- | ||
|
|
||
| ## 提案の詳細 | ||
|
|
||
| どのように改善するかについて、具体的に説明してください。 | ||
| `github-actions` が作成した最新のコメントに記載されたパッケージを更新してください。 |
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
| 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()); | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️