From bc6571a8c1ca9cfeb981aa74704388b3ef40e74e Mon Sep 17 00:00:00 2001 From: Jonathan Carroll Otsuka <105506+djgoku@users.noreply.github.com> Date: Sun, 13 Jul 2025 01:27:24 -0500 Subject: [PATCH 1/5] feat: add `AWS.CodeGen.Util.maybe_add_parens/1` This function takes in a string and only adds `()` when there are no previous parens. --- lib/aws_codegen/util.ex | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/aws_codegen/util.ex b/lib/aws_codegen/util.ex index c09d6f0..a40caa9 100644 --- a/lib/aws_codegen/util.ex +++ b/lib/aws_codegen/util.ex @@ -62,4 +62,12 @@ defmodule AWS.CodeGen.Util do |> Enum.reverse() end end + + def maybe_add_parens(string) do + if String.ends_with?(string, "()") do + string + else + string <> "()" + end + end end From c9dc9401f5eab5623c9e154f2761af21fb00e499 Mon Sep 17 00:00:00 2001 From: Jonathan Carroll Otsuka <105506+djgoku@users.noreply.github.com> Date: Sun, 13 Jul 2025 01:42:55 -0500 Subject: [PATCH 2/5] chore: switch to using `maybe_add_parens/1` and update tests --- lib/aws_codegen/types.ex | 14 +++-- test/aws_codegen_test.exs | 18 +++--- test/fixtures/generated/data_exchange.ex | 80 ++++++++++++------------ 3 files changed, 58 insertions(+), 54 deletions(-) diff --git a/lib/aws_codegen/types.ex b/lib/aws_codegen/types.ex index 27604c6..7fe8daf 100644 --- a/lib/aws_codegen/types.ex +++ b/lib/aws_codegen/types.ex @@ -103,20 +103,24 @@ defmodule AWS.CodeGen.Types do %Shape{type: "structure"} -> type = "#{AWS.CodeGen.Name.to_snake_case(String.replace(shape_name, ~r/com\.amazonaws\.[^#]+#/, ""))}" + |> AWS.CodeGen.Util.maybe_add_parens() if reserved_type(type) do - "#{String.downcase(String.replace(context.module_name, ["aws_", "AWS."], ""))}_#{type}()" + "#{String.downcase(String.replace(context.module_name, ["aws_", "AWS."], ""))}_#{type}" else - "#{type}()" + "#{type}" end %Shape{type: "list", member: member} -> - type = "#{shape_to_type(context, member["target"], module_name, all_shapes)}" + # this change alone gets us down to 1595 + type = + "#{shape_to_type(context, member["target"], module_name, all_shapes)}" + |> AWS.CodeGen.Util.maybe_add_parens() if reserved_type(type) do - "list(#{String.downcase(String.replace(context.module_name, ["aws_", "AWS."], ""))}_#{type}())" + "list(#{String.downcase(String.replace(context.module_name, ["aws_", "AWS."], ""))}_#{type})" else - "list(#{type}())" + "list(#{type})" end nil -> diff --git a/test/aws_codegen_test.exs b/test/aws_codegen_test.exs index 08ba277..a8b2707 100644 --- a/test/aws_codegen_test.exs +++ b/test/aws_codegen_test.exs @@ -171,7 +171,7 @@ defmodule AWS.CodeGenTest do put_audit_events_request() :: %{ optional(\"externalId\") => String.t(), - required(\"auditEvents\") => list(audit_event()()), + required(\"auditEvents\") => list(audit_event()), required(\"channelArn\") => String.t() } @@ -183,8 +183,8 @@ defmodule AWS.CodeGenTest do ## Example: put_audit_events_response() :: %{ - required(\"failed\") => list(result_error_entry()()), - required(\"successful\") => list(audit_event_result_entry()()) + required(\"failed\") => list(result_error_entry()), + required(\"successful\") => list(audit_event_result_entry()) } \"\"\" @@ -409,7 +409,7 @@ defmodule AWS.CodeGenTest do put_audit_events_request() :: %{ optional(\"externalId\") => String.t(), - required(\"auditEvents\") => list(audit_event()()), + required(\"auditEvents\") => list(audit_event()), required(\"channelArn\") => String.t() } @@ -421,8 +421,8 @@ defmodule AWS.CodeGenTest do ## Example: put_audit_events_response() :: %{ - required(\"failed\") => list(result_error_entry()()), - required(\"successful\") => list(audit_event_result_entry()()) + required(\"failed\") => list(result_error_entry()), + required(\"successful\") => list(audit_event_result_entry()) } \"\"\" @@ -653,7 +653,7 @@ defmodule AWS.CodeGenTest do put_audit_events_request() :: %{ optional(\"externalId\") => String.t(), - required(\"auditEvents\") => list(audit_event()()), + required(\"auditEvents\") => list(audit_event()), required(\"channelArn\") => String.t() } @@ -665,8 +665,8 @@ defmodule AWS.CodeGenTest do ## Example: put_audit_events_response() :: %{ - required(\"failed\") => list(result_error_entry()()), - required(\"successful\") => list(audit_event_result_entry()()) + required(\"failed\") => list(result_error_entry()), + required(\"successful\") => list(audit_event_result_entry()) } \"\"\" diff --git a/test/fixtures/generated/data_exchange.ex b/test/fixtures/generated/data_exchange.ex index e706a75..b43a274 100644 --- a/test/fixtures/generated/data_exchange.ex +++ b/test/fixtures/generated/data_exchange.ex @@ -111,9 +111,9 @@ defmodule AWS.DataExchange do ## Example: scope_details() :: %{ - "LakeFormationTagPolicies" => list(lake_formation_tag_policy_details()()), - "RedshiftDataShares" => list(redshift_data_share_details()()), - "S3DataAccesses" => list(s3_data_access_details()()) + "LakeFormationTagPolicies" => list(lake_formation_tag_policy_details()), + "RedshiftDataShares" => list(redshift_data_share_details()), + "S3DataAccesses" => list(s3_data_access_details()) } """ @@ -208,7 +208,7 @@ defmodule AWS.DataExchange do ## Example: list_received_data_grants_request() :: %{ - optional("AcceptanceState") => list(String.t()()), + optional("AcceptanceState") => list(String.t()), optional("MaxResults") => integer(), optional("NextToken") => String.t() } @@ -221,7 +221,7 @@ defmodule AWS.DataExchange do ## Example: list_data_sets_response() :: %{ - optional("DataSets") => list(data_set_entry()()), + optional("DataSets") => list(data_set_entry()), optional("NextToken") => String.t() } @@ -236,7 +236,7 @@ defmodule AWS.DataExchange do "DataSetId" => String.t(), "Encryption" => export_server_side_encryption(), "EventActionArn" => String.t(), - "RevisionDestinations" => list(revision_destination_entry()()) + "RevisionDestinations" => list(revision_destination_entry()) } """ @@ -250,7 +250,7 @@ defmodule AWS.DataExchange do optional("Arn") => String.t(), optional("CreatedAt") => non_neg_integer(), optional("Details") => response_details(), - optional("Errors") => list(job_error()()), + optional("Errors") => list(job_error()), optional("Id") => String.t(), optional("State") => String.t(), optional("Type") => String.t(), @@ -300,7 +300,7 @@ defmodule AWS.DataExchange do ## Example: list_received_data_grants_response() :: %{ - "DataGrantSummaries" => list(received_data_grant_summaries_entry()()), + "DataGrantSummaries" => list(received_data_grant_summaries_entry()), "NextToken" => String.t() } @@ -475,7 +475,7 @@ defmodule AWS.DataExchange do ## Example: list_jobs_response() :: %{ - optional("Jobs") => list(job_entry()()), + optional("Jobs") => list(job_entry()), optional("NextToken") => String.t() } @@ -499,7 +499,7 @@ defmodule AWS.DataExchange do ## Example: untag_resource_request() :: %{ - required("TagKeys") => list(String.t()()) + required("TagKeys") => list(String.t()) } """ @@ -510,8 +510,8 @@ defmodule AWS.DataExchange do ## Example: database_l_f_tag_policy_and_permissions() :: %{ - "Expression" => list(l_f_tag()()), - "Permissions" => list(String.t()()) + "Expression" => list(l_f_tag()), + "Permissions" => list(String.t()) } """ @@ -689,7 +689,7 @@ defmodule AWS.DataExchange do list_data_set_revisions_response() :: %{ optional("NextToken") => String.t(), - optional("Revisions") => list(revision_entry()()) + optional("Revisions") => list(revision_entry()) } """ @@ -782,8 +782,8 @@ defmodule AWS.DataExchange do ## Example: table_l_f_tag_policy_and_permissions() :: %{ - "Expression" => list(l_f_tag()()), - "Permissions" => list(String.t()()) + "Expression" => list(l_f_tag()), + "Permissions" => list(String.t()) } """ @@ -794,7 +794,7 @@ defmodule AWS.DataExchange do ## Example: export_assets_to_s3_request_details() :: %{ - "AssetDestinations" => list(asset_destination_entry()()), + "AssetDestinations" => list(asset_destination_entry()), "DataSetId" => String.t(), "Encryption" => export_server_side_encryption(), "RevisionId" => String.t() @@ -845,7 +845,7 @@ defmodule AWS.DataExchange do ## Example: export_assets_to_s3_response_details() :: %{ - "AssetDestinations" => list(asset_destination_entry()()), + "AssetDestinations" => list(asset_destination_entry()), "DataSetId" => String.t(), "Encryption" => export_server_side_encryption(), "RevisionId" => String.t() @@ -859,7 +859,7 @@ defmodule AWS.DataExchange do ## Example: list_revision_assets_response() :: %{ - optional("Assets") => list(asset_entry()()), + optional("Assets") => list(asset_entry()), optional("NextToken") => String.t() } @@ -872,7 +872,7 @@ defmodule AWS.DataExchange do details() :: %{ "ImportAssetFromSignedUrlJobErrorDetails" => import_asset_from_signed_url_job_error_details(), - "ImportAssetsFromS3JobErrorDetails" => list(asset_source_entry()()) + "ImportAssetsFromS3JobErrorDetails" => list(asset_source_entry()) } """ @@ -930,7 +930,7 @@ defmodule AWS.DataExchange do ## Example: schema_change_request_details() :: %{ - "Changes" => list(schema_change_details()()), + "Changes" => list(schema_change_details()), "SchemaChangeAt" => non_neg_integer() } @@ -963,7 +963,7 @@ defmodule AWS.DataExchange do ## Example: database_l_f_tag_policy() :: %{ - "Expression" => list(l_f_tag()()) + "Expression" => list(l_f_tag()) } """ @@ -975,9 +975,9 @@ defmodule AWS.DataExchange do s3_data_access_asset() :: %{ "Bucket" => String.t(), - "KeyPrefixes" => list(String.t()()), - "Keys" => list(String.t()()), - "KmsKeysToGrant" => list(kms_key_to_grant()()), + "KeyPrefixes" => list(String.t()), + "Keys" => list(String.t()), + "KmsKeysToGrant" => list(kms_key_to_grant()), "S3AccessPointAlias" => String.t(), "S3AccessPointArn" => String.t() } @@ -1012,7 +1012,7 @@ defmodule AWS.DataExchange do ## Example: table_l_f_tag_policy() :: %{ - "Expression" => list(l_f_tag()()) + "Expression" => list(l_f_tag()) } """ @@ -1100,9 +1100,9 @@ defmodule AWS.DataExchange do s3_data_access_asset_source_entry() :: %{ "Bucket" => String.t(), - "KeyPrefixes" => list(String.t()()), - "Keys" => list(String.t()()), - "KmsKeysToGrant" => list(kms_key_to_grant()()) + "KeyPrefixes" => list(String.t()), + "Keys" => list(String.t()), + "KmsKeysToGrant" => list(kms_key_to_grant()) } """ @@ -1251,8 +1251,8 @@ defmodule AWS.DataExchange do ## Example: s3_data_access_details() :: %{ - "KeyPrefixes" => list(String.t()()), - "Keys" => list(String.t()()) + "KeyPrefixes" => list(String.t()), + "Keys" => list(String.t()) } """ @@ -1300,7 +1300,7 @@ defmodule AWS.DataExchange do ## Example: import_assets_from_s3_response_details() :: %{ - "AssetSources" => list(asset_source_entry()()), + "AssetSources" => list(asset_source_entry()), "DataSetId" => String.t(), "RevisionId" => String.t() } @@ -1322,7 +1322,7 @@ defmodule AWS.DataExchange do ## Example: import_assets_from_redshift_data_shares_request_details() :: %{ - "AssetSources" => list(redshift_data_share_asset_source_entry()()), + "AssetSources" => list(redshift_data_share_asset_source_entry()), "DataSetId" => String.t(), "RevisionId" => String.t() } @@ -1368,7 +1368,7 @@ defmodule AWS.DataExchange do ## Example: import_assets_from_redshift_data_shares_response_details() :: %{ - "AssetSources" => list(redshift_data_share_asset_source_entry()()), + "AssetSources" => list(redshift_data_share_asset_source_entry()), "DataSetId" => String.t(), "RevisionId" => String.t() } @@ -1430,7 +1430,7 @@ defmodule AWS.DataExchange do optional("Arn") => String.t(), optional("CreatedAt") => non_neg_integer(), optional("Details") => response_details(), - optional("Errors") => list(job_error()()), + optional("Errors") => list(job_error()), optional("Id") => String.t(), optional("State") => String.t(), optional("Type") => String.t(), @@ -1613,7 +1613,7 @@ defmodule AWS.DataExchange do ## Example: import_assets_from_s3_request_details() :: %{ - "AssetSources" => list(asset_source_entry()()), + "AssetSources" => list(asset_source_entry()), "DataSetId" => String.t(), "RevisionId" => String.t() } @@ -1628,7 +1628,7 @@ defmodule AWS.DataExchange do lake_formation_data_permission_asset() :: %{ "LakeFormationDataPermissionDetails" => lake_formation_data_permission_details(), "LakeFormationDataPermissionType" => String.t(), - "Permissions" => list(String.t()()), + "Permissions" => list(String.t()), "RoleArn" => String.t() } @@ -1653,7 +1653,7 @@ defmodule AWS.DataExchange do ## Example: list_data_grants_response() :: %{ - "DataGrantSummaries" => list(data_grant_summary_entry()()), + "DataGrantSummaries" => list(data_grant_summary_entry()), "NextToken" => String.t() } @@ -1715,7 +1715,7 @@ defmodule AWS.DataExchange do ## Example: list_event_actions_response() :: %{ - optional("EventActions") => list(event_action_entry()()), + optional("EventActions") => list(event_action_entry()), optional("NextToken") => String.t() } @@ -1749,7 +1749,7 @@ defmodule AWS.DataExchange do "Arn" => String.t(), "CreatedAt" => non_neg_integer(), "Details" => response_details(), - "Errors" => list(job_error()()), + "Errors" => list(job_error()), "Id" => String.t(), "State" => String.t(), "Type" => String.t(), @@ -1875,7 +1875,7 @@ defmodule AWS.DataExchange do export_revisions_to_s3_request_details() :: %{ "DataSetId" => String.t(), "Encryption" => export_server_side_encryption(), - "RevisionDestinations" => list(revision_destination_entry()()) + "RevisionDestinations" => list(revision_destination_entry()) } """ From 3dc5cffa64c21229130cd28f4fc1fbe24168671f Mon Sep 17 00:00:00 2001 From: Onno Vos Date: Mon, 14 Jul 2025 09:01:29 +0200 Subject: [PATCH 3/5] Test bumping pipeline deps --- .github/workflows/gen_elixir.yml | 6 +++--- .github/workflows/gen_erlang.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/gen_elixir.yml b/.github/workflows/gen_elixir.yml index 1db860c..2a9f014 100644 --- a/.github/workflows/gen_elixir.yml +++ b/.github/workflows/gen_elixir.yml @@ -15,8 +15,8 @@ jobs: strategy: fail-fast: false matrix: - elixir: ["1.13.4"] - erlang: ["25.0.4"] + elixir: ["1.18.3"] + erlang: ["27.3.3"] steps: - uses: actions/checkout@v2 @@ -51,4 +51,4 @@ jobs: run: | mix deps.get mix test - working-directory: aws-beam/aws-elixir \ No newline at end of file + working-directory: aws-beam/aws-elixir diff --git a/.github/workflows/gen_erlang.yml b/.github/workflows/gen_erlang.yml index 4b438d4..83e8f5a 100644 --- a/.github/workflows/gen_erlang.yml +++ b/.github/workflows/gen_erlang.yml @@ -12,9 +12,9 @@ jobs: strategy: matrix: platform: [ubuntu-latest] - elixir: ["1.13.4"] - erlang: ["25.0.4"] - rebar3: ['3.20.0'] + elixir: ["1.18.3"] + erlang: ["27.3.3"] + rebar3: ["3.25.0"] runs-on: ${{ matrix.platform }} services: ddb: From 63d8c3427fe40551eec0818e6be7caad52ce3b7c Mon Sep 17 00:00:00 2001 From: Onno Vos Date: Mon, 14 Jul 2025 09:21:26 +0200 Subject: [PATCH 4/5] Bump s3mock container --- .github/workflows/gen_erlang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gen_erlang.yml b/.github/workflows/gen_erlang.yml index 83e8f5a..1fae46d 100644 --- a/.github/workflows/gen_erlang.yml +++ b/.github/workflows/gen_erlang.yml @@ -22,7 +22,7 @@ jobs: ports: - 8000:8000 s3mock: - image: adobe/s3mock:2.11.0 + image: adobe/s3mock:4.6.0 ports: - 9090:9090 steps: From 8dabf83eac2cd31a5e584d8b0eab60c51f0ca92f Mon Sep 17 00:00:00 2001 From: Onno Vos Date: Mon, 14 Jul 2025 09:38:57 +0200 Subject: [PATCH 5/5] Try OTP 26 which works locally --- .github/workflows/gen_erlang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gen_erlang.yml b/.github/workflows/gen_erlang.yml index 1fae46d..c2cb025 100644 --- a/.github/workflows/gen_erlang.yml +++ b/.github/workflows/gen_erlang.yml @@ -13,7 +13,7 @@ jobs: matrix: platform: [ubuntu-latest] elixir: ["1.18.3"] - erlang: ["27.3.3"] + erlang: ["26"] rebar3: ["3.25.0"] runs-on: ${{ matrix.platform }} services: