glasp v0.4.0 リリース:タイムアウト/自動リトライ対応

glasp v0.4.0 をリリースしました。

glasp v0.4.0

github.com

主な変更点

タイムアウト設定

API へのリクエストにタイムアウトを設定できるようになりました。デフォルトは 180 秒です。

# フラグで指定
glasp push --timeout 60

# 環境変数で指定
GLASP_TIMEOUT=60 glasp push

# タイムアウトなし
glasp push --no-timeout

.glasp/config.json に書いて指定することもできます。

{
  "httpTimeout": 60
}

自動リトライ

ネットワークエラーや 429・5xx などの一時的な失敗に対して、自動でリトライするようになりました。 デフォルトは最大 3 回です。リトライはコマンド(push / pull / clone / list-deployments)にのみ適用されます。

# リトライ回数を5回に変更
glasp push --max-retries 5

# リトライを無効化
glasp push --no-retries

内部リファクタリング

cmd/glasp および internal パッケージの構造を整理しました。


不具合やご要望

不具合や要望等がありましたら、SNSまたはIssues等でご連絡ください

Issues · takihito/glasp · GitHub

glasp v0.3.0 リリースしました

glasp v0.3.0

github.com

今回のリリースでは以下の改善を行いました。

  • PKCE対応によるOAuth認証の強化
  • GitHub Actions におけるセキュリティ向上
    • Harden-Runnerの audit から block への移行
    • clone / pull / push の継続的な実行テスト追加

glaspの概要についてはこちらの記事をご覧ください。

zenn.dev


PKCE 対応

v0.3.0 では OAuth 認証フローのPKCE に対応しています。ログイン時に--pkceオプションを渡すことでよりセキュアな認証が行えるようになっています。

glasp login --pkce

GitHub Actions のセキュリティ強化

CI/CD 側では GitHub Actions ワークフローを見直しました。

今までは Harden-Runnerに audit を使用していましたが、block に移行しました。 auditは通信を検知してレポートしますが、blockはホワイトリストから違反を検出しワークフローを失敗させることができます。

実行テスト追加

コマンドオプション:clone, pull, push の実行テストをmainブランチへのpush時に行なうようにしています。

ご利用されている方へ

不具合・改善点などありましたらご連絡いただけると助かります。よろしくお願いいたします。

Issues · takihito/glasp · GitHub

10年ぶりCPANリリース&爆破解体の裏話

このエントリーはPerl Advent Calendar 2025の 12日目のエントリーになります。

10年ぶりCPANリリース

今年10年ぶりに新作モジュール Text-Textile2MarkdownStandaloneCPAN に投稿した。

前回の投稿である Web-API-Mock-0.01 が 2015 年なので、実にほぼ 10 年ぶり。この機会に Web-API-Mock も 0.01 から 0.11 にバージョンアップ しておいた。

爆破解体裏話

先日、2025-12-02 爆破解体予定だったレガシーサーバーの転生 について書いた。当初は Redmine を完全に爆破解体し、必要なときだけ DB ダンプからリストアして閲覧する方針だった。

しかし、さすがにそれは手間が大きい。運用上よく参照する Wiki だけでも GitHub Wiki に移して、いつでも見られるようにしておきたいと考えた。

RedmineのTextile形式

RedmineWiki 形式は Textile だったので、Markdown に変換する必要がある。そこで作ったのが Text-Textile2MarkdownStandalone 。コードの 9 割は AI に書いてもらった。

実装手順は次のとおり。

  • RedmineWiki(Textile 形式)を数ページ抽出しファイルに保存
  • 自動(完璧ではない)+人間で抽出ファイルを Textile → Markdown に変換
  • その変換例をもとに、AI に「Textile を Markdown に変換する Perl 関数」を生成してもらう
    • 一度で完成しないので、問題箇所を指摘しながら何度も修正依頼
  • 変換の隘路に入り込んだときだけ人間が直接コードを修正

