From 0f32a0e0fe8ff24f9ecb60ac4a406a8a264f0d96 Mon Sep 17 00:00:00 2001 From: Sean Holung Date: Wed, 8 May 2024 13:57:46 -0400 Subject: [PATCH] add programs and content scripts (#11419) --- Makefile | 36 ++++++- scripts/content/new-example-program.sh | 99 +++++++++++++++++++ scripts/content/new-learn-module.sh | 49 +++++++++ scripts/content/new-learn-topic.sh | 47 +++++++++ scripts/content/new-template.sh | 58 +++++++++++ scripts/programs/common.sh | 32 ++++++ scripts/programs/test.sh | 132 +++++++++++++++++++++++++ scripts/programs/upgrade.sh | 38 +++++++ 8 files changed, 490 insertions(+), 1 deletion(-) create mode 100755 scripts/content/new-example-program.sh create mode 100755 scripts/content/new-learn-module.sh create mode 100755 scripts/content/new-learn-topic.sh create mode 100755 scripts/content/new-template.sh create mode 100755 scripts/programs/common.sh create mode 100755 scripts/programs/test.sh create mode 100755 scripts/programs/upgrade.sh diff --git a/Makefile b/Makefile index 011def1b9095a..b9ec118c9267e 100644 --- a/Makefile +++ b/Makefile @@ -96,4 +96,38 @@ serve-all: .PHONY: build-assets build-assets: - yarn --cwd ./theme run build \ No newline at end of file + yarn --cwd ./theme run build + +.PHONY: test +test: + $(MAKE) test-programs + +.PHONY: test-programs +test-programs: + ./scripts/programs/test.sh preview + +.PHONY: upgrade-programs +upgrade-programs: + ./scripts/programs/upgrade.sh + +.PHONY: new-learn-module +new-learn-module: + ./scripts/content/new-learn-module.sh + +.PHONY: new-learn-topic +new-learn-topic: + ./scripts/content/new-learn-topic.sh + +.PHONY: new-template +new-template: + ./scripts/content/new-template.sh + +.PHONY: new-example-program +new-example-program: + ./scripts/content/new-example-program.sh + +.PHONY: new-blog-post +new-blog-post: + hugo new --kind blog-post --contentDir content \ + "blog/$(shell bash -c 'read -p "Slug (e.g., 'my-new-post'): " slug; echo $$slug')" + diff --git a/scripts/content/new-example-program.sh b/scripts/content/new-example-program.sh new file mode 100755 index 0000000000000..87c52aec81dce --- /dev/null +++ b/scripts/content/new-example-program.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +set -o errexit -o pipefail + +source ./scripts/common.sh +source ./scripts/programs/common.sh + +cloud="" +example_name="" +example_description="" +examples_dir="static/programs" + +prompt_for_cloud() { + read -p "Cloud (e.g., aws): " cloud + + if [[ ! -z "$cloud" ]]; then + return + fi + + echo "Enter a cloud name that exists in pulumi/templates, like 'aws-native' or 'scaleway'." + echo + prompt_for_cloud +} + +prompt_for_example_name() { + read -p "Example name (e.g., awsx-apigateway-lambda): " example_name + + if [ ! -z "$example_name" ]; then + return + fi + + echo "Please give the example a name." + prompt_for_example_name +} + +prompt_for_example_description() { + read -p "Example description (e.g., 'An example that deploys an API Gateway REST API on AWS.'): " example_description + + if [ ! -z "$example_description" ]; then + return + fi + + echo "Please give the example a description." + prompt_for_example_description +} + +generate_example() { + languages=(javascript typescript python go csharp java yaml) + echo + + for language in "${languages[@]}"; do + example_dir="${examples_dir}/${example_name}-${language}" + + rm -rf "${example_dir}" + mkdir -p "${example_dir}" + + pushd "$example_dir" > /dev/null + echo "Creating ${example_dir} ..." + pulumi new "${cloud}-${language}" --description="${example_description}" --yes --force --generate-only > /dev/null + pulumi install > /dev/null + popd > /dev/null + done + + unsuffix_gomods +} + +echo +echo "So, you want to make a new example program? Awesome! 🙌" +echo +echo "Step 1: Choose a cloud. Your example will be built from an existing Pulumi template, +so choose a cloud/provider that we have an existing - template for, like +'aws', 'azure', 'gcp', or 'digitalocean'." +echo +prompt_for_cloud + +echo +echo "Step 2: Give the example a descriptive, Pulumi project-friendly name. This name will +be used for the project prefix. Try to choose a name that succinctly describes the content +of the example, rather than the specific page you're building it for, as this'll make the +example more easily findable and reusable." +echo +prompt_for_example_name + +echo +echo "Step 3: Give the example a project description. This will be used for the description +field in Pulumi.yaml." +echo +prompt_for_example_description + +generate_example +echo +echo "✨ Done! Your new projects are now available at ${examples_dir}/${example_name}. To +include them in any Markdown file (blog post, doc, whatever), use the '{{< example-program >}}' +shortcode thusly: + +{{< example-program path=\"${example_name}\" >}} + +Enjoy!" +echo diff --git a/scripts/content/new-learn-module.sh b/scripts/content/new-learn-module.sh new file mode 100755 index 0000000000000..7cf18837181e3 --- /dev/null +++ b/scripts/content/new-learn-module.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -o errexit -o pipefail + +module="" +topic="" + +content_dir="content" + +prompt_for_module_name() { + read -p "Module name (e.g., pulumi-101-aws): " module + + if [ ! -z "$module" ]; then + hugo new --kind learn/module --contentDir "${content_dir}" "learn/${module}" + return + fi + + echo "Please give the module a name." + prompt_for_module_name +} + +prompt_for_topic_name() { + read -p "Topic name (e.g., basics): " topic + + if [ ! -z "$topic" ]; then + hugo new --kind learn/topic --contentDir "${content_dir}" "learn/${module}/${topic}" + return + fi + + echo "Please give the topic a name." + prompt_for_topic_name +} + +echo "So, you want to make a new Learn Pulumi module? Awesome! 🙌" +echo +echo "Step 1:" +echo "First, give the module a URL- and SEO-friendly name. +For example, to create a new module that'll live at +https://pulumi.com/learn/pulumi-101, type 'pulumi-101'." +echo +prompt_for_module_name + +echo +echo "Step 2:" +echo "Now give your new module at least one new topic, also expressed +as a URL-friendly name. For example, to create a new topic under ${module} +that'll live at https://pulumi.com/learn/${module}/basics, type 'basics'." +echo +prompt_for_topic_name diff --git a/scripts/content/new-learn-topic.sh b/scripts/content/new-learn-topic.sh new file mode 100755 index 0000000000000..610a5a75b8331 --- /dev/null +++ b/scripts/content/new-learn-topic.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +set -o errexit -o pipefail + +module="" +topic="" +content_dir="content" + +prompt_for_module_name() { + read -p "Module name (e.g., pulumi-101-aws): " module + + if [[ ! -z "$module" && -d "${content_dir}/learn/${module}" ]]; then + return + fi + + echo "Couldn't find a module with that name. Make sure you're using the path as listed under content/learn." + echo + prompt_for_module_name +} + +prompt_for_topic_name() { + read -p "Topic name (e.g., basics): " topic + + if [ ! -z "$topic" ]; then + hugo new --kind learn/topic --contentDir "${content_dir}" "learn/${module}/${topic}" + return + fi + + echo "Please give the topic a name." + echo + prompt_for_topic_name +} + +echo "So, you want to make a new Learn Pulumi topic? Great! 🙌" +echo +echo "Step 1:" +echo "What is the path name of the module you want to write for?" +echo +prompt_for_module_name + +echo +echo "Step 2:" +echo "Now give your new topic a URL-friendly name. For example, to +create a new topic under ${module} that'll live at +https://pulumi.com/learn/${module}/basics, type 'basics'." +echo +prompt_for_topic_name diff --git a/scripts/content/new-template.sh b/scripts/content/new-template.sh new file mode 100755 index 0000000000000..6c713865ec40c --- /dev/null +++ b/scripts/content/new-template.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -o errexit -o pipefail + +type="" +template="" +content_dir="content" + +prompt_for_template_type() { + read -p "Template type (e.g., static-website): " type + + if [[ ! -z "$type" && -d "${content_dir}/templates/${type}" ]]; then + return + fi + + create_template_type +} + +create_template_type() { + echo + read -e -p "Template type '${type}' doesn't exist in '${content_dir}/templates'. Create it [y/n]? " choice + + if [[ "$choice" == [Yy]* ]]; then + hugo new --kind templates/type --contentDir "${content_dir}" "templates/${type}" + return + fi + + echo "Ok, exiting." + exit 0 +} + +prompt_for_template_name() { + read -p "Template name (e.g., azure): " template + + if [ ! -z "$template" ]; then + hugo new --kind templates/template --contentDir "${content_dir}" "templates/${type}/${template}" + return + fi + + echo "Please give the template a name." + echo + prompt_for_template_name +} + +echo "So, you want to make a new Pulumi template? Great! 🙌" +echo +echo "Step 1:" +echo "What type of template would you like to create?" +echo +prompt_for_template_type + +echo +echo "Step 2:" +echo "Now give your new template a URL-friendly name. For example, to +create a new template under ${type} that'll live at +https://pulumi.com/templates/${type}/azure, type 'azure'." +echo +prompt_for_template_name && echo && echo "Done! You can now run 'make serve' to get started." diff --git a/scripts/programs/common.sh b/scripts/programs/common.sh new file mode 100755 index 0000000000000..0aae44798421e --- /dev/null +++ b/scripts/programs/common.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +suffix_gomods() { + for file in $(find ./static/programs/* -name 'go.mod' -not -path "**/node_modules/**") + do + cp $file $(echo "$file" | sed -r 's|.mod|.mod.txt|g') + done +} + +unsuffix_gomods() { + for file in $(find ./static/programs/* -name 'go.mod.txt' -not -path "**/node_modules/**" ) + do + cp $file $(echo "$file" | sed -r 's|.mod.txt|.mod|g') + done +} + +clean_gomods() { + local requires=0 + local i=0 + + for file in $(find ./static/programs/* -name 'go.mod*' -not -path "**/node_modules/**" ) + do + new_file="$(cat $file)" + split_at="$(awk '/require/{i++; if (i==2) { print NR-1; exit }}' $file)" + + if [[ "$split_at" != "" ]]; then + new_file="$(cat $file | head -n $split_at)" + fi + + echo "$new_file" > "$file" + done +} diff --git a/scripts/programs/test.sh b/scripts/programs/test.sh new file mode 100755 index 0000000000000..aa7a3badcf887 --- /dev/null +++ b/scripts/programs/test.sh @@ -0,0 +1,132 @@ +#!/bin/bash + +set -o errexit -o pipefail + +source ./scripts/programs/common.sh + +programs_dir="static/programs" + +# Delete install artifacts, but leave existing go.mod files. +git clean -fdX -e '!go.mod' "${programs_dir}/*" + +# Fix up go.mod files. +clean_gomods +unsuffix_gomods + +# By default, only run previews. +mode="${1:-preview}" + +# If we're only running previews, just use local mode -- it's faster. +if [[ "$mode" == "preview" ]]; then + org="organization" + export PULUMI_CONFIG_PASSPHRASE="foo" + pulumi login --local +else + org="$(pulumi whoami -v --json | jq -r .user)" +fi + +pushd "$programs_dir" + found_first_program=false + + for dir in */; do + project="$(basename $dir)" + + # Optionally test only selected examples by setting an ONLY_TEST="" + # environment variable (e.g., ONLY_TEST="awsx-ecr-repository"). + if [[ ! -z "$ONLY_TEST" && "$project" != "$ONLY_TEST"* ]]; then + continue + fi + + # Optionally test only from the specified example forward by setting ONLY_TEST_FROM="". + if [[ ! -z "$ONLY_TEST_FROM" ]]; then + if [[ "$project" == "$ONLY_TEST_FROM"* && "$found_first_program" == false ]]; then + found_first_program=true + fi + + if [ "$found_first_program" == false ]; then + continue + fi + fi + + # Skip programs we know don't compile. + + # API Gateway authorizer parameter `providerArns` is mistyped. + # https://github.com/pulumi/pulumi-aws-apigateway/issues/121 + if [[ "$project" == "awsx-apigateway-auth-cognito-java" ]]; then + continue + fi + + echo + echo "***" + echo "* $project" + echo "***" + echo + + stack="dev" + fqsn="${org}/${project}/${stack}" + + # Install dependencies. + pulumi -C "$project" install + + # Skip programs we know don't successfully preview. + + # Java examples of FargateService erroneously complain about missing container declarations. + # https://github.com/pulumi/pulumi-awsx/issues/820 + if [[ "$project" == "awsx-vpc-fargate-service-java" ]]; then + continue + elif [[ "$project" == "awsx-load-balanced-fargate-ecr-java" ]]; then + continue + elif [[ "$project" == "awsx-load-balanced-fargate-nginx-java" ]]; then + continue + fi + + # Custom-domain examples won't work because of the hosted-zone lookup (which will fail unless + # the credentials can access the specified Route 53 zone). + if [[ "$project" == "awsx-apigateway-custom-domain-"* ]]; then + continue + fi + + # Destroy any existing stacks. + pulumi -C "$project" cancel --stack $fqsn --yes || true + pulumi -C "$project" destroy --stack $fqsn --yes --refresh --remove || true + + # Create a new stack. + pulumi -C "$project" stack select $fqsn || pulumi -C "$project" stack init $fqsn + pulumi -C "$project" config set aws:region us-west-2 || true + + # Preview or deploy. + if [[ "$mode" == "update" ]]; then + + # Skip programs we know don't successfully update. + + # Error converting 'java.util.Collections$UnmodifiableRandomAccessList' to 'TypeShape{type=interface java.util.List, parameters=[TypeShape{type=class com.pulumi.aws.lb.outputs.TargetGroupTargetHealthState, parameters=[]}]}'. + # https://github.com/pulumi/pulumi-java/issues/1276 + if [[ "$project" == "awsx-elb-web-listener-java" ]]; then + continue + elif [[ "$project" == "awsx-elb-multi-listener-redirect-java" ]]; then + continue + elif [[ "$project" == "awsx-load-balanced-ec2-instances-java" ]]; then + continue + fi + + pulumi -C "$project" up --yes + else + pulumi -C "$project" preview + fi + + # Destroy and remove. + pulumi -C "$project" destroy --yes --remove + + # Clean up artifacts. + git clean -fdX -e '!go.mod' . + done +popd + +clean_gomods +suffix_gomods + +# Log out of local mode. +if [[ "$mode" == "preview" ]]; then + unset PULUMI_CONFIG_PASSPHRASE + pulumi logout --local +fi diff --git a/scripts/programs/upgrade.sh b/scripts/programs/upgrade.sh new file mode 100755 index 0000000000000..bb020503e7196 --- /dev/null +++ b/scripts/programs/upgrade.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -o errexit -o pipefail + +source ./scripts/programs/common.sh + +programs_dir="static/programs" + +# Delete install artifacts, but leave existing go.mod files. +git clean -fdX -e '!go.mod' "${programs_dir}/*" + +# Fix up go.mod files. +clean_gomods +unsuffix_gomods + +pushd "$programs_dir" + for dir in */; do + project="$(basename $dir)" + + echo + echo "***" + echo "* $project" + echo "***" + echo + + pushd "$project" + + if [[ "$project" == *"-go" && -e "go.mod" ]]; then + go get -u + go mod tidy + fi + + popd + done +popd + +clean_gomods +suffix_gomods