メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

GitHub ActionsでFlutterのPluginをリリースできるActionをMarketplaceに公開した

FlutterでPluginを作りたいと思ったらPubに登録するのが一般的です。

もともとGitHub Actionsでリリースできるようにしていたのですが、Pluginに依らずやることは同じなのでAction化してMarketplaceに公開しました。

github.com

Marketplaceに公開までにあたりいくつかハマった点があったので共有します。

Dockerイメージのユーザはrootである必要

今回はcirrues/flutterのDockerイメージを利用していたのですが、ユーザを指定していたため、Permission deniedで怒られました。

現状GitHub ActionsはDockerのデフォルトユーザ(root)での実行を想定しています。それ以外だとGITHUB_WORKSPACE にアクセスできないため、ファイル作成などでPermission errorが出ます。

なので、今回のケースにおいてはDockerfile内でユーザをrootに指定しなおします。

  • Dockerfile
USER root

Dockerイメージをそのまま使う場合は引数で指定してあげるとうまくいきます。

container:
  image: cirrusci/flutter:stable
  options: -u root

inputsは自動的に環境変数に登録される

envで指定しなくても環境変数として渡ります。もしも明示的に引数として扱いたい場合は args に渡してあげればよいです。

inputsで渡した場合は頭に INPUT_ が付いて大文字に変換された名前で環境変数に登録されます。任意の名前で扱いたい場合は envで渡すのもよいと思います。

同一リポジトリでの確認

作成しているGitHub Actionsの確認に利用できます。.github/workflows/ に置いたyamlが、通常のGitHub Actionsと同様に実行されます。 uses: ./ と指定してあげることで、作成中のActionを指定することができます。自分が確認している範囲では、ローカル環境での動作確認はまだできないみたいです。

jobs:
  test_job:
    runs-on: ubuntu-latest
    name: Test
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Test action
        uses: ./

作成したActionのMarketplaceでのURLはnameが使われる

GitHubリポジトリ名が使われると思ってたのですがそうではなかったです。作成の際にはnameに気をつけてください。

ややこしいことに、yamlのAction名にはリポジトリ名が利用されます。揃えておいたほうが利用者にとってわかりやすいので、なるべく揃えたほうが良いと思います。

Actionを利用するときのバージョン指定は完全一致じゃないとNot foundになる

よく使う、 actions/checkout@v1 のようにメジャーバージョンだけ指定すればよしなにv1.y.zの最新のバージョンが利用されると思っていたのですがそうではありませんでした。

現状はタグ名の完全一致で見ているようです。 v1 タグがしっかり存在していました。

しかしこの仕様は見直される可能性があるみたいです。

まとめ

ドキュメントをよく読むことに尽きるのですが、構造化されてなくて現状結構情報が探しにくいと思います。すでに公開されているActionが非常に参考になるので探して動かしてみると色々わかると思います。

また、Community Forumに投稿したり検索したりするとわりと情報が見つかるので活用すると良いです。

github.community

こちらは今回公開したActionの利用例です。

github.com

参考

Virtual environments for GitHub Actions - GitHub Help

Creating a Docker container action - GitHub Help

Solved: Version numbering for Actions - GitHub Community Forum

パッケージが統合されたFlutter for Webへのアップグレード

Flutter for Webのパッケージがflutterに統合されました。それに伴い既存のFlutter for Webのプロジェクトでアップグレードが必要になったのでその記録です。

Upgrading

まだstableには来てないのでdevに向けて、webを有効にします。

$ flutter channel dev
$ flutter upgrade
$ flutter config --enable-web

channelの変更は、次のバージョンがstableに来たら不要になると思います

$ flutter --version
Flutter 1.10.6 • channel dev • https://github.com/flutter/flutter.git
Framework • revision cc3ca9a916 (5 days ago) • 2019-09-25 10:57:58 -0400
Engine • revision 63949eb0fd
Tools • Dart 2.6.0 (build 2.6.0-dev.0.0 69b5681546)