機械的に辿り着けるところまでは AI に任せ、ラストワンマイルのみ人間が走る方式だ。とはいえ、もう少しすれば AI 単独で完走できる気もする。あと、AIに複数言語で書き比べさせたんだけど、テキスト処理の領域では Perl の力が頼りになる。

Pandoc や世に公開されている変換スクリプトも検討したが、Redmine 版 Textile には拡張記法があって期待どおりの変換にならない部分がある。結局Text-Textile2MarkdownStandaloneを作って変換した。

Redmineの運用

またRedmine 爆破解体の話に戻る。このモジュールで主要ページは Markdown 化して移行できたが、それでもチケット調査をしたくなる場面はあるし、メールや Slack にURLは残っている。そのたびに DB を復元するのは面倒なので、URL のパスを変更して Redmine 自体を転生させた。社内では「もう使わない」という意見が多かったものの、実際には調査で間接的に参照されるケースも多く、結果的に正解だった。

ただし起動に時間がかかるため、閲覧頻度の高いページだけは GitHub Wiki に移設し、ストレスなく参照できるようにしている。

CPANのアカウントがロックされていた

User 'AKIHITO' set to nologin. Many users with an insecure password have got their password reset recently because of an incident on perlmonks.org.

さらに、久しぶりに CPAN にログインしようとしたらアカウントがロックされており、慌てて解除を依頼することに。約1か月後、「ロック解除したよ」という温かみのあるメールが届き、無事にアップロードできた。こうした運用を長く続けるのは本当に大変だと思う。

Hi Takeda-san, I've just unlocked your PAUSE account, so you should be able to log in now.

「i’m happy thank yoooou」

そういえば、このブログを書くのも 7 年ぶりで、前回のエントリーPerl Advent Calendar だった。


まったく全然関係ないけど平良達郎が強すぎる。このままUFCベルトを獲れるなれるのでないか、戦い方も詰め将棋のようで好みのスタイル。5月に日本でUFC開催する噂があるし応援したい。

それでは、みなさま良いお年を🎄

チームで中規模Perlアプリケーションを開発する工夫

Perl Advent Calendar 2018 13 日目の記事です。

チームで開発を行うとき、機能単位で担当者を割り振り、実装することが多いかと思います。

しかし、実際には一人で実装するにはボリュームが大きく、機能も分割しにくいケースがよくあります。

このような時には、ビジネスロジックをプラガブルに設計しておくことで、開発のスケールアウトをしやすくなります。

プラグインの実装

複数の処理を繋ぎ合わせ、次処理に回すような流れを想定した場合、菱形多重継承のような実装モデルが想像されます。

各クラスで実装した処理をメソッド順序解決を行いながら順次実行されるわけです。

f:id:t-akihito:20181212161145p:plain
多重継承 Class A → B → C → Dの順に init が実行される

このようなプラガブルな構造を実装する方法としては、古くはClass::C3のようなモジュールがありました。

しかし、次処理にまわしたい要件を実現することに、多重継承を用いて解決することには牛刀感があります。

合成の利用

MooseにはRoleという仕組みがあり、これを使うことでモジュールへの合成を行うことができます。

呼び出し元にプラグインを追加して行くことにより機能を追加していくことになります。

処理をクラス毎に分割し実装担当者が メソッドの in -out のチェックを行うようにすれば、個々人が並列に実装作業を行うことができるようになります。

package Yyy;
use Mouse::Role;

before 'init' => sub {
    my $self = shift;
    push @{$self->list}, 'y';
};

1;

package Zzz;
use Mouse::Role;

before 'init' => sub {
    my $self = shift;
    push @{$self->list}, 'z';
};
1;

package Main;
use Mouse;
with ' 'Yyy', 'Zzz';

has list => (
    is      => 'rw',
    isa     => 'ArrayRef',
    default => sub { []; }
);

sub init {
    my $self = shift;
    my $string = join ('-', @{$self->list});
    return $string;
}
1;
use Main;
my $m = Main->new();
print $m->init(); # 呼び出し順をたどって z-y が出力される

with に追記した逆順に各クラスの before 'init' が実行処理されるようになっています。上記のコードの場合は Yyy, Zzzのそれぞれのクラスを担当者で実装してもらうわけです。

