kakakakakku blog

Weekly Tech Blog: Keep on Learning!

2025年(7-9月)のプルリクエストを振り返る

2016年から毎年送ったプルリクエストを振り返る記事を書いている📅

2025年(7-9月)は「計30件」だった❗️

プルリクエストを振り返るための検索

プルリクエストを振り返るために GitHub の検索条件を使う.

今回は「2025年(7-9月)」に限定するため created:2025-07-01..2025-09-30 とする.

is:pr is:public author:kakakakakku -user:kakakakakku created:2025-07-01..2025-09-30

2025/07

aws-samples/serverless-patterns

支援してる会社で AWS サーバレスを学びたいという人に教えるっていう仕事もしていて,ペアプロをしながら体験してもらうテーマとして Serverless LandServerless Patterns Collection を使っている.その準備として試していたら AWS Lambda のランタイムが古くなっているサンプルが多いことに気付いて,2025年7月からコツコツ直すことにした.あとは AWS Community Builders (Serverless) に選出してもらってる背景もあって,サーバレス関連で貢献もしたいな〜という思いもあった💪

Terraform x AWS Lambda(Python ランタイム)のサンプルをいくつか直した.プルリクエストのレビューは比較的遅く,merge してもらえたプルリクエストとまだ見てもらえていないプルリクエストがある.

github.com github.com github.com github.com github.com github.com

microsoft/mcp-for-beginners

MCP (Model Context Protocol) のキャッチアップとして Model Context Protocol (MCP) Curriculum for Beginners を試していたときに気付いた README の誤りと手順の誤りを修正した.

github.com github.com

hashicorp/terraform-provider-aws

Terraform の aws_lb_listener を試していたときにドキュメントにサンプルコードがあったら助かるなぁ〜と感じた場面があってプルリクエストを送ったら merge してもらえた.Terraform AWS Provider にプルリクエストを送ったのは初で嬉しかった😀

github.com

2025/08

aws-samples/serverless-patterns

引き続き Serverless Patterns Collection のサンプルを直していた.Terraform x AWS Lambda(Python ランタイム)にプラスして Terraform x AWS Lambda(Node.js ランタイム)も修正した.

github.com github.com github.com github.com github.com github.com github.com github.com github.com github.com

aws-actions/aws-lambda-deploy

リリースされた直後に話題になっていた AWS Lambda Deploy GitHub Action を試しつつ,README に誤りがあったため修正した.

github.com

mingrammer/diagrams

社内勉強会で Amazon ECS Service Connect を紹介する機会があって,資料を作りながら Diagrams で Amazon ECS Service Connect のアイコンがサポートされていないことに気付いて追加した.

github.com

lambdadb/docs

LambdaDB の Quickstart を試しているときに Python コードに些細な誤りがあってハマったためドキュメントを修正した.

github.com

localstack/localstack-docs

LocalStack の AWS Cloud Control API サポートを調べているときにドキュメントに Markdown の構文誤りを発見して修正した.

github.com

2025/09

awslabs/s3vectors-embed-cli

Amazon S3 Vectors に入門する Tutorial: Getting started with S3 Vectors を試しているときにドキュメントに誤りがあるのを発見して修正した.

github.com

aws-samples/serverless-patterns

2025年9月も引き続き Serverless Patterns Collection のサンプルを直していた.Terraform x AWS Lambda にプラスして AWS SAM x AWS Lambda(Node.js ランタイム)も修正した.

github.com github.com github.com

localstack/pulumi-local

2025年9月からは Pulumi を使う機会が増えて,Pulumi と LocalStack の連携を試しているときに README の誤りを発見して修正した.

github.com

pulumi/examples

Pulumi のサンプルプロジェクトを試していたら Serverless Land の Serverless Patterns Collection と同じく AWS Lambda のランタイムが古くなっていることに気付いて修正した.

github.com

xhiroga/aws-peacock-management-console

AWS マネジメントコンソールの環境を判別しやすくするために AWS Peacock Management Console を愛用していて(支援してる会社でもたくさん紹介してる🦚),AWS User Experience Customization がリリースされてから微妙にスタイルが適用されず困っていたところを修正した.