既存プロジェクトですでに作成済みの web/main.dart を削除します。

次に、プロジェクトをFlutter SDK向けに変更していきます。

AndroidiOSディレクトリを作成します

$ flutter create .

pubspec.yamlを置き換えて、flutter_webの部分をflutterに置き換えます。

web/assets/ に置いていた FontManifest.json の内容を移行します。

MaterialIconsは

flutter:
  uses-material-design: true

となり、

fontを利用していた場合は fonts フォルダをプロジェクトルートに作り、そこにフォントファイルを置きます。その後、font名の指定とfontのpathを書きます。

flutter:
  ...
  fonts:
    - family: KosugiMaru
      fonts:
        - asset: fonts/KosugiMaru-Regular.ttf

画像などの素材は、 assets フォルダをプロジェクトルートに作り、そこに移動させます。その後フォルダを指定します。

flutter:
  ...
  assets:
    - assets/

これで web/assets フォルダは空になったと思うので、削除します。

実行は次のコマンドです。Windowが立ち上がります。

$ flutter run -d chrome

ドキュメント的には以上なのですが、自分の環境では更に次のような手順が必要でした。

追加手順

rootBundleのimport

rootBundle を使っている場合、含まれるパッケージが変わっているので flutter/service からimportします。

import 'package:flutter/services.dart' show rootBundle;

assetsのパス

rootBundleでassetsにアクセスしている場合、pathが次のように変わります。

  • some.json

だったものが

  • assets/some.json

になります。assetsに指定しているフォルダからpathを指定する必要があります。

BinaryMessengerへのアクセス

runApp より早いタイミングで rootBundle を利用している場合、chromeのconsoleにエラーが出ます。

Uncaught (in promise) Error: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.

rootBundleがbinaryMessengerを利用しているため、怒られます。回避するためにはエラー文の通り、

WidgetsFlutterBinding.ensureInitialized()rootBundleより先に呼び出します。

dart:htmlのimportエラー

自分はIntelliJで開発しているのですが、Target of URI doesn’t exist: ‘dart:html’. のエラーが出ました。ですが、ターミナルからビルドする分には問題ありませんでした。

現状Dart SDKが提供しているもので、利用できるものとそうでないものがあるみたいです。

github.com

Release Buildのアウトプット先

今までは build/だったのですが、build/web/ に変わりました。Deployする際には注意が必要です。

リリースビルドのコマンドは次です。デフォルトでreleaseのconfigurationになっています。

$ flutter build web

まとめ

パッケージ統合以前のFlutter for Webのプロジェクトでも、アップグレードガイドがあるので移行自体はさっとできます。

ただし、いくつか注意点があるのでハマりすぎないように気をつけてください。

自分の環境において、マイグレーションのドキュメントに書いてないことで気をつける必要があったことは次の5点です。

  • rootBundleのimportが変わる
  • assetsのパスが変わる
  • assetsに早いタイミングでアクセスしている場合はWidgetsFlutterBinding.ensureInitialized() が必要になる
  • Dart SDKのいくつかのパッケージはWebでの利用に制限がある
  • アウトプットのpathが異なる

参考

Upgrading from package:flutter_web to the Flutter SDK · flutter/flutter Wiki · GitHub

Flutter: Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized - Stack Overflow

Properly enable dart:html imports · Issue #35588 · flutter/flutter · GitHub

Building a web application with Flutter - Flutter

技術書典7にFitbit本の続編を出した

先日開催された技術書典7にサークル参加しました。サークル参加としては2回目で、技術書典5以来なので1年ぶりの参加でした。

前回の参加記事はこちら

sakebook.hatenablog.com

事前準備(執筆編)

1年ぶりで、結構色々忘れていました。

次の記事を参考に環境を構築しました。去年と大きく異なっていたのは、Re:VIEWのメジャーバージョンが2から3に変わっていました。

