{"id":48790,"date":"2023-08-04T01:25:10","date_gmt":"2023-10-29T13:44:10","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/"},"modified":"2024-04-30T16:51:41","modified_gmt":"2024-04-30T08:51:41","slug":"%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/","title":{"rendered":"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP"},"content":{"rendered":"<h1>\u505a\u7684\u4e8b\u60c5<\/h1>\n<p>GitHub Actions + Terraform + GCP\uff08OIDC\uff09\u5728\u4e2d\u56fd\u672c\u571f\u5316\u540e\u52a0\u4ee5\u5229\u7528\u3002<\/p>\n<h1>\u4ee5\u4e0b\u662f\u5bf9\u201c\u30b9\u30c6\u30c3\u30d7\u201d\u7684\u4e00\u79cd\u4e2d\u6587\u672c\u5730\u5316\u7684\u91ca\u4e49\uff1a<\/h1>\n<p>\u6b65\u9aa4<\/p>\n<h2>1. \u521b\u5efa (GCP) Service Account<\/h2>\n<p>\u5728GitHub Actions\u4e2d\u521b\u5efa\u4e00\u4e2aService Account\u5e76\u6388\u4e88Editor\u89d2\u8272\u3002\uff08\u6b64\u6b21\u5728\u63a7\u5236\u53f0\u4e0a\u8fdb\u884c\u64cd\u4f5c\u3002\uff09<\/p>\n<p>\u8bbe\u5b9a\u53d8\u91cf<\/p>\n<pre class=\"post-pre\"><code><span class=\"nb\">export <\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"o\">=<\/span>&lt;your project <span class=\"nb\">id<\/span><span class=\"o\">&gt;<\/span>\r\n<span class=\"nb\">export <\/span><span class=\"nv\">POOL_NAME<\/span><span class=\"o\">=<\/span>&lt;pool name&gt; <span class=\"c\"># github-actions <\/span>\r\n<span class=\"nb\">export <\/span><span class=\"nv\">PROVIDER_NAME<\/span><span class=\"o\">=<\/span>&lt;provider name&gt; <span class=\"c\"># gha-provider<\/span>\r\n<span class=\"nb\">export <\/span><span class=\"nv\">SA_EMAIL<\/span><span class=\"o\">=<\/span>&lt;service_account name&gt;@&lt;project_name&gt;.iam.gserviceaccount.com\r\n<span class=\"nb\">export <\/span><span class=\"nv\">GITHUB_REPO<\/span><span class=\"o\">=<\/span>&lt;org&gt;\/&lt;repo_name&gt;\r\n<\/code><\/pre>\n<p>\u542f\u7528iamcredentials API<\/p>\n<pre class=\"post-pre\"><code>gcloud services <span class=\"nb\">enable <\/span>iamcredentials.googleapis.com <span class=\"nt\">--project<\/span> <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span>\r\n<\/code><\/pre>\n<p>\u5c06 workload-identity-pools \u521b\u5efa\u5e76\u5c06\u5176 ID \u5b58\u50a8\u5728\u53d8\u91cf WORKLOAD_IDENTITY_POOL_ID \u4e2d\u3002<\/p>\n<pre class=\"post-pre\"><code>gcloud iam workload-identity-pools create <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">POOL_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--project<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">--location<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"global\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--display-name<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"use from GitHub Actions\"<\/span>\r\n<span class=\"nb\">export <\/span><span class=\"nv\">WORKLOAD_IDENTITY_POOL_ID<\/span><span class=\"o\">=<\/span><span class=\"si\">$(<\/span> <span class=\"se\">\\<\/span>\r\n    gcloud iam workload-identity-pools describe <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">POOL_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n      <span class=\"nt\">--project<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">--location<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"global\"<\/span> <span class=\"se\">\\<\/span>\r\n      <span class=\"nt\">--format<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"value(name)\"<\/span> <span class=\"se\">\\<\/span>\r\n  <span class=\"si\">)<\/span>\r\n<\/code><\/pre>\n<p>\u786e\u8ba4 WORKLOAD_IDENTITY_POOL_ID \u7684\u5185\u5bb9<\/p>\n<pre class=\"post-pre\"><code>echo $WORKLOAD_IDENTITY_POOL_ID\r\n<\/code><\/pre>\n<p>\u4e3aGitHub\u521b\u5efaOIDC providers\u7684\u5de5\u4f5c\u8d1f\u8f7d\u8eab\u4efd\u6c60\u3002<\/p>\n<pre class=\"post-pre\"><code>gcloud iam workload-identity-pools providers create-oidc <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROVIDER_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--project<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">--location<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"global\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--workload-identity-pool<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">POOL_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--display-name<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"use from GitHub Actions provider\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--attribute-mapping<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.actor=assertion.actor,attribute.aud=assertion.aud\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--issuer-uri<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"https:\/\/token.actions.githubusercontent.com\"<\/span>\r\n<\/code><\/pre>\n<p>\u5c06\u670d\u52a1\u8d26\u53f7\u7ed1\u5b9a\u5230\u7b56\u7565 (\u7ed1\u5b9a\u7b56\u7565\u5230\u670d\u52a1\u8d26\u53f7)<\/p>\n<pre class=\"post-pre\"><code>gcloud iam service-accounts add-iam-policy-binding <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">SA_EMAIL<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--project<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--role<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"roles\/iam.workloadIdentityUser\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--member<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"principalSet:\/\/iam.googleapis.com\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">WORKLOAD_IDENTITY_POOL_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\/attribute.repository\/<\/span><span class=\"k\">${<\/span><span class=\"nv\">GITHUB_REPO<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span>\r\n<\/code><\/pre>\n<p>\u63cf\u8ff0\u63d0\u4f9b\u8005\uff0c\u5e76\u786e\u8ba4\u5de5\u4f5c\u8d1f\u8f7d\u8eab\u4efd\u63d0\u4f9b\u8005\u3002<\/p>\n<pre class=\"post-pre\"><code>gcloud iam workload-identity-pools providers describe <span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROVIDER_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--project<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">PROJECT_ID<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"nt\">--location<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"global\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--workload-identity-pool<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"k\">${<\/span><span class=\"nv\">POOL_NAME<\/span><span class=\"k\">}<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\n    <span class=\"nt\">--format<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"value(name)\"<\/span>\r\n<\/code><\/pre>\n<p>\u7ed3\u679c: workload_identity_provider\uff08GitHub Actions\u914d\u7f6e\u9700\u8981\u8bb0\u4e0b\u6765\u5907\u5fd8\uff09<\/p>\n<pre class=\"post-pre\"><code>projects\/&lt;id&gt;\/locations\/global\/workloadIdentityPools\/&lt;pool_name&gt;\/providers\/&lt;provider_name&gt;\r\n<\/code><\/pre>\n<h2>2. \u521b\u5efa(GCP)\u4e91\u5b58\u50a8\u5b58\u50a8\u6876<\/h2>\n<p>\u9009\u62e9Region\u4e3aasia-northeast1\uff08\u4e1c\u4eac\uff09\uff0c\u5176\u4f59\u5168\u90e8\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e\u521b\u5efa\u5b58\u50a8\u6876\u3002<\/p>\n<h2>3. \u51c6\u5907terraform\u4ee3\u7801\u3002<\/h2>\n<p>\u672c\u6b21\uff0c\u6211\u4eec\u5c06\u628aTerraform\u7684\u4ee3\u7801\u653e\u5728\u540d\u4e3agcp\u7684\u6587\u4ef6\u5939\u4e0b\uff08\u901a\u8fc7GitHub Actions\u7684WORKING_DIR\u53c2\u6570\u8bbe\u7f6e\u4e3agcp\uff0c\u6216\u8005\u786e\u4fdd\u5728gcp\u6587\u4ef6\u5939\u5185\u8fdb\u884c\u4ee3\u7801\u66f4\u6539\u4ee5\u4f7fGitHub Actions\u6b63\u5e38\u8fd0\u884c\uff09\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nx\">terraform<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">required_providers<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">google<\/span> <span class=\"p\">=<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">source<\/span>  <span class=\"p\">=<\/span> <span class=\"s2\">\"hashicorp\/google\"<\/span>\r\n      <span class=\"nx\">version<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"~&gt; 4.0\"<\/span> <span class=\"c1\"># OIDC https:\/\/github.com\/hashicorp\/terraform-provider-google\/releases\/tag\/v3.61.0 or later<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"nx\">backend<\/span> <span class=\"s2\">\"gcs\"<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">bucket<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"&lt;bucket_name&gt;\"<\/span>\r\n    <span class=\"nx\">prefix<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"state\"<\/span> <span class=\"c1\"># any prefix is ok.<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>terraform init\r\n<\/code><\/pre>\n<p>\u8bf7\u5c06.terraform.lock.hcl\u4e5f\u5b89\u88c5\u597d\u3002<\/p>\n<blockquote><p>\u6bcf\u6b21\u8fd0\u884c terraform init \u547d\u4ee4\u65f6\uff0cTerraform \u4f1a\u81ea\u52a8\u521b\u5efa\u6216\u66f4\u65b0\u4f9d\u8d56\u9501\u5b9a\u6587\u4ef6\u3002\u4f60\u5e94\u8be5\u5c06\u8be5\u6587\u4ef6\u5305\u542b\u5728\u4f60\u7684\u7248\u672c\u63a7\u5236\u5e93\u4e2d\u3002<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h2>4. \u521b\u5efaGitHub Actions<\/h2>\n<p>\u4ece\u4e4b\u524d\u8bbe\u7f6e\u7684\u670d\u52a1\u5e10\u6237\u4e2d\u83b7\u53d6\u6240\u9700\u4fe1\u606f\u3002<\/p>\n<p>workload_identity_provider: projects\/\/locations\/global\/workloadIdentityPools\/\/providers\/<\/p>\n<p>service_account: @.iam.gserviceaccount.com<\/p>\n<p>\u6211\u5011\u9019\u6b21\u8981\u505a\u7684GitHub Actions\u662f\uff1a<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u5f53\u6709\u4e86\u8ba1\u5212\u5e76\u5728\u516c\u5173\u4e2d\u8fdb\u884c\u4e86\u8bc4\u8bba\u540e\uff0c\u5373\u53ef\u5728\u516c\u5173\u4e2d\u5199\u4e0b\u7ed3\u679c\u3002<\/ol>\n<\/li>\n<\/ol>\n<p>\u5f53\u5408\u5e76\u5230\u4e3b\u5206\u652f\u540e\uff0c\u8bf7\u5e94\u7528\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">gcp<\/span>\r\n<span class=\"na\">on<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">pull_request<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">paths<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">gcp\/**'<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">!gcp\/**md'<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">.github\/workflows\/gcp.yml'<\/span>\r\n    <span class=\"na\">branches<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">main<\/span>\r\n  <span class=\"na\">push<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">paths<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">gcp\/**'<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">!gcp\/**md'<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s1\">'<\/span><span class=\"s\">.github\/workflows\/gcp.yml'<\/span>\r\n    <span class=\"na\">branches<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">main<\/span>\r\n\r\n<span class=\"na\">env<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">TERRAFORM_VERSION<\/span><span class=\"pi\">:<\/span> <span class=\"s\">1.1.8<\/span>\r\n  <span class=\"na\">WORKING_DIR<\/span><span class=\"pi\">:<\/span> <span class=\"s\">gcp<\/span> <span class=\"c1\"># Use `gcp` dir in this example.<\/span>\r\n\r\n<span class=\"na\">jobs<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">terraform<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"c1\"># Add \"id-token\" with the intended permissions.<\/span>\r\n    <span class=\"na\">permissions<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">contents<\/span><span class=\"pi\">:<\/span> <span class=\"s\">read<\/span>\r\n      <span class=\"na\">id-token<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span>\r\n      <span class=\"na\">pull-requests<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span>\r\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\r\n    <span class=\"na\">defaults<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">run<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">working-directory<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ env.WORKING_DIR }}<\/span>\r\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v3<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">auth'<\/span>\r\n        <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">Authenticate<\/span> <span class=\"s\">to<\/span> <span class=\"s\">Google<\/span> <span class=\"s\">Cloud'<\/span>\r\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">google-github-actions\/auth@v0.7.0<\/span>\r\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\r\n          <span class=\"na\">create_credentials_file<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">true'<\/span>\r\n          <span class=\"na\">workload_identity_provider<\/span><span class=\"pi\">:<\/span> <span class=\"s\">projects\/&lt;project_id&gt;\/locations\/global\/workloadIdentityPools\/github-actions\/providers\/gha-provider<\/span>\r\n          <span class=\"na\">service_account<\/span><span class=\"pi\">:<\/span> <span class=\"s\">&lt;service_account_name&gt;@&lt;project_name&gt;.iam.gserviceaccount.com<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">hashicorp\/setup-terraform@v1<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Terraform fmt<\/span>\r\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">fmt<\/span>\r\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">terraform fmt -check<\/span>\r\n        <span class=\"na\">continue-on-error<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Terraform Init<\/span>\r\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">init<\/span>\r\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">terraform init<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Terraform Validate<\/span>\r\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">validate<\/span>\r\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">terraform validate -no-color<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Terraform Plan<\/span>\r\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">plan<\/span>\r\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">terraform plan -no-color -lock=false<\/span> <span class=\"c1\"># TODO<\/span>\r\n        <span class=\"na\">continue-on-error<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/github-script@v6<\/span>\r\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">github.event_name == 'pull_request'<\/span>\r\n        <span class=\"na\">env<\/span><span class=\"pi\">:<\/span>\r\n          <span class=\"na\">PLAN<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">terraform<\/span><span class=\"se\">\\n<\/span><span class=\"s\">${{<\/span> <span class=\"s\">steps.plan.outputs.stdout<\/span> <span class=\"s\">}}\"<\/span>\r\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\r\n          <span class=\"na\">github-token<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ secrets.GITHUB_TOKEN }}<\/span>\r\n          <span class=\"na\">script<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\r\n            <span class=\"s\">const output = `#### Terraform Format and Style ?\\`${{ steps.fmt.outcome }}\\`<\/span>\r\n            <span class=\"s\">#### Terraform Initialization \u2699\ufe0f\\`${{ steps.init.outcome }}\\`<\/span>\r\n            <span class=\"s\">#### Terraform Validation ?\\`${{ steps.validate.outcome }}\\`<\/span>\r\n            <span class=\"s\">&lt;details&gt;&lt;summary&gt;Validation Output&lt;\/summary&gt;<\/span>\r\n            <span class=\"s\">\\`\\`\\`\\n<\/span>\r\n            <span class=\"s\">${{ steps.validate.outputs.stdout }}<\/span>\r\n            <span class=\"s\">\\`\\`\\`<\/span>\r\n            <span class=\"s\">&lt;\/details&gt;<\/span>\r\n            <span class=\"s\">#### Terraform Plan ?\\`${{ steps.plan.outcome }}\\`<\/span>\r\n            <span class=\"s\">&lt;details&gt;&lt;summary&gt;Show Plan&lt;\/summary&gt;<\/span>\r\n            <span class=\"s\">\\`\\`\\`\\n<\/span>\r\n            <span class=\"s\">${process.env.PLAN}<\/span>\r\n            <span class=\"s\">\\`\\`\\`<\/span>\r\n            <span class=\"s\">&lt;\/details&gt;<\/span>\r\n            <span class=\"s\">*Pusher: @${{ github.actor }}, Action: \\`${{ github.event_name }}\\`, Working Directory: \\`${{ env.tf_actions_working_dir }}\\`, Workflow: \\`${{ github.workflow }}\\`*`;<\/span>\r\n            <span class=\"s\">github.rest.issues.createComment({<\/span>\r\n              <span class=\"s\">issue_number: context.issue.number,<\/span>\r\n              <span class=\"s\">owner: context.repo.owner,<\/span>\r\n              <span class=\"s\">repo: context.repo.repo,<\/span>\r\n              <span class=\"s\">body: output<\/span>\r\n            <span class=\"s\">})<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">steps.plan.outcome == 'failure' || steps.fmt.outcome == 'failure'<\/span>\r\n        <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">make it fail when plan failed<\/span>\r\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">exit <\/span><span class=\"m\">1<\/span>\r\n\r\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Terraform Apply<\/span>\r\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">apply<\/span>\r\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'<\/span>\r\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">terraform apply -auto-approve -input=false -lock=false<\/span> <span class=\"c1\"># TODO<\/span>\r\n<\/code><\/pre>\n<h2>5. PR\u7b56\u5212\u548c\u5408\u5e76<\/h2>\n<p>\u52a8\u4f5c\u786e\u8ba4:<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">PR\u3067\u30b3\u30e1\u30f3\u30c8\u306bPlan\u7d50\u679c\u304c\u66f8\u304b\u308c\u308b<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">Merge\u3067Apply\u304c\u8d70\u308b<\/ul>\n<h1>\u6ce8\u610f\u4e8b\u9879\u548c\u95ee\u9898<\/h1>\n<h2>\u8c37\u6b4c\u63d0\u4f9b\u5546\u7684\u7248\u672c\u8fdb\u884c\u57fa\u7840\u8bbe\u65bd\u6784\u5efa<\/h2>\n<p>v3.61.0 \u6216\u66f4\u9ad8\u7248\u672c\uff08\u4f9b\u5e94\u5546\u73b0\u5728\u652f\u6301\u5de5\u4f5c\u8d1f\u8f7d\u8eab\u4efd\u8054\u5408\uff09\u3002<br \/>\n\u8981\u4f7f\u7528 OIDC\uff0c\u8bf7\u786e\u4fdd Provider \u7684\u7248\u672c\u4e3a v3.61.0 \u6216\u66f4\u9ad8\u3002<\/p>\n<h2>2. \u9501\u7684\u95ee\u9898<\/h2>\n<p>\u5982\u679c\u751f\u6210\u4e86lock\u6587\u4ef6\uff0c\u5c06\u65e0\u6cd5\u6267\u884cPlan\/Apply\u3002\uff08\u6682\u5b9a\u7684\u89e3\u51b3\u65b9\u6848\u662f-lock=false\uff0c\u4f46\u4e0d\u5efa\u8bae\u4f7f\u7528\u3002\u6700\u574f\u7684\u60c5\u51b5\u4e0b\u53ef\u4ee5\u4f7f\u7528gsutil\u6765\u5220\u9664lock\u6587\u4ef6\u3002\uff09<\/p>\n<pre class=\"post-pre\"><code>Terraform acquires a state lock to protect the state from being written by multiple users at the same time. Please resolve the issue above and try again. For most commands, you can disable locking with the \"-lock=false\" flag, but this is not recommended.\r\n<\/code><\/pre>\n<h2>\u5728GitHub Actions\u4e2d\uff0c\u5373\u4f7f\u5728setup-terraform#usage\u7684\u793a\u4f8b\u4e2d\u8ba1\u5212\u5931\u8d25\uff0c\u7ed3\u679c\u4ecd\u7136\u4f1a\u663e\u793a\u4e3a\u6210\u529f\u3002<\/h2>\n<p>\u6dfb\u52a0\u4ee5\u4e0b\u6b65\u9aa4<\/p>\n<pre class=\"post-pre\"><code>  <span class=\"pi\">-<\/span> <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">steps.plan.outcome == 'failure'<\/span>\r\n    <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">make it fail when plan failed<\/span>\r\n    <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">exit <\/span><span class=\"m\">1<\/span>\r\n<\/code><\/pre>\n<h2>4. \u542f\u7528API API)<\/h2>\n<p>\u5982\u679c\u4e0d\u542f\u7528API\uff0c\u5c06\u4f1a\u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef\u3002<\/p>\n<pre class=\"post-pre\"><code>Error: Error creating Address: googleapi: Error 403: Compute Engine API has not been used in project xxxxxx before or it is disabled. Enable it by visiting\r\n<\/code><\/pre>\n<h1>\u8bf7\u53c2\u9605<\/h1>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">https:\/\/github.com\/hashicorp\/setup-terraform<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">https:\/\/engineer.retty.me\/entry\/2021\/09\/22\/123000<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">https:\/\/scrapbox.io\/pokutuna\/GCP_API_%E3%82%92_Terraform_%E3%81%8B%E3%82%89%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B<\/ul>\n<\/li>\n<\/ul>\n<p>https:\/\/qiita.com\/mintak21\/items\/5232a089f3a39a71b155 &lt;- \u3042\u3068\u304b\u3089\u898b\u3064\u3051\u305f\u3051\u3069\u3001Service Account\u306e\u4f5c\u6210\u3082\u542b\u3081\u3066Terraform\u3067\u51fa\u6765\u3066\u308b\u306e\u3067\u3053\u3061\u3089\u306e\u307b\u3046\u304c\u3044\u3044!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u505a\u7684\u4e8b\u60c5 GitHub Actions + Terraform + GCP\uff08OIDC\uff09\u5728\u4e2d\u56fd\u672c\u571f\u5316\u540e\u52a0\u4ee5\u5229\u7528\u3002 [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-48790","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528github-actions\u548cterraform\u5f00\u59cb\u7ba1\u7406gcp\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP\" \/>\n<meta property=\"og:description\" content=\"\u505a\u7684\u4e8b\u60c5 GitHub Actions + Terraform + GCP\uff08OIDC\uff09\u5728\u4e2d\u56fd\u672c\u571f\u5316\u540e\u52a0\u4ee5\u5229\u7528\u3002 [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528github-actions\u548cterraform\u5f00\u59cb\u7ba1\u7406gcp\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-29T13:44:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-30T08:51:41+00:00\" \/>\n<meta name=\"author\" content=\"\u65b0, \u97f5\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u65b0, \u97f5\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/\",\"name\":\"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2023-10-29T13:44:10+00:00\",\"dateModified\":\"2024-04-30T08:51:41+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9\",\"name\":\"\u65b0, \u97f5\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g\",\"caption\":\"\u65b0, \u97f5\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/yunxin\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528github-actions\u548cterraform\u5f00\u59cb\u7ba1\u7406gcp\/","og_locale":"zh_CN","og_type":"article","og_title":"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP","og_description":"\u505a\u7684\u4e8b\u60c5 GitHub Actions + Terraform + GCP\uff08OIDC\uff09\u5728\u4e2d\u56fd\u672c\u571f\u5316\u540e\u52a0\u4ee5\u5229\u7528\u3002 [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528github-actions\u548cterraform\u5f00\u59cb\u7ba1\u7406gcp\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2023-10-29T13:44:10+00:00","article_modified_time":"2024-04-30T08:51:41+00:00","author":"\u65b0, \u97f5","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u65b0, \u97f5","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"4 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/","name":"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2023-10-29T13:44:10+00:00","dateModified":"2024-04-30T08:51:41+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u4f7f\u7528GitHub Actions\u548cTerraform\u5f00\u59cb\u7ba1\u7406GCP"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9","name":"\u65b0, \u97f5","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g","caption":"\u65b0, \u97f5"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/yunxin\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8github-actions%e5%92%8cterraform%e5%bc%80%e5%a7%8b%e7%ae%a1%e7%90%86gcp\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/48790","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=48790"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/48790\/revisions"}],"predecessor-version":[{"id":93110,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/48790\/revisions\/93110"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=48790"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=48790"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=48790"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}