github.com

過去の振り返り記事

既存の AWS リソースを Pulumi にインポートする: import コマンドと import リソースオプション

既存の AWS リソースを途中から Pulumi で管理する場合はインポートできる👌

Pulumi のインポート方法は大きく「import コマンド」「import リソースオプション」の2種類ある.詳しくはドキュメントに載っている.あくまでイメージだけど Terraform の import コマンドimport ブロックの関係に似てるとも言えそう.

www.pulumi.com

1. import コマンドを試す

まず AWS CLI で Amazon CloudWatch Logs ロググループ sandbox-pulumi-import-cli を作っておく.ログクラスは Infrequent Access・保持期間は 90日 にしておく.

$ aws logs create-log-group --log-group-name sandbox-pulumi-import-cli --log-group-class INFREQUENT_ACCESS
$ aws logs put-retention-policy --log-group-name sandbox-pulumi-import-cli --retention-in-days 90
$ aws logs describe-log-groups --log-group-name-prefix sandbox-pulumi-import-cli
{
    "logGroups": [
        {
            "logGroupName": "sandbox-pulumi-import-cli",
            "creationTime": 1758519450411,
            "retentionInDays": 90,
            "metricFilterCount": 0,
            "arn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:sandbox-pulumi-import-cli:*",
            "storedBytes": 0,
            "logGroupClass": "INFREQUENT_ACCESS",
            "logGroupArn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:sandbox-pulumi-import-cli"
        }
    ]
}

ここで pulumi import コマンドを実行する.pulumi import コマンドの指定方法はドキュメントに載っている📝

www.pulumi.com

するとプレビュー時に 1 to import・デプロイ時に 1 imported と表示された❗️そしてインポートしたリソースには protect 設定(誤って削除されないように保護できる)が付いているという注意コメントと Pulumi コードも出力される \( 'ω')/

$ pulumi import aws:cloudwatch/logGroup:LogGroup sandbox-pulumi-import-cli sandbox-pulumi-import-cli
Previewing import (dev)

     Type                        Name                       Plan       
     pulumi:pulumi:Stack         sandbox-pulumi-aws-dev                
 =   └─ aws:cloudwatch:LogGroup  sandbox-pulumi-import-cli  import     

Resources:
    = 1 to import
    2 unchanged

Do you want to perform this import? yes
Importing (dev)

     Type                        Name                       Status               
     pulumi:pulumi:Stack         sandbox-pulumi-aws-dev                          
 =   └─ aws:cloudwatch:LogGroup  sandbox-pulumi-import-cli  imported (0.26s)     

Resources:
    = 1 imported
    2 unchanged

Duration: 2s

Please copy the following code into your Pulumi application. Not doing so
will cause Pulumi to report that an update will happen on the next update command.

Please note that the imported resources are marked as protected. To destroy them
you will need to remove the `protect` option and run `pulumi update` *before*
the destroy will take effect.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const sandbox_pulumi_import_cli = new aws.cloudwatch.LogGroup("sandbox-pulumi-import-cli", {
    logGroupClass: "INFREQUENT_ACCESS",
    name: "sandbox-pulumi-import-cli",
    region: "ap-northeast-1",
    retentionInDays: 90,
}, {
    protect: true,
});

pulumi import コマンドを実行したタイミングでインポート対象リソース(今回で言うと Amazon CloudWatch Logs ロググループ)は Pulumi 側に登録されている👌ちなみに protect 設定を意味する鍵マークにカーソルを合わせると Resource is protected from accidental deletion と表示される🔒️

あとは出力された Pulumi コードを追加して pulumi preview コマンドを実行すれば差分なし❗️

$ pulumi preview
Previewing update (dev)

     Type                 Name                    Plan     
     pulumi:pulumi:Stack  sandbox-pulumi-aws-dev           

Resources:
    3 unchanged

最後にインポートした Amazon CloudWatch Logs ロググループ sandbox-pulumi-import-cli の設定変更を試す.保持期間を 180日 に変更する.