mochikoastech.hatenablog.com

続編という位置づけで考えていたのですが、旧刊を購入していないと話がわからないのでは敷居が高すぎると思ったので、一部内容は重複してしまうのですが、それぞれ独立して読めるような構成にしました

今回は表紙をお願いすることにしました。

お願いするにあたって、何が決まっていれば嬉しいのかがわからなかったので、こんな感じだと嬉しいなってのをboothからピックアップして雰囲気を伝えました。

あとは表示サイズと仮タイトルを伝えて、ここはこういうふうにしたほうがFitbitをつけてるのが映えるよーってのをやり取りして決めていきました。

印刷は前回と同じく日光企画さんにお願いしました。Fitbit Versa 2の発売日が技術書展7の明後日なので、なるべく最新の情報を詰めたくて前日まで粘ってたのですが、結局開発者向けの新しい情報は公開されませんでした。

前日印刷でも、午前10時までにデータを入稿すれば間に合いはしますが、印刷代が倍くらいに膨れるので最後の手段と思ったほうが良さそうです。

自分の場合だとA5サイズ64ページで50冊印刷して50,240円でした。

事前準備(ブース編)

前回の振り返りを見て、背の高いPOPスタンドを置いておくと目立つというのと、卓上に布があったほうが圧倒的に見栄えが良いことがわかっていたので、準備しました。

シンプルなあの布POPスタンドを用意しました。

今回は本の価格を1000円にしました。残っていた旧刊も売れればいいなと思い持っていきました。旧刊は500円なので、数枚程度500円玉を用意し、万札にも耐えられるように1000円札を用意しました。

あとはPOPスタンドに吊るす紙をA4で印刷し、電子版も対応していたのでQRコードを印刷した紙を用意しました。

当日

若干遅刻してしまいました。サークル入場も遅れていたので結果的に自分はほとんど待つことなく入場できましたが、準備が間に合わないんじゃないかとヒヤヒヤしました。

本は技術書典のバックアップ印刷所さんに依頼しておけばブースまで持ってきてもらえます。当日着いたらすでに届いていました。

実際の部数は65冊ありました。

遅れたこともあり、立ち読み本の扱いがよくわからなかったのですが横のサークルの方に教えてもらい、無事提出できました。準備はサッとできました。

実は今回も売り子を見つけられず一人での参加となりました。辛かったですがお手洗いなどは横のサークルの方が気を利かせてくれて助かりました。

技術書典5でFitbit本を購入し、今回も購入してくださった方がいてめちゃめちゃ嬉しかったです。

後払いで20部、現金で19部の合計39部売れました。印刷代やサークル参加費を考えると赤字です。旧刊は完売したのでそこは良かったです。余った部数が多かったのでboothにあずけて帰りました。boothでも、月に安定して売上が立たなければ保管料金がかかるみたいなので注意です

今回販売した新刊のboothリンクです。Versa 2買った人や購入検討中の人は買って損のない内容になってます。

sakebook.booth.pm

終わってみて

一人参加は相変わらず辛いですが、ちょっとこなれた感じがあります。ウェアラブルバイスに関するサークルがうちと横のサークルしかなく、横の方はその辺りを話題にだしたりしていたのですが、自分はあまりそういう接客ができていなかったです。交流という意味でも接客という意味でもその辺りはもう少しやりようはあったなーと思いました。

立ち読みはしてくれたのですが、そこから購入に至らなかった人がわりといました。本の質の問題なのか、目次から読み取りにくかったのか、思ってたのと違ったのか、その辺りがわからないのが辛いところです。

掛けた時間と帰ってくるお金は相変わらず見合わないですが、サークル参加自体は敷居が低くなってきているので、気になってる方はやってみると良いと思います。自分の好きなことを好き勝手書いていいんですよ!

参考

技術書典7

BOOTH - 創作物の総合マーケット

株式会社 日光企画