HTMLメールの注意点(Gmail)
システムで Gmail へ HTML メールを送る際の注意点になります。
Yahooなど他のサービスでの動作については確認していません。
例えばですが、PCではフォントサイズ 16px
SP ではフォントサイズ 20px
みたいな要件のとき
.font { font-size: 16px; } @media only screen and (max-width:480px) { .font { font-size: 20px !important; } }
の様に書けば要件を満たせます。
ここで注意しなければいけない部分が2点あります。
1 media query の max-width:
の後ろにスペースを入れてはいけない
@media only screen and (max-width: 480px) {
とするだけで、SP 時にフォントサイズが変わらないということが起きます。
2 !important
を書かないと上書きされない
font-size: 20px !important;
css は後から書いたスタイルが優先されるはずなのですが、Gmail へ送る HTML メールでは !important
を書かなければ上書きされないようでした。
参考
html - Why is Gmail ignoring my media queries? (On iOS) - Stack Overflow
AWS CloudFormation で ECR のライフサイクルを設定する
AWS ECR を使ってコンテナを更新していくと知らないうちにイメージが貯まっていきます。
Lifecycle Policy を設定すれば、古いイメージを自動で削除できます。
CloudFormation で設定する方法を見ると、 LifecyclePolicyText
に String
で設定すれば、 ECR の Lifecycle Policy を設定できます。
ですが、 Amazon ECR ライフサイクルポリシー を見ると分かるのですが、 JSON で設定するようになっています。
Lifecycle Policy の条件とその JSON は以下の様になります。
- ルールの優先順位 : 1
- イメージのステータス : タグ付けなし
- 一致条件 : 次の数値を超えるイメージ数 10
{ "rules": [ { "action": { "type": "expire" }, "selection": { "countType": "imageCountMoreThan", "countNumber": 10, "tagStatus": "untagged" }, "description": "delete cycle", "rulePriority": 1 } ] }
YAML では >
を使うと改行をスペースに置き換えられるのでそのまま JSON を書くことで String
として扱うことができます。
LifecyclePolicyText: > { "rules": [ { "action": { "type": "expire" }, "selection": { "countType": "imageCountMoreThan", "countNumber": 10, "tagStatus": "untagged" }, "description": "delete cycle", "rulePriority": 1 } ] }
試してみた CloudFormation のリソースを残しておきます。
Parameters: RepositoryName: Type: String ImageName: Type: String Resources: Repository: Type: AWS::ECR::Repository Properties: RepositoryName: !Ref RepositoryName RepositoryPolicyText: Version: "2012-10-17" Statement: - Sid: AllowPushPull Effect: Allow Principal: AWS: - !Sub arn:aws:iam::${AWS::AccountId}:user/${ImageName} Action: - "ecr:*" LifecyclePolicy: LifecyclePolicyText: > { "rules": [ { "action": { "type": "expire" }, "selection": { "countType": "imageCountMoreThan", "countNumber": 10, "tagStatus": "untagged" }, "description": "delete cycle", "rulePriority": 1 } ] } RegistryId: !Ref AWS::AccountId
参考
AWS Lambda のトリガーで CloudWatch の定数(JSONテキスト)を使った場合の起動方法
AWS Lambda が .Net Core をサポートしたと言うけど実際に書くときに引数ってどうするんだろうって思ったので調べてみた。
Lambda のトリガーには CloudWatch を指定できて、 CloudWatch のイベントからルールを設定することでバッチ処理のようなことをさせることができます。
CloudWatch のイベントルール
ここで気になったのが、入力を 定数 (JSON テキスト)
にした場合、ソースコードで引数部分をどう書けばいいのかということでした。
イベントごとの書き方の違い
一致したイベント
一致したイベントの場合は CloudWatchLogsEvent
で大丈夫です。
public string FunctionHandler(CloudWatchLogsEvent logEvent) { }
定数 (JSON テキスト)
定数 (JSON テキスト) の場合、 JSON テキストは
{ "mode": "test" }
としたとき、 一致したイベント
と同じ書き方ではエラーになります。
Object reference not set to an instance of an object.: NullReferenceException
その場合は自分で型を定義してあげることで無事Lambdaを起動することができます。
public class InputParameter { public string mode { get; set; } } public string FunctionHandler(InputParameter params) { Console.WriteLine("mode : {0}", params.mode); }
参考
CircleCI 2.0 で AWS CodeDeploy を使う
まず、 CircleCI 1.0 で CodeDeploy を使っているという前提で話を進めます。
そのため、デプロイ先のインスタンスへの CodeDeploy エージェントインストールなどについては触れません。
先に示すこれは失敗する例です。
成功する例はこの記事の一番最後に書いてあります。
.circleci/config.yml
version: 2 jobs: deploy: working_directory: ~/repo docker: - image: naughtldy/circleci-node-awscli:8 steps: - checkout - run: name: zip command: "zip -r master ../repo" - run: name: zip upload command: aws s3 cp master.zip s3://{バケット名}/{ファイル名} --region ap-northeast-1 - run: name: Deploy Staging command: | aws deploy create-deployment \ --application-name bot-ryuzu \ --deployment-group-name ryuzu-prod \ --s3-location bucket="{バケット名}",bundleType="zip",eTag=`aws s3api head-object --bucket {バケット名} --key {ファイル名} | jq .ETag`,key="{ファイル名}" \ --region ap-northeast-1 workflows: version: 2 deploy: jobs: - deploy: filters: branches: only: master
実行結果は、 appspec.yml が無いという理由でデプロイに失敗します。
CircleCI 1.0 で動いていたので、ファイルが不足するなどの理由はないはずなので CircleCI 1.0 のときと比較してみます。
デプロイしたソースコードは、 CodeDeploy によるデプロイ先インスタンスの
/opt/codedeploy-agent/deployment-root/{英数字の羅列}/
ここにデプロイIDごとにディレクトリが分かれて入っています。
以前の成功していた時のものを見てみると、デプロイIDのディレクトリの中身は
bundle.tar deployment-archive logs
となっています。
CodeDeploy でデプロイするソースコードなどは deployment-archive
の中に入ってます。
失敗する場合は
bundle.tar deployment-archive repo
となります。
repo
はCircleCIでのソースコード展開先のディレクトリ名です。
そうすると、 CodeDeploy のイベント BeforeInstall
で、ディレクトリ deployment-archive
の中に appspec.yml が無いというエラーで CodeDeploy の実行に失敗します。
確認してみると deployment-archive
の中身が空で、ソースコードなどは repo
に入っています。
こちらが成功する例です。
.circleci/config.yml
version: 2 jobs: deploy: working_directory: ~/deployment-archive docker: - image: naughtldy/circleci-node-awscli:8 steps: - checkout - run: name: zip command: "zip -r master ../deployment-archive" - run: name: zip upload command: aws s3 cp master.zip s3://{バケット名}/{ファイル名} --region ap-northeast-1 - run: name: Deploy Staging command: | aws deploy create-deployment \ --application-name bot-ryuzu \ --deployment-group-name ryuzu-prod \ --s3-location bucket="{バケット名}",bundleType="zip",eTag=`aws s3api head-object --bucket {バケット名} --key {ファイル名} | jq .ETag`,key="{ファイル名}" \ --region ap-northeast-1 workflows: version: 2 deploy: jobs: - deploy: filters: branches: only: master
working_directory: ~/deployment-archive
で、 CircleCI のソースコード展開先ディレクトリ名を deployment-archive
にしたことで、 デプロイ先インスタンスの deployment-archive
にソースコードが入り今まで通りにデプロイできるようになりました。
GitHubで二段階認証を有効にしたときに聞かれるパスワード認証の回避方法
GitHubで二段階認証をすると、 http 通信ではなく、 ssh 通信を使う必要があります。
ssh 通信を使用すると、 CLIなどで pull
や push
などの操作をしたときに秘密鍵のパスワードを聞かれます。
Enter passphrase for key '/path/to/id_rsa':
このパスフレーズを回避する方法のメモです。
いくつか方法があるようです。
全部実施する必要はなくて、どれか一つをすれば大丈夫です。
ssh-add -K {秘密鍵}
CLIで↓のコマンドを入力してPCを再起動するまでの間、秘密鍵のパスワード入力を省略する。
ssh-add -K {秘密鍵}
.netrc を作成する
ユーザーのルートディレクトリに .netrc
ファイルを作成する。
.netrc
には以下の内容を記述する。
machine github.com login {username} password {password}
リポジトリのクローン時にトークンを追加する
GitHubの Settings から Personal access tokens でトークンを生成してリポジトリのURLにtokenを追加する。
https://github.com/settings/tokens
https://{username}:{token}@github.com/{username}/{repository}.git
秘密鍵からパスフレーズを消す
VSCodeのExtensionを端末間で共有する方法
VSCodeでインストールしたExtensionを端末間で共有したり、PCを新しく買ったときにどうやって同じ設定にしようか悩んでました。
どうやら Settings Sync を使うことで簡単に Gist で管理できるみたいです。
AWS CloudFormationで名前に - が使えなくて困ったこと
AWSの環境ではWAF など、名前に -
が使えない物があります。
CloudFormationからWAFの設定をしようとした時に少し困ったのでメモを残しておきます。
何に困ったのか?
CloudFormationのテンプレートで、Parametersから入ってくる変数の値に -
が入っていると Name
を設定するときにエラーになってしまう。
最初に作成したテンプレートは↓です。
AWSTemplateFormatVersion: '2010-09-09' Description: WAF CI/CD Pipeline Parameters: ProductName: Type: String Stage: Type: String Default: prod Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Product Configuration Parameters: - ProductName - Stage ParameterLabels: ProductName: default: ProductName Stage: default: Stage Resources: WAF: Type: AWS::WAF::WebACL Properties: Name: !Sub ${ProductName}${Stage} MetricName: !Sub ${ProductName}${Stage} DefaultAction: Type: BLOCK Rules: - Action: Type: ALLOW Priority: 1 RuleId: !Ref WAFRule WAFRule: Type: AWS::WAF::Rule Properties: Name: !Sub ${ProductName}MyIp${Stage} MetricName: !Sub ${ProductName}MyIp${Stage} Predicates: - DataId: !Ref WAFIPSet Negated: false Type: IPMatch WAFIPSet: Type: AWS::WAF::IPSet Properties: Name: !Sub ${ProductName}-my-ipset-${Stage} IPSetDescriptors: - Type: IPV4 Value: {IPアドレス}/32
モックアプリを作っていたので、 ProductName には hoge-mock
という感じで -
付きにしていました。
AWS::WAF::WebACL
AWS::WAF::Rule
の Name
には -
が使えないので、ココでエラーが出てしまいます。
※ Stage
は、環境を表していて、 prod
stg
dev
などの文字が入ってきます。
-
を消す方法(テンプレートの変換の流れ)
どうにか -
を消せないかとイロイロ試したところ↓の方法で -
を消すことができました。
Name: !Join - '' - - !Join - '' - !Split - '-' - !Ref ProductName - !Ref Stage
!Ref
のところを展開します。
Name: !Join - '' - - !Join - '' - !Split - '-' - hoge-mock - prod
!Split
で hoge-mock
を、 -
で分割した配列に変えます。
Name: !Join - '' - - !Join - '' - - hoge - mock - prod
!Join
で [hoge, mock]
を、文字列に変換します。
Name: !Join - '' - - hogemock - prod
!Join
で [hogemock, prod]
を、文字列に変換します。
Name: hogemockprod
こういう変換の流れで、 -
を消すことができました。
完成形
AWSTemplateFormatVersion: '2010-09-09' Description: WAF CI/CD Pipeline Parameters: ProductName: Type: String Stage: Type: String Default: prod Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Product Configuration Parameters: - ProductName - Stage ParameterLabels: ProductName: default: ProductName Stage: default: Stage Resources: WAF: Type: AWS::WAF::WebACL Properties: Name: !Join - '' - - !Join - '' - !Split - '-' - !Ref ProductName - !Ref Stage MetricName: !Join - '' - - !Join - '' - !Split - '-' - !Ref ProductName - !Ref Stage DefaultAction: Type: BLOCK Rules: - Action: Type: ALLOW Priority: 1 RuleId: !Ref WAFRule WAFRule: Type: AWS::WAF::Rule Properties: Name: !Join - '' - - !Join - '' - !Split - '-' - !Ref ProductName - MyIp - !Ref Stage MetricName: !Join - '' - - !Join - '' - !Split - '-' - !Ref ProductName - MyIp - !Ref Stage Predicates: - DataId: !Ref WAFIPSet Negated: false Type: IPMatch WAFIPSet: Type: AWS::WAF::IPSet Properties: Name: !Sub ${ProductName}-my-ipset-${Stage} IPSetDescriptors: - Type: IPV4 Value: {IPアドレス}/32