チケットの担当者が変わったときに、SlackやRocket.Chat、Teamsなどに通知するプラグイン、Redmine issue assign notice pluginのv1.1.2をリリースしました。
担当者にグループをアサインするとエラーとなるという致命的な問題でした。
私の関わるプロジェクトでも、先日やっと導入しました。とっても便利ですね!
チケットの担当者が変わったときに、SlackやRocket.Chat、Teamsなどに通知するプラグイン、Redmine issue assign notice pluginのv1.1.2をリリースしました。
担当者にグループをアサインするとエラーとなるという致命的な問題でした。
私の関わるプロジェクトでも、先日やっと導入しました。とっても便利ですね!
2020年はコロナもあって、数年ぶりにまったくライブに行かない年になりました。
逆に家での時間が増えたので、その分家で音楽を聴く時間も増えたと思います。
Spotifyの2020まとめでみた12月3日時点でのトータル視聴時間は 74,646時間でした。
夜中はYouTubeでPV流しながら作業するし、SoundCloudでも音楽聴くので、それを考慮すると、1日平均で4時間以上は音楽聴いていたようです。
2019年のSpotifyまとめの画像がもう見れないので比較画像は貼れないのですが、、2019年は洋楽ばっかり(1位のアーティストはEd Sheeran、上位5位も全部洋楽)だったので、それとはうってかわって2020年は邦楽を多く聴く年になりました。
2020年に一番聴いた&ハマったアーティストはeillでした。 tell me tell me で、この良い声のアーティストは誰だろう、、ってところから始まり、SPOTLIGHTを聴いてすぐに大好きになりました。曲が良いのはもちろん、声がとーーっても良いです。
eill | SPOTLIGHT (Official Music Video)
SPOTLIGHT以外でも、この夜が明けるまで、20、MAKUAKE、最近だとFAKE LOVE/ や 片っぽ とか、たくさん良い曲があります。
もっといろんな人に聴いて欲しいアーティストです。ちょっとしたきっかけがあれば、すぐに有名になるんじゃないかなーって思っています。
Spotifyのプレイリストで良く聴くのはグローバルTop50や日本Top50、Top Hits Japan、Tokyo Super Hits!、Teen Cultureといったところですが、そこからYOASOBI、ずとまよ、Rin音やヨルシカを知って、どんどん聴くようになりました。
どのアーティストも特徴があって、好きな曲がたくさんあります。家族も好きで、小学2年生の娘も良く歌ってます。
Spotifyのおかげでいろいろ新しい音楽を見つけることができているので、ほんとSpotifyすばらしいです。家族みんな音楽が好きなので、Premium Familyに入っています。5人家族で1480円って価格も安すぎるな、、って感じです。
もっと聞きたかったアーティストです。Spotify上だと楽曲が少ないのですが、、YouTubeやSoundCloudでも聴いています。一番好きな曲は「洋装の語る今日は」で、リズミカルに流れる曲の上でさらに流れるような声という、声も楽器のようなすばらしい曲です。
曲と声のどちらもすばらしいアーティストなので、2021年はもっと楽曲出してくれることをすごーーく期待しています。
ストリーミングでのライブはいくつか視聴しましたが、やはり周りのみんなで歌ってアーティストと一緒に盛り上がるライブが最高なので、コロナが収束して、そういったライブにまた参戦できればな、、って思っています。
JavaのDBマイグレーションライブラリとしてFlywayを愛用していますが、マイグレーションが全て完了した後に、特定のSQLを流せないかなと調べてみたところ、Callbackという仕組みがあることがわかりました。
マイグレーションが全て成功した後だったり、1マイグレーション毎だったりと、いろいろなコールバックというかフック的なものが用意されています。
マイグレーションが全て完了した後だと、afterMigrate
が使えるようです。afterMigrate.sql
を配置し、そこにマイグレーションが全て完了した後に流したいSQLを書けばOKです。
今回これを使いたいと思ったのは、PostgreSQLで参照しかできないユーザを用意したいと思ったところからでした。
PostgreSQLだと、下記のようなSQLでスキーマ内の全部のテーブルに対して権限を与えられます。(以下はpublicスキーマの全てのテーブルに対して、user2にSELECT権限を与えています)
GRANT SELECT ON ALL TABLES IN SCHEMA public To user2;
このSQLは、SQLを実行した時点で存在するテーブルに対してのみしか権限が付与されません。その後に追加されたテーブルがあった場合には、そのテーブルに対しても適宜権限を付与する必要がでてきます。
テーブル追加されるごとに行うのはかなり煩雑なので、afterMigrate.sql
にこのSQLを書いておけば、毎回全てのテーブルに対して権限を与えることができてとても便利そうです。
試したプロジェクトのリンクも張っておきます。
この記事はRedmine Advent Calendar 2020 17日目の記事です。
チケットの担当者が変わったときに、SlackやRocket.Chatなどに通知するプラグインを作りました。
チケットの担当者が変わった時に、下記のようなメッセージを投稿してくれるようになります。
また、オプションでメンションを送ることもできます。(メンション先のIDは、ユーザのカスタムフィールドを利用します)
詳しい利用方法は、下記をご参照ください!
Redmine3.0.2と、最新の4.1.1で動作することを確認しています。
また、通知先としてSlackとRocket.Chatで確認していますが、Incoming webhookでtext
しか使っていないので、Incoming webhookに対応している他のチャットツールでも動くと思います。(メンション周りはツールによって異なるので、動かないところあったら教えてください!)
View customize plugin の v2.8.0 をリリースしました。
Insertion position として Bottom of all pages が選べるようになりました。
HTML bodyの末尾に埋め込まれるような形になります。これを利用すると、Redmine自体でJavaScriptが埋め込まれているような箇所(例えばガントチャート)で、それより後に実行するといったことが簡単にできます。
iquiw (Iku Iwasa)さんに要望+プルリクエストをいただき実現しました。ありがとうございます。
挿入位置を表す名称を悩んだ(特に日本語)のですが、いったんこの名前にしています。HTML上の要素で表した方が良いのかな、、とも思いましたが、いったんこのままで。
ブラウザでのテストだけではなく、ちょっとしたブラウザ操作の自動化にもSeleniumを利用するのですが、久しぶりに起動すると、各ブラウザのDriverが古くでエラーになる、、みたいなことが多々発生していました。
今更ながら、他の方々はどうやってこの問題を解決しているのだろうと調べてみたら、WebDriverManagerというとても便利なものがあることを知りました。
WebDriverManagerは、下記のようなコードを書くだけで、、
WebDriverManager.chromedriver().setup();
webdriver.chrome.driver
とか)を設定。といったことをやってくれます。これを使えば、自分でいちいち最新のDriverをダウンロードしてくるといったことをする必要はありません。
個人のプロダクトでSelenium使っているものは、全部WebDriverManagerに置き換えました。
サンプルとしてRedmineに対してのテストをGradleプロジェクトとして書いているので、気になる方はぜひ。
SeleniumでChromeDriverで実行した際に、ヘッドレスモードだとエラー、ヘッドレスモードにしないと成功するといったテストがありました。
エラー内容は下記のような感じで、要素が操作できないといったものでした。
org.openqa.selenium.ElementNotInteractableException: element not interactable (Session info: headless chrome=86.0.4240.183) Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03' System info: host: 'DESKTOP-U275NQ4', ip: '192.168.33.1', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_222' Driver info: org.openqa.selenium.chrome.ChromeDriver Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 86.0.4240.183, chrome: {chromedriverVersion: 86.0.4240.22 (398b0743353ff..., userDataDir: C:\Users\xxxxx\AppData\Lo...}, goog:chromeOptions: {debuggerAddress: localhost:57435}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:virtualAuthenticators: true} Session ID: 467a08d7a335a893b5ec767a330cc821 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187) at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122) at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49) at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158) at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552) at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285) at org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:84) at com.github.onozaty.selenium.RedmineTest.login(RedmineTest.java:114) at com.github.onozaty.selenium.RedmineTest.チケット作成(RedmineTest.java:41)
調べたところ、下記のような記事を見つけました。
ヘッドレスモードの場合、ウインドウのデフォルトサイズは 800 × 600 になり、ヘッドレスモードではないときよりサイズが小さくなるため、このような現象になるようです。
下記のような形で、ウインドウサイズを指定してあげることで回避できました。
ChromeOptions options = new ChromeOptions() .setHeadless(true) .addArguments("-window-size=1280,1024"); WebDriver driver = new ChromeDriver(options);