道具の進歩(github)により開発が衝突する機会が少なくなってきてはいますが、それでも時には人的リソースのスケールアウトが可能なように設計をしておくことも一つの案だと思っています。

現場では依然として活発に稼働しているPerlプロダクトが多数あります。枯れた技術を工夫しながら日々改善するのが長期運用のコツではないかと感じています。

builderscon 2018 に参加(登壇)してきました

数年放置していた本ブログですが、私は元気です。

builderscon 2018に参加してきました。

オープニングには間に合いませんでしたが、色々なセッションに刺激をもらいました

開発現場で役立たせるための設計原則とパターン

実況中継シリーズ 「開発現場で役立たせるための設計原則とパターン」 #builderscon 2018 - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴く

設計に関しては、抽象論の空中戦になることが多い実感。「個人の感想です」が顔を出しがちになるホントこれ。設計原則に当てはめて考察するってのは筋がいい。設計コストの問題もあるにせよ、これは自身やチームのレビューに有効そうだなと実感。

Webサービスにて200週連続で新機能をリリースする舞台裏

Webサービスにて200週連続で新機能をリリースする舞台裏 / builderscon tokyo 2018 - Speaker Deck

毎週リリースとなると週刊連載を持つようなものだよなぁと思ってたけど、実際にネタのストックをためておいたりとか1話完結の漫画家ぽい