const sandbox_pulumi_import_cli = new aws.cloudwatch.LogGroup("sandbox-pulumi-import-cli", {
    logGroupClass: "INFREQUENT_ACCESS",
    name: "sandbox-pulumi-import-cli",
    region: "ap-northeast-1",
    retentionInDays: 180,
}, {
    protect: true,
});

pulumi up コマンド実行して期待通りに変更できていた👌

2. import リソースオプションを試す

同じく AWS CLI で Amazon CloudWatch Logs ロググループ sandbox-pulumi-import-option を作っておく.ログクラスは Infrequent Access・保持期間は 90日 にしておく.

$ aws logs create-log-group --log-group-name sandbox-pulumi-import-option --log-group-class INFREQUENT_ACCESS
$ aws logs put-retention-policy --log-group-name sandbox-pulumi-import-option --retention-in-days 90
$ aws logs describe-log-groups --log-group-name-prefix sandbox-pulumi-import-option
{
    "logGroups": [
        {
            "logGroupName": "sandbox-pulumi-import-option",
            "creationTime": 1758545230909,
            "retentionInDays": 90,
            "metricFilterCount": 0,
            "arn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:sandbox-pulumi-import-option:*",
            "storedBytes": 0,
            "logGroupClass": "INFREQUENT_ACCESS",
            "logGroupArn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:sandbox-pulumi-import-option"
        }
    ]
}

import リソースオプションを使う場合は Pulumi コードを自分で実装する必要がある.さらに以下のように import リソースオプションに対象リソースの識別子を指定する.Amazon CloudWatch Logs ロググループの場合は name を指定する.

new aws.cloudwatch.LogGroup("sandbox-pulumi-import-option", {
    logGroupClass: "INFREQUENT_ACCESS",
    name: "sandbox-pulumi-import-option",
    region: "ap-northeast-1",
    retentionInDays: 90,
}, {
    import: "sandbox-pulumi-import-option"
});

ここで pulumi up コマンドを実行する.するとプレビュー時に 1 to import・デプロイ時に 1 imported と表示された❗️

$ pulumi up
Previewing update (dev)

     Type                        Name                          Plan       
     pulumi:pulumi:Stack         sandbox-pulumi-aws-dev                   
 =   └─ aws:cloudwatch:LogGroup  sandbox-pulumi-import-option  import     

Resources:
    = 1 to import
    3 unchanged

Do you want to perform this update? yes
Updating (dev)

     Type                        Name                          Status               
     pulumi:pulumi:Stack         sandbox-pulumi-aws-dev                             
 =   └─ aws:cloudwatch:LogGroup  sandbox-pulumi-import-option  imported (0.26s)     

Resources:
    = 1 imported
    3 unchanged

Duration: 3s

そして Pulumi 側にも登録されていた👌

最後にインポートした Amazon CloudWatch Logs ロググループ sandbox-pulumi-import-option の設定変更を試す.保持期間を 180日 に変更する.

new aws.cloudwatch.LogGroup("sandbox-pulumi-import-option", {
    logGroupClass: "INFREQUENT_ACCESS",
    name: "sandbox-pulumi-import-option",
    region: "ap-northeast-1",
    retentionInDays: 180,
}, {
    import: "sandbox-pulumi-import-option"
});

pulumi up コマンド実行して期待通りに変更できていた👌

関連記事

今回はドキュメントを参考に自分で考えながらインポートを試したけど,インポートを体験できるチュートリアル「Importing AWS Infrastructure」もあるので興味があったらこちらもぜひ❗️

www.pulumi.com

Elemental MediaConvert と CloudFront に入門できる「File Streaming with AWS Media Services」

AWS Elemental MediaConvert を使って動画ファイルを変換するっていう流れをシュッと速習したいな❗️と思って「File Streaming with AWS Media Services」ワークショップを実施してみた.

catalog.us-east-1.prod.workshops.aws

Amazon S3 に動画ファイルをアップロードしたら AWS Lambda 経由で AWS Elemental MediaConvert ジョブを呼び出して,最終的に Apple HTTP Live Streaming (HLS) フォーマットに変換した動画を Amazon CloudFront から配信する流れを構築・体験できる👌基本的な流れを体験できて個人的にスゴイ良かった \( 'ω')/

