GitHub Actions 上で Azure Functions(PowerShell)をビルド・デプロイしているときに、AWS.Tools.S3 の Import だけがなぜか失敗する――この現象は、AWSPowerShell 系モジュールとの衝突やインストール方法の違いが原因で起きることが多いです。この記事では、エラーの正体から YAML の修正例、Azure Functions 側のモジュール管理までを一気に整理します。
GitHub Actions で AWS.Tools.S3 の Import が失敗する問題の全体像
まず、今回のケースを簡単に整理します。
- Azure Functions(PowerShell)を GitHub Actions からビルド/デプロイしている。
- ワークフロー内で
AWS.Tools.S3を導入しようとすると、次のようなエラーが出て失敗する。
Installing AWS.Tools.S3 version 4.1.343 ...
Install-Package: The following commands are already available on this system:
'Clear-AWSCredentials, ...'
このメッセージは、単なる「インストール失敗」以上の意味を持っています。特にポイントとなるのは以下の 2 点です。
- 同名コマンドの衝突(clobber) が起きている。
- Install-Package(PackageManagement)と Install-Module(PowerShellGet)が混在している可能性が高い。
つまり、モジュールの構成とインストールのやり方が「ごちゃっと」なっている状態です。これをきれいに整理してあげることで、GitHub Actions でも安定して AWS.Tools.S3 が使えるようになります。
エラーメッセージの意味:なぜ「The following commands are already available」になるのか
エラーメッセージのキーワードは 「The following commands are already available」 です。これは PowerShell の世界では「すでに同名のコマンドが読み込まれているので、別のモジュールから同じ名前のコマンドを上書きしようとしている」ことを意味します。
犯人になりがちなのが、次の 2 系列の AWS モジュールです。
- 旧来の一体型モジュール:
AWSPowerShell/AWSPowerShell.NetCore - 新しい分割モジュール(推奨):
AWS.Tools.S3などのAWS.Tools.*系
これらは内部的には似たコマンドを多数持っており、たとえば Clear-AWSCredentials や Get-S3Object のようなコマンド名が両方に存在します。そのため、片方が先にロードされている状態で、もう片方を導入しようとすると「どっちの Clear-AWSCredentials を使うの?」という衝突(clobber)が起きるわけです。
| モジュール系列 | 例 | 特徴 |
|---|---|---|
| 旧来一体型 | AWSPowerShell / AWSPowerShell.NetCore | すべての AWS サービスを 1 モジュールに詰め込んだ大型モジュール。コマンド数が多く、読み込みが重くなりがち。 |
| 新しい分割型 | AWS.Tools.S3 / AWS.Tools.EC2 など | サービスごとに分割された軽量モジュール。必要なサービスだけを導入できる。 |
今回のエラーは、GitHub Actions ランナー上に AWSPowerShell 系がすでに存在し、そこに AWS.Tools.S3 を Install-Package 経由で入れようとしたことで発生している可能性が高いと考えられます。
原因の整理:GitHub Actions ランナー特有の落とし穴
同じコードでも「ローカルでは動くのに GitHub Actions だと失敗する」というのは CI/CD あるあるです。今回のケースでは、特に次の 3 点が原因として効いてきます。
| 原因 | 具体的な内容 |
|---|---|
| 1. 旧モジュールが先に見つかる | ランナーのイメージや他ステップで AWSPowerShell 系がインストールされていると、先にそのコマンドがロードされてしまう。 |
| 2. Install-Package と Install-Module の混在 | Install-Package(PackageManagement)経由で入れると、PowerShellGet と管理場所が分かれ、不整合が起きやすい。 |
| 3. スコープやシェルの混在 | Windows PowerShell(5.1)と PowerShell 7(pwsh)が混在していると、どの環境にモジュールを入れたか分かりづらくなる。 |
特に GitHub Actions では、windows-latest や ubuntu-latest といった共用ランナーを使うため、「環境が毎回クリーンに見えて、実は事前インストール済みモジュールがいる」というケースがあります。これを前提にすると、ワークフロー(YAML)側で明示的にモジュールを整理する のが最も再現性の高い解決方法になります。
解決の基本方針:AWS.Tools 系へ統一し、AWSPowerShell 系を排除する
実務的な解決策はシンプルで、次の 3 ステップに集約できます。
- 旧モジュール(AWSPowerShell 系)をアンロード&アンインストールする
- AWS.Tools 系モジュールの導入方法を Install-Module に統一する
- Import-Module を明示し、どのモジュールを使うかをはっきりさせる
この方針に沿ってワークフローを整理すれば、冒頭のエラーはかなりの確率で解消できます。特にポイントとなるのが次のフラグです。
-AllowClobber:同名コマンドが存在しても上書きすることを許可。-Force:すでに存在するモジュールの上書き・再インストールを許可。
ただし、AllowClobber は万能薬ではありません。どのモジュールを「正とするか」(= AWS.Tools 系)を決めたうえで、不要なモジュールを片付けてから使う という順番が重要になります。
GitHub Actions ワークフローの具体的な修正例
ここからは、実際に GitHub Actions の YAML をどう書き換えるかを具体的に見ていきます。まずは Windows ランナーでの最小構成例です。
name: Build and Deploy Functions
on:
push:
branches: [ main ]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: 準備: PSGallery を信頼済みに
shell: pwsh
run: Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
- name: AWS.Tools.S3 をクリーンに導入
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
# 旧来モジュールをアンロード(ロード済みなら)
Get-Module AWSPowerShell,AWSPowerShell.NetCore -ErrorAction SilentlyContinue |
Remove-Module -Force -ErrorAction SilentlyContinue
# 旧来モジュールが見つかる場合はアンインストール(存在すれば)
if (Get-Module -ListAvailable AWSPowerShell) {
Uninstall-Module AWSPowerShell -AllVersions -Force -ErrorAction SilentlyContinue
}
if (Get-Module -ListAvailable AWSPowerShell.NetCore) {
Uninstall-Module AWSPowerShell.NetCore -AllVersions -Force -ErrorAction SilentlyContinue
}
# 推奨: インストーラー経由で必要モジュールのみ導入
Install-Module AWS.Tools.Installer -Scope CurrentUser -Force
Install-AWSToolsModule AWS.Tools.S3 `
-Scope CurrentUser `
-Force `
-CleanUp `
-AllowClobber `
-RequiredVersion 4.1.343
# インポートを明示
Import-Module AWS.Tools.S3 -Force
# 確認
Get-Command -Module AWS.Tools.S3 | Select-Object -First 5
各ステップが何をしているのか、整理しておきます。
| 処理 | 役割 |
|---|---|
| Set-PSRepository | PowerShell Gallery を信頼済みに設定し、対話不要で Install-Module できるようにする。 |
| Remove-Module AWSPowerShell* | すでにロードされている旧モジュールをアンロードし、メモリ上の衝突を避ける。 |
| Uninstall-Module AWSPowerShell* | ディスク上にインストールされている旧モジュールを削除し、解決順序から外す。 |
| Install-Module AWS.Tools.Installer | AWS.Tools 系モジュールをまとめて扱えるインストーラーを導入する。 |
| Install-AWSToolsModule AWS.Tools.S3 | AWS.Tools.S3 のみを指定バージョンでインストール。-CleanUp で不要ファイルも削除。 |
| Import-Module AWS.Tools.S3 | 使用するモジュールを明示的にインポートし、以降のステップで確実に利用できるようにする。 |
なお、Ubuntu ランナーに切り替えたい場合は、基本的には runs-on: ubuntu-latest に変更するだけで同じ PowerShell スクリプトが動作します。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: AWS.Tools.S3 をクリーンに導入 (Linux)
shell: pwsh
run: |
# 上記と同様の PowerShell スクリプトをここに記述
ここで重要なのは、必ず shell: pwsh を指定する ことです。デフォルトの bash や cmd のままだと PowerShell コマンドがそのままでは動作しませんし、Windows PowerShell 5.1 と PowerShell 7 が混在しているとモジュールの解決先がブレやすくなります。
Azure Functions(PowerShell)側でのモジュール管理:requirements.psd1 を活用する
GitHub Actions 側でモジュールをすべて準備する方法もありますが、Azure Functions(PowerShell)には requirements.psd1 を使った「実行時依存関係の管理」機能 があります。これを使うと、関数アプリが起動するときに自動で必要なモジュールをダウンロード・ロードしてくれます。
例として、次のような requirements.psd1 を関数プロジェクトのルートに置きます。
@{
'AWS.Tools.S3' = '4.1.343'
# 他に必要なモジュールがあればここへ追記
# 'Az' = '11.*'
}
この設定を行うと、Azure Functions ランタイムは初回起動時に PowerShell Gallery から指定バージョンのモジュールをダウンロードし、以降の関数実行時にはそのモジュールを利用できるようになります。関数コードからは単純に次のように呼び出せば OK です。
Import-Module AWS.Tools.S3
# 例: S3 バケットの一覧を取得
Get-S3Bucket
この方式のメリットは、GitHub Actions 側の YAML からモジュール管理の責務を外せる ことです。CI ではビルド・テスト・デプロイに集中し、モジュール導入は Azure Functions ランタイムに任せる、という役割分担ができます。
| 管理方法 | モジュール導入の場所 | 向いているケース |
|---|---|---|
| GitHub Actions で導入 | CI ランナー(ビルド環境) | ビルド時に AWS を叩きたい、テスト時に S3 にアクセスしたい場合など。 |
| requirements.psd1 で導入 | Azure Functions ランタイム(実行環境) | 本番実行環境だけで S3 を使えればよい、CI は単純にデプロイだけしたい場合。 |
実際の現場では、両方を併用する ケースも多いです。たとえば、CI 側では最小限の動作確認だけ行い、本番依存度の高い処理は Azure Functions 上で行う、といった運用です。
Install-Package を避け、Install-Module に統一する理由
エラー文を見ると Install-Package が使われていることが分かりますが、PowerShell モジュールの導入では基本的に Install-Module(PowerShellGet)に統一する ことを強くおすすめします。
理由は主に次の 3 つです。
- 管理場所が違う:
Install-Packageは PackageManagement、Install-Moduleは PowerShellGet を経由します。モジュールの格納パスやバージョン管理の仕組みが異なるため、「どこに入ったのか分からない」状態になりがちです。 - ドキュメントの前提:AWS 公式の PowerShell ドキュメントや Azure Functions のサンプルは
Install-Moduleを前提としていることが多く、トラブルシュートしやすいです。 - 混在時のバグが分かりにくい:一部のモジュールを
Install-Package、別のモジュールをInstall-Moduleで入れると、名前は同じなのに実体が違うことがあります。
そのため、GitHub Actions の YAML を修正するときは、Install-Package をすべて廃止して Install-Module に揃える のが安全です。すでに Install-Package AWS.Tools.S3 のような記述がある場合は、次のように書き換えるとよいでしょう。
# NG 例
Install-Package AWS.Tools.S3 -Force
# OK 例
Install-Module AWS.Tools.S3 -Scope CurrentUser -Force -AllowClobber
よくあるハマりどころと回避策のチェックリスト
ここまでの内容を踏まえて、AWS.Tools.S3 に限らず「PowerShell モジュール周りでハマりやすいポイント」をチェックリスト形式でまとめておきます。GitHub Actions のトラブルシューティング時に流し読みできるよう、症状ベースで整理します。
| 症状 | 想定される原因 | 確認・対処のポイント |
|---|---|---|
| Install-Package エラーで「already available」 | AWSPowerShell 系と AWS.Tools 系の同名コマンド衝突 | 旧モジュールのアンロード&アンインストール。Install-Module に切り替え、AllowClobber を付けて再導入。 |
| ローカルでは動くが GitHub Actions で Import できない | ランナーにモジュールが入っていない / シェルが異なる | shell: pwsh を指定しているか確認。ワークフロー内で Install-Module を実行。 |
| モジュールがどこにインストールされたか分からない | Install-Package と Install-Module の混在 | Get-Module -ListAvailable AWS* でパスを確認し、Install-Package で入れたモジュールを削除。 |
| Azure Functions 上では動くが CI では動かない | requirements.psd1 だけを頼りにしている | CI で AWS を叩きたい場合は、GitHub Actions 側でも AWS.Tools.* をインストールしておく。 |
| Windows と Ubuntu で挙動が違う | Windows PowerShell 5.1 と PowerShell 7 の混在 | CI では必ず PowerShell 7(pwsh)を使用し、ローカルも合わせる。 |
トラブルシューティングに役立つ PowerShell コマンド集
実際に問題が起きたときに素早く状況を把握するためのコマンド例をまとめておきます。GitHub Actions のデバッグステップや、ローカルでの検証にそのまま流用できます。
現在ロードされている AWS 関連モジュールを確認
Get-Module AWS*,AWSPowerShell* | Select-Object Name, Version, Path
どの系列のモジュールがメモリ上に載っているかを確認できます。ここに AWSPowerShell がいれば、まずは Remove-Module で降ろしてあげるのが先決です。
ディスク上に存在する AWS 関連モジュールを確認
Get-Module -ListAvailable AWS*,AWSPowerShell* `
| Select-Object Name, Version, ModuleBase
パスを見れば、「どのユーザースコープに入っているか」「OS が事前にインストールしているものか」などが判断しやすくなります。
旧来モジュールをまとめて削除
Get-Module -ListAvailable AWSPowerShell,AWSPowerShell.NetCore `
| Sort-Object Version -Descending `
| ForEach-Object {
Write-Host "Uninstalling $($_.Name) $($_.Version)"
Uninstall-Module $_.Name -RequiredVersion $_.Version -Force -ErrorAction SilentlyContinue
}
GitHub Actions 上では、これをワークフロー中の一時的なクリーンアップとして実行しておけば、「ランナーの初期状態に何が入っていても気にせず自分の世界を作る」ことができます。
GitHub Actions と Azure Functions での役割分担の考え方
最後に、モジュール管理の役割分担について少し踏み込んでおきます。AWS.Tools.S3 をどこで導入・更新するかは、チームの運用ポリシーによって変わりますが、代表的なパターンは次の 3 つです。
| パターン | 特徴 | メリット | デメリット |
|---|---|---|---|
| ① すべて CI で導入 | GitHub Actions 内でモジュールをインストールし、本番環境にはバンドル済みの状態でデプロイ。 | 本番と CI のモジュールが完全に一致。アーティファクト単位で再現可能。 | ビルド時間が長くなりがち。Azure Functions の managed dependencies と重複することも。 |
| ② すべて Azure Functions で導入 | requirements.psd1 のみで管理し、CI 側ではモジュールを持たない。 | CI の設定がシンプル。ランタイムの更新にも追随しやすい。 | CI 上で AWS を利用するテストがやりづらい。本番初回起動時に依存モジュールのダウンロードが発生。 |
| ③ ハイブリッド | CI でも最小限のモジュールを導入しつつ、最終的な依存は requirements.psd1 に委ねる。 | CI でのテストと本番の安定性を両立できる。 | 設計がやや複雑。どこまでを CI で、どこからを本番で行うか設計が必要。 |
今回のようなエラーをきっかけに、「そもそもどこでモジュールを管理するべきか」 を見直しておくと、将来的なバージョンアップやランナー変更に強い構成にできます。
まとめ:YAML を整理し、AWS.Tools 系に統一するのが近道
ここまでの内容をまとめると、GitHub Actions 実行時に AWS.Tools.S3 の Import が失敗する問題は、次のように整理できます。
- エラーの本質は AWSPowerShell 系モジュールと AWS.Tools 系モジュールの同名コマンド衝突 である。
Install-PackageとInstall-Moduleの混在や、Windows PowerShell と PowerShell 7 の混在が不整合を増幅する。- 解決策としては、GitHub Actions の YAML を修正し、旧モジュールの除去 → AWS.Tools 系に統一 → Install-Module / Import-Module を明示 するのが実務的に最も確実。
- Azure Functions(PowerShell)では requirements.psd1 を使ったモジュール管理も有効で、CI と本番の役割分担を見直すきっかけになる。
一度 YAML をきちんと整えておけば、GitHub Actions ランナーのイメージが変わったり、PowerShell のバージョンが上がった場合でも、「毎回同じ手順で AWS.Tools.S3 が導入される」という再現性を維持できます。
もし同様のエラーに悩まされている場合は、まずは 「旧モジュールを消し、AWS.Tools 系の世界に統一する」 ことを意識して、ワークフローを見直してみてください。それだけでも、かなりのトラブルが解消されるはずです。

コメント