それでも毎週リリース出せるのはチームの自力があってのことだろうし、ここ数年のMackreleの開発状況を見ると尊敬せざるをえない。スタートアップ期が終わったっていうのは良い判断だし素晴らしいスピード感だったと思う (Mackerelガンガン使っております

機械学習を用いず数学でゲーム内の需要予測をする

機械学習を用いず数学でゲーム内の需要予測をする - Speaker Deck

会社の同僚のセッション。機械学習で使えるような形式やデータ量でもない場合には数式(+人間)で予測することができる。ソーシャルゲームで需要予測を行ったの実例を紹介。山場はホワイトボードで数式を書き始めたあたり、かっこいい!

Webサービスの品質とは何か?アラート地獄と監視の失敗、サービスレベル目標設計から学んだ3つの答え

Webサービスの品質とは何か?アラート地獄と監視の失敗、サービスレベル目標設計 から学んだ3つの答え - Speaker Deck

大変身につまされる思いがしました...ごめんなさい。忙しさにかまけて、ついつい放置しがちになってしまい云々....アラートがアクションにつながらないってのは本当

証券トレーディング業務におけるExcel依存を脱却するプロジェクトで直面した技術的選択とプロジェクト運営の失敗

録画撮影禁止だけのことはある、業界自体が怖いよ。ヒットマンが飛んできそうだ。 社内システムの顛末なんだけど、当初の要件としてはシステム規模が大きくならないはずなのにね。 あまり関わることのない世界だと思いたい。

ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ

ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ / The construction of large scale TLS certificates management system with AWS - Speaker Deck

そーだいなるピタゴラスイッチだ。色々悲鳴が聞こえて来てはいた(?)けどよくぞ作ったものだと尊敬する。実にはてなっぽい。

要素技術的にはDynamoDBのTTLをトリガーにするのが良さそう。ドミノを倒すトリガーについて考えていたので参考になりそう。

RDB THE Right Way ~壮大なるRDBリファクタリング物語

RDB THE Right Way - builderscon 2018/ RDB_THE_Right_Way - Speaker Deck

「データベースの寿命はアプリケーションより長い」が重い。世の10年超えのサービスはすごいよなぁ。 データと情報、技術的根拠。そして本読む時間作ろう。

ちなみに自分は以下のセッションで登壇をしてきました。

SNSでの反応を見る限りでは結構楽しめたようなので安心しました。 ここ数年ほとんど表に出ていなかったので色々緊張しました....

ソーシャルゲームが高負荷に陥っているとき、何が起こっているのか

speakerdeck.com

運営スタッフ・スポンサー・関係者の皆様、楽しいイベントありがとうございました

来年も機会があれば参加したいと思います!

APIドキュメントからモックサーバを立ち上げるWeb::API::Mockを書いた

APIドキュメント(API Blueprint)からモックサーバを立ち上げるWeb::API::Mockを書きました

Plackで作った事もあり以前紹介したapi-mockよりも、ちょっと便利になっています

APIドキュメントからモックサーバを立ち上げたい - akihitoのログ置き場

  1. モックサーバ立ち上げ時にplackupのオプションが使える
  2. 複数個のAPIドキュメントに対応
  3. 未実装のAPIリストを渡す事でステータス:501を返す

モックサーバからアプリケーションサーバへURL毎にスイッチする

3番目の仕組みを利用することで、nginxを使ってモックサーバからサーバアプリケーションに差し替える事が出来ます

upstream mock_backend {
   server 127.0.0.1:5001;
}

upstream prod_backend {
   server 127.0.0.1:5002;
}

server {

    location ~ ^/ {
         proxy_intercept_errors on;
         proxy_pass http://mock_backend;
         proxy_set_header Host $host;
    }

    error_page 501 =200 @prod;
    location @prod {
        proxy_pass http://prod_backend;
        proxy_set_header Host $host;
    }

モックサーバ(mock_backend)にnot-implemented-urlsオプションで渡したURLが501で返ってくるので、 nginx側でキャッチして、実装したサーバアプリケーションにURL毎にまわせるようになります

APIドキュメントからモックサーバを立ち上げたい

APIドキュメント(API Blueprint)を記述するとモックサーバを立ち上げてくれるサービスがあります。 GitHubAPIドキュメントを管理したり、モックサーバのアクセスログが見えたりの中々の優れ物です。

提供されるモックサーバがRESTful APIで少々融通が効かないこと、外部のWebサービスなので場合によっては採用しづらいのが難点。

ただ、API BlueprintのテストツールやモックサーバはOSSで提供されているので、サービスを使わずに利用することも可能のようです

api-mockで手軽にモックサーバを立ち上げる

公開されているモックサーバがJavaだったりして、ちょっと入れづらいなぁと思っていたら、api-mockなるモジュールがあるようですね。これもAPI Blueprintからモックサーバをたち上げてくれるようです

API Blueprint形式のAPIドキュメントを用意する

API Blueprintは、Markdownを拡張した形式です。

API Blueprint詳細

こんな感じでMethod,URI,Request,Response等を記述していきます

FORMAT: 1A
HOST: http://example

# Nopaste

タイトルと本文を投稿します

## POST /api/nopaste

+ Request

    + Header

        Host: example

    + Parameters
        + title (required, string) ... タイトル
        + body (required, string) ... 本文

+ Response 201 (text/html)

    + Header

            X-Framework: Ark

    + Body

            {
                "result": {
                    "ok": 1
                }
            }

他にも幾つかAPIを記述しておきます sample.md

API Blueprintはちょっと癖があったり未整備な所もあるのですが、現時点での要求としては十分かなと思っています。

api-mockを入れる

nodeで書かれているのでnpmを使ってインストールします

npm install -g api-mock

実行

では早速実行してみましょう

$ api-mock sample.md --port 3001
Listening on port 3001

コマンドラインから叩いて確認してみます

$ curl http://localhost:3001/api/nopaste/1234
{
    "result": {
        "title": "Hello Nopaste",
        "body": "Text"
    }
}
$ curl -I http://localhost:3001/api/nopaste/1234
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json
X-Framework: Ark
Content-Length: 83
Date: Fri, 11 Apr 2014 04:05:05 GMT
Connection: keep-alive

Headerに記述した"X-Framework: Ark"もちゃんと返ってきてますね

ドキュメントに記述した固定正常系のResponseしか返してくれませんが、それでもクライアントが サーバサイドの実装を待たずに疎通確認が出来るのはうれしいんじゃないかなと思っています

(このサンプルをApiary — Homeに持っていくとエラーになるんですが、統一感があるのでこちらの方がいいかなぁと…思っています)