File Streaming with AWS Media Services: Introduction から引用

File Streaming with AWS Media Services: Automation から引用

目次

ワークショップを実施する時間は1時間で十分だった👌今回はオプションタスクの Region Redundancy(マルチリージョン構成)は試さずに手順を読むだけにした.

  • Preparation
  • Introduction
  • Storage
  • Amazon CloudFront
  • Transcoding
  • Playback
  • Automation
  • Region Redundancy
  • Clean Up

Storage

Amazon S3 バケットを2つ作っておく.設定をするときは sourcedestination を間違えないようにする👌

  • vod-source-us-east1-kakakakakku
  • vod-destination-us-east1-kakakakakku

Amazon CloudFront から配信する destination バケット側に CORS 設定をしておくのはなるほど💡

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]

Amazon CloudFront

Amazon CloudFront のコンソールは微妙にアップデートされてて,ワークショップのキャプチャと異なる部分があった.とは言え大きな問題はなくデフォルト設定を中心にポチポチと進めて,あとは Price classUse North America, Europe, Asia, Middle East, and Africa にしたりもした.

Origin Access Control (OAC) は destination バケット側に自動的に設定されていた👌

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::vod-destination-us-east1-kakakakakku/*",
            "Condition": {
                "ArnLike": {
                    "AWS:SourceArn": "arn:aws:cloudfront::000000000000:distribution/XXXXXXXXXXXXXX"
                }
            }
        }
    ]
}

Transcoding

AWS Elemental MediaConvert で Apple HLS に変換するための設定をポチポチとしていく.そして出力グループとして3種類を設定してからジョブを実行した.1回目はワークショップ側でホスティングしている https://static.us-east-1.prod.workshops.aws/public/09743ab7-164b-4f79-a072-45f200ee05e0/assets/VANLIFE.m2ts を直接指定した.

  • H.264 (640 x 360), AAC, _360
  • H.264 (960 x 540), AAC, _540
  • H.264 (1280 x 720), AAC, _720

ジョブテンプレートを作るのはなるほど💡

docs.aws.amazon.com

Playback

ジョブの実行後に Amazon CloudFront 経由で動画を再生できた❗️Safari ならすぐに再生できて,Google Chrome の場合は拡張機能を追加したら再生できた.

そして,Amazon S3 バケット(destination 側)を確認すると以下のようなファイル構成で出力されていた.

$ aws s3 ls vod-destination-us-east1-kakakakakku/assets/VANLIFE/HLS/
2025-09-23 02:17:48        494 VANLIFE.m3u8
2025-09-23 02:17:48        737 VANLIFE_360.m3u8
2025-09-23 02:16:58     651232 VANLIFE_36020250923T021652_00001.ts
2025-09-23 02:17:03     658376 VANLIFE_36020250923T021657_00002.ts
2025-09-23 02:17:07    1069156 VANLIFE_36020250923T021702_00003.ts
2025-09-23 02:17:12     767040 VANLIFE_36020250923T021706_00004.ts
2025-09-23 02:17:16    1006176 VANLIFE_36020250923T021711_00005.ts
2025-09-23 02:17:21     632056 VANLIFE_36020250923T021715_00006.ts
2025-09-23 02:17:25     506848 VANLIFE_36020250923T021720_00007.ts
2025-09-23 02:17:30     780388 VANLIFE_36020250923T021724_00008.ts
2025-09-23 02:17:34     444244 VANLIFE_36020250923T021729_00009.ts
2025-09-23 02:17:39    1394208 VANLIFE_36020250923T021733_00010.ts
2025-09-23 02:17:43    1345140 VANLIFE_36020250923T021738_00011.ts
2025-09-23 02:17:48     690148 VANLIFE_36020250923T021743_00012.ts
2025-09-23 02:17:48      49256 VANLIFE_36020250923T021747_00013.ts
2025-09-23 02:17:48        737 VANLIFE_540.m3u8
2025-09-23 02:16:58    1179136 VANLIFE_54020250923T021652_00001.ts
2025-09-23 02:17:03    1381800 VANLIFE_54020250923T021657_00002.ts
2025-09-23 02:17:07    2288712 VANLIFE_54020250923T021702_00003.ts
2025-09-23 02:17:12    1568296 VANLIFE_54020250923T021706_00004.ts
2025-09-23 02:17:16    1788632 VANLIFE_54020250923T021711_00005.ts
2025-09-23 02:17:21    1096040 VANLIFE_54020250923T021715_00006.ts
2025-09-23 02:17:25     870252 VANLIFE_54020250923T021720_00007.ts
2025-09-23 02:17:30    1463392 VANLIFE_54020250923T021724_00008.ts
2025-09-23 02:17:34     674168 VANLIFE_54020250923T021729_00009.ts
2025-09-23 02:17:39    2607372 VANLIFE_54020250923T021733_00010.ts
2025-09-23 02:17:43    2487992 VANLIFE_54020250923T021738_00011.ts
2025-09-23 02:17:48    1189288 VANLIFE_54020250923T021742_00012.ts
2025-09-23 02:17:48      89864 VANLIFE_54020250923T021747_00013.ts
2025-09-23 02:17:48        737 VANLIFE_720.m3u8
2025-09-23 02:16:58    1947680 VANLIFE_72020250923T021652_00001.ts
2025-09-23 02:17:03    2082664 VANLIFE_72020250923T021657_00002.ts
2025-09-23 02:17:08    3311056 VANLIFE_72020250923T021702_00003.ts
2025-09-23 02:17:12    2223852 VANLIFE_72020250923T021707_00004.ts
2025-09-23 02:17:17    2632752 VANLIFE_72020250923T021711_00005.ts
2025-09-23 02:17:21    1573372 VANLIFE_72020250923T021716_00006.ts
2025-09-23 02:17:25    1162780 VANLIFE_72020250923T021720_00007.ts
2025-09-23 02:17:30    2159744 VANLIFE_72020250923T021724_00008.ts
2025-09-23 02:17:34     994520 VANLIFE_72020250923T021729_00009.ts
2025-09-23 02:17:39    3772972 VANLIFE_72020250923T021733_00010.ts
2025-09-23 02:17:43    3642312 VANLIFE_72020250923T021738_00011.ts
2025-09-23 02:17:48    1997876 VANLIFE_72020250923T021742_00012.ts
2025-09-23 02:17:48     149648 VANLIFE_72020250923T021747_00013.ts

Automation

最後は Amazon S3 バケット(source 側)に動画ファイルをアップロードしたら AWS Lambda 関数をトリガーするように統合していく❗️ちなみに IAM Role VODLambdaRole のポリシーを設定するときに Amazon CloudWatch Logs 関連のステートメントは AWSLambdaBasicExecutionRole と重複していて不要だと思う.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::000000000000:role/vod-MediaConvertRole"
            ],
            "Effect": "Allow",
            "Sid": "PassRole"
        },
        {
            "Action": [
                "mediaconvert:*"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow",
            "Sid": "MediaConvertService"
        }
    ]
}

AWS Lambda 関数自体に AWS Elemental MediaConvert のジョブテンプレート job_template.json を含めるのはなるほど〜💡という感じだった.

最終的に TestAsset.m2ts を Amazon S3 バケットにアップロードして,期待通りに動画を変換できた❗️Amazon S3 バケット(destination 側)を確認すると以下のようになっていた.697934d3-a14f-4cba-8f91-9ef20f1122b9/ というのは AWS Lambda 関数側で str(uuid.uuid4()) としてアセット ID を採番している.

$ aws s3 ls vod-destination-us-east1-kakakakakku/assets/697934d3-a14f-4cba-8f91-9ef20f1122b9/HLS/
2025-09-23 02:59:34        500 testasset.m3u8
2025-09-23 02:59:34        763 testasset_360.m3u8
2025-09-23 02:58:38     651232 testasset_36020250923T025832_00001.ts
2025-09-23 02:58:43     658376 testasset_36020250923T025837_00002.ts
2025-09-23 02:58:49    1069156 testasset_36020250923T025843_00003.ts
2025-09-23 02:58:54     767040 testasset_36020250923T025848_00004.ts
2025-09-23 02:58:59    1006176 testasset_36020250923T025853_00005.ts
2025-09-23 02:59:04     632056 testasset_36020250923T025858_00006.ts
2025-09-23 02:59:08     506848 testasset_36020250923T025903_00007.ts
2025-09-23 02:59:13     780388 testasset_36020250923T025907_00008.ts
2025-09-23 02:59:18     444244 testasset_36020250923T025912_00009.ts
2025-09-23 02:59:23    1394208 testasset_36020250923T025917_00010.ts
2025-09-23 02:59:28    1345140 testasset_36020250923T025922_00011.ts
2025-09-23 02:59:33     690148 testasset_36020250923T025927_00012.ts
2025-09-23 02:59:33      49256 testasset_36020250923T025932_00013.ts
2025-09-23 02:59:34        763 testasset_540.m3u8
2025-09-23 02:58:38    1179136 testasset_54020250923T025832_00001.ts
2025-09-23 02:58:43    1381800 testasset_54020250923T025837_00002.ts
2025-09-23 02:58:49    2288712 testasset_54020250923T025842_00003.ts
2025-09-23 02:58:54    1568296 testasset_54020250923T025848_00004.ts
2025-09-23 02:58:59    1788632 testasset_54020250923T025853_00005.ts
2025-09-23 02:59:04    1096040 testasset_54020250923T025858_00006.ts
2025-09-23 02:59:08     870252 testasset_54020250923T025903_00007.ts
2025-09-23 02:59:13    1463392 testasset_54020250923T025907_00008.ts
2025-09-23 02:59:18     674168 testasset_54020250923T025912_00009.ts
2025-09-23 02:59:23    2607372 testasset_54020250923T025917_00010.ts
2025-09-23 02:59:28    2487992 testasset_54020250923T025922_00011.ts
2025-09-23 02:59:33    1189288 testasset_54020250923T025927_00012.ts
2025-09-23 02:59:34      89864 testasset_54020250923T025933_00013.ts
2025-09-23 02:59:34        763 testasset_720.m3u8
2025-09-23 02:58:39    1947680 testasset_72020250923T025832_00001.ts
2025-09-23 02:58:44    2082664 testasset_72020250923T025838_00002.ts
2025-09-23 02:58:49    3311056 testasset_72020250923T025843_00003.ts
2025-09-23 02:58:54    2223852 testasset_72020250923T025848_00004.ts
2025-09-23 02:58:59    2632752 testasset_72020250923T025853_00005.ts
2025-09-23 02:59:04    1573372 testasset_72020250923T025858_00006.ts
2025-09-23 02:59:08    1162780 testasset_72020250923T025903_00007.ts
2025-09-23 02:59:13    2159744 testasset_72020250923T025908_00008.ts
2025-09-23 02:59:18     994520 testasset_72020250923T025913_00009.ts
2025-09-23 02:59:23    3772972 testasset_72020250923T025917_00010.ts
2025-09-23 02:59:28    3642312 testasset_72020250923T025922_00011.ts
2025-09-23 02:59:33    1997876 testasset_72020250923T025928_00012.ts
2025-09-23 02:59:34     149648 testasset_72020250923T025932_00013.ts

まとめ

「File Streaming with AWS Media Services」ワークショップは Elemental MediaConvert と CloudFront に入門できる良いコンテンツだった❗️

関連

docs.aws.amazon.com

aws.amazon.com

Pulumi で AWS リソースに一括でタグを設定する aws:defaultTags

Pulumi でデプロイする AWS リソースに一括でタグを設定する場合,Pulumi YAML(たとえば Pulumi.dev.yaml)で defaultTags を設定すれば OK👌

www.pulumi.com

👾 Pulumi.dev.yaml

Environment タグと Project タグを設定する.

config:
  aws:region: ap-northeast-1
  aws:defaultTags:
    tags:
      Environment: dev
      Project: Sandbox

👾 index.ts

検証として Amazon S3 バケットと Amazon CloudWatch Logs ロググループをデプロイする.

import * as aws from "@pulumi/aws";

new aws.s3.Bucket("sandbox");
new aws.cloudwatch.LogGroup("sandbox");

デプロイ確認

期待通りにタグが設定できている❗️

$ aws s3api get-bucket-tagging \
    --bucket sandbox-4740f3d
{
    "TagSet": [
        {
            "Key": "Project",
            "Value": "Sandbox"
        },
        {
            "Key": "Environment",
            "Value": "dev"
        }
    ]
}

$ aws logs list-tags-for-resource \
    --resource-arn arn:aws:logs:ap-northeast-1:000000000000:log-group:sandbox-588ff71
{
    "tags": {
        "Environment": "dev",
        "Project": "Sandbox"
    }
}

goo ブログからはてなブログに移行するためにやったこと

2025年11月18日で「goo ブログ」がサービス終了になるというアナウンスが出ている📝

blog.goo.ne.jp

母親が goo ブログを書いていて(正直知らなかった👀)移行を頼まれたため作業ログをまとめておこうと思う.

ちなみに移行するデータ量としては以下だった.日記のような内容だとしても凄すぎる継続力❗️

  • 9911記事
  • ブログ運営16年間
  • 画像33677枚(goo blog フォト有料プラン)

ブロガーは遺伝する説まである \( 'ω')/

ブログメディアを選ぶ

まずはブログメディアを選ぶ.goo ブログのサイトを見ると「Ameba ブログ」「はてなブログ」という選択肢が載っていて,その他移行可能サービス というリンクを辿ると「note」も出てくるような感じだった.最終的に「はてなブログ」を選んだ.母親が希望していたし,僕自身も使っていて慣れているのもあった.

ちなみに僕個人としては note をおすすめしたかったけど 1000記事以上は非推奨 と書いてあって選択肢にすら入らなかった😇

よって,以下の手順を参考に進めていくことにした.

blog.hatenablog.com

goo ブログから記事をエクスポートする

1記事の文字数が少なめということもあって,9911記事もあったけど比較的早く終わった.export_blog.zip をダウンロードしておいた.展開すると export_blog_1.txt というテキストファイルに以下のフォーマットで記事がエクスポートされていた😀

AUTHOR: xxx
TITLE: xxx
DATE: DD/MM/YYYY HH:MM:SS
PRIMARY CATEGORY: xxx
STATUS: publish
ALLOW COMMENTS: 1
CONVERT BREAKS: 0
CF50_GBENTRYHASH: xxx
-----
BODY:
xxx
-----

はてなブログに記事をインポートする

次ははてなブログに記事をインポートする.13時間ほど待って完了してなく,翌朝になったら終わっていた👌スピードから予測すると15時間ぐらいで終わったと思う.

この次に goo ブログの画像をはてなブログにインポートする必要があるけど,実は「この時点で」はてなブログとしては既に記事を閲覧できるようになっている.理由としては goo ブログの記事で画像は blogimg.goo.ne.jp ドメインの img タグになっていて,goo blog フォトを参照するようになっているため.

はてなブログに画像をインポートする

次にはてなブログに画像をインポートする.これは本当に長かった😇計算したところ1日3000枚程度というスピードになっていて,合計11日間待って終わった.ちなみに2枚は移行できなかったようだけどどうしてだろう!?

もちろん goo blog フォトにリクエストする流量を抑えているという背景があると思うし,さらに記事本文の blogimg.goo.ne.jp ドメインを cdn-ak.f.st-hatena.com ドメインに書き換える処理も必要になるから特に遅いとは感じなかった👌

リダイレクト

さらに goo ブログからはてなブログにリダイレクトを設定することができた🔗もともとの goo ブログにブックマーク経由で流入してくるような場合をフォローアップできて良かった👌ちなみに HTTP ヘッダーを確認したらちゃんとリダイレクトされていた.

$ curl -s -I https://blog.goo.ne.jp/XXXXX | grep -i Location
Location: https://XXXXX.hatenablog.com

blogsync でバックアップ

もしかしたら最初ははてなブログの操作に慣れてなく,間違えて記事を消してしまった😨という事故も想定して,blogsync を使って定期的に記事をバックアップする仕組みも作った.kakakakakku blog でも同じ仕組みを使っててシュッと実現できた.

github.com

まとめ

移行完了❗️

Happy Blogging \( 'ω')/