aws-lambda-layer-cli 2.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,10 +4,10 @@ A command-line tool for creating and publishing AWS Lambda layers for Node.js an
4
4
 
5
5
  ## Features
6
6
 
7
- - Create and publish Lambda layers for Node.js (npm) and Python (pip)
8
- - Automatic version management and smart naming
9
- - Direct publishing to AWS with IAM credentials and region support
10
- - Support for multiple packages in a single layer
7
+ - **Effortless Publishing**: Create and publish Node.js and Python layers in a single command
8
+ - **Smart Compatibility**: Auto-selects the right Linux binaries for Amazon Linux 2 or 2023
9
+ - **Cross-Architecture**: Native support for `x86_64` and `arm64` builds
10
+ - **Auto-Versioning**: Automatically handles layer naming and version increments
11
11
 
12
12
  ## Installation
13
13
 
@@ -46,12 +46,12 @@ aws-lambda-layer-cli <command> [options]
46
46
  |--------|-------------|
47
47
  | `--nodejs, -n <pkgs>` | Create Node.js layer (comma-separated packages) |
48
48
  | `--python, -p <pkgs>` | Create Python layer (comma-separated packages) |
49
+ | `--wheel, -w <file>` | Use with `--python` to create layer from `.whl` file |
49
50
  | `--name` | Custom layer name |
50
51
  | `--description` | Layer description (publish only) |
51
52
  | `--profile` | AWS CLI profile (publish only) |
52
53
  | `--region` | AWS region (publish only) |
53
54
  | `--architecture, -a` | Target architecture (`x86_64` or `arm64`) |
54
- | `--platform` | Target platform tag (Python only, e.g. `manylinux_2_28_aarch64`) |
55
55
  | `--node-version` | Node.js version (default: 24) |
56
56
  | `--python-version` | Python version (default: 3.14) |
57
57
  | `-v, --version` | Show version |
@@ -72,9 +72,23 @@ aws-lambda-layer-cli publish --nodejs lodash --profile prod --region us-east-1 -
72
72
  # Create local zip with specific python version and architecture
73
73
  aws-lambda-layer-cli zip --python numpy==1.26.0,pandas --python-version 3.12 --architecture arm64
74
74
 
75
- # Publish to AWS with explicit platform tag (e.g. Amazon Linux 2023 / manylinux_2_28)
76
- aws-lambda-layer-cli publish --python requests --name web-layer --platform manylinux_2_28_x86_64
75
+ # Publish to AWS for ARM64 architecture
76
+ aws-lambda-layer-cli publish --python requests --name web-layer --architecture arm64
77
77
  ```
78
+ > **Note**: This tool automatically selects the optimal platform based on the Python version:
79
+ > - **Python 3.12+ (Amazon Linux 2023)**: Targets `manylinux_2_28` (GLIBC 2.28+)
80
+ > - **Python 3.11- (Amazon Linux 2)**: Targets `manylinux2014` (GLIBC 2.17+)
81
+
82
+ ### Wheel File
83
+ The tool auto-detects Python version and architecture from the wheel filename.
84
+ ```bash
85
+ # Create local zip from wheel (preferred syntax)
86
+ aws-lambda-layer-cli zip --python --wheel numpy-2.4.1-cp313-cp313-manylinux.whl
87
+
88
+ # Publish directly from wheel
89
+ aws-lambda-layer-cli publish --python --wheel pandas-2.1.0-cp311-...-x86_64.whl
90
+ ```
91
+ > **Note**: For wheels, arguments like `--python-version` or `--architecture` are checked against the wheel metadata. If they conflict, the tool will error to prevent incompatibility.
78
92
 
79
93
  ## Shell Completion
80
94
 
@@ -13,7 +13,7 @@ _aws_lambda_layer_cli() {
13
13
  local common_opts="--name -h --help"
14
14
  local publish_opts="--description --layer-name --profile --region"
15
15
  local node_opts="--node-version"
16
- local python_opts="--python-version --no-uv"
16
+ local python_opts="--python-version --platform"
17
17
 
18
18
  case ${cword} in
19
19
  1)
@@ -40,7 +40,7 @@ _aws-lambda-layer-cli() {
40
40
 
41
41
  python_opts=(
42
42
  '--python-version:version:'
43
- '--no-uv'
43
+ '--platform:platform:'
44
44
  )
45
45
 
46
46
  _arguments -C \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aws-lambda-layer-cli",
3
- "version": "2.1.3",
3
+ "version": "2.2.0",
4
4
  "description": "CLI tool for creating and publishing AWS Lambda layers for Node.js and Python.",
5
5
  "keywords": [
6
6
  "aws",
@@ -41,13 +41,19 @@ else
41
41
  PYTHON_SCRIPT="$INSTALL_DIR/create_python_layer.sh"
42
42
  fi
43
43
 
44
+ if [ -f "$SCRIPT_DIR/create_wheel_layer.sh" ]; then
45
+ WHEEL_SCRIPT="$SCRIPT_DIR/create_wheel_layer.sh"
46
+ else
47
+ WHEEL_SCRIPT="$INSTALL_DIR/create_wheel_layer.sh"
48
+ fi
49
+
44
50
  BIN_DIR="/usr/local/bin"
45
51
  COMPLETION_DIR="/etc/bash_completion.d"
46
52
 
47
53
  # Show help
48
54
  show_help() {
49
55
  local version_file="$SCRIPT_DIR/VERSION.txt"
50
- local version="2.1.3"
56
+ local version="2.2.0"
51
57
  if [ -f "$version_file" ]; then
52
58
  version=$(cat "$version_file")
53
59
  fi
@@ -56,8 +62,10 @@ show_help() {
56
62
  printf "${BLUE}Usage:${NC}\n"
57
63
  printf " aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--nodejs${NC} <packages> [options]\n"
58
64
  printf " aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--python${NC} <packages> [options]\n"
65
+ printf " aws-lambda-layer-cli ${GREEN}zip${NC} ${YELLOW}--python --wheel${NC} <wheel_file> [options]\n"
59
66
  printf " aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--nodejs${NC} <packages> [options]\n"
60
67
  printf " aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--python${NC} <packages> [options]\n"
68
+ printf " aws-lambda-layer-cli ${GREEN}publish${NC} ${YELLOW}--python --wheel${NC} <wheel_file> [options]\n"
61
69
  printf " aws-lambda-layer-cli ${GREEN}help${NC}\n"
62
70
  printf " aws-lambda-layer-cli [options]\n\n"
63
71
 
@@ -72,8 +80,11 @@ show_help() {
72
80
  printf " ${YELLOW}--nodejs, --node, -n${NC} Create a Node.js Lambda layer\n"
73
81
  printf " ${YELLOW}--python, --py, -p${NC} Create a Python Lambda layer\n"
74
82
  printf " ${YELLOW}--runtime=RUNTIME${NC} Specify runtime (nodejs or python)\n"
83
+ printf "${BLUE}Source Options (Python only):${NC}\n"
84
+ printf " ${YELLOW}--wheel, -w${NC} Create layer from existing Wheel file\n"
75
85
  printf "${BLUE}Arguments:${NC}\n"
76
- printf " <packages> Comma-separated list of packages with optional versions (required)\n"
86
+ printf " <packages> Comma-separated list of packages\n"
87
+ printf " <wheel_file> Path to a local .whl file (use with --python --wheel)\n"
77
88
 
78
89
  printf "${BLUE}Common Options:${NC}\n"
79
90
  printf " ${YELLOW}--name${NC} Name for the output zip file / layer name\n"
@@ -85,8 +96,7 @@ show_help() {
85
96
  printf " ${YELLOW}--version, -v${NC} Show tool version information\n"
86
97
  printf " ${YELLOW}--node-version${NC} Node.js version (default: 24)\n"
87
98
  printf " ${YELLOW}--python-version${NC} Python version (default: 3.14)\n"
88
- printf " ${YELLOW}--architecture, -a${NC} Target architecture (x86_64, arm64)\n"
89
- printf " ${YELLOW}--platform${NC} Target platform tag (Python only)\n\n"
99
+ printf " ${YELLOW}--architecture, -a${NC} Target architecture (x86_64, arm64)\n\n"
90
100
 
91
101
  printf "${MAGENTA}${UNDERLINE}Package Version Examples:${NC}\n"
92
102
  printf " Node.js: express@^4.0.0, lodash@~4.17.0, axios@>=1.6.0\n"
@@ -114,7 +124,7 @@ show_version() {
114
124
  echo "v$version"
115
125
  else
116
126
  # Fallback if VERSION file is missing (e.g. during development or if moved)
117
- echo "v2.1.3"
127
+ echo "v2.2.0"
118
128
  fi
119
129
  }
120
130
 
@@ -249,25 +259,6 @@ get_aws_account_info() {
249
259
  esac
250
260
  }
251
261
 
252
- # Determine compatible runtimes for AWS
253
- get_compatible_runtimes() {
254
- local runtime="$1"
255
- local version="2.1.3"
256
-
257
- case "$runtime" in
258
- nodejs)
259
- echo "nodejs${version}.x"
260
- ;;
261
- python)
262
- # AWS Lambda uses format like python3.14, not python3.14.x
263
- echo "python${version}"
264
- ;;
265
- *)
266
- echo ""
267
- ;;
268
- esac
269
- }
270
-
271
262
  # Check dependencies
272
263
  check_dependencies() {
273
264
  local runtime="$1"
@@ -317,6 +308,7 @@ check_dependencies() {
317
308
  # Zip command handler - creates local zip files
318
309
  handle_zip() {
319
310
  local runtime=""
311
+ local is_wheel=false
320
312
  local packages=""
321
313
 
322
314
  # Parse runtime flag
@@ -328,6 +320,10 @@ handle_zip() {
328
320
  --python|--py|-p)
329
321
  runtime="python"
330
322
  shift
323
+ if [[ "${1:-}" == "--wheel" || "${1:-}" == "-w" || "${1:-}" == "--whl" ]]; then
324
+ is_wheel=true
325
+ shift
326
+ fi
331
327
  ;;
332
328
  --runtime=*)
333
329
  runtime="${1#*=}"
@@ -396,7 +392,7 @@ handle_zip() {
396
392
  local current_dir=$(pwd)
397
393
  cd "$output_dir"
398
394
 
399
- # Pass arguments to the appropriate script with -i
395
+ # Pass arguments to the appropriate script
400
396
  if [ "$runtime" = "nodejs" ]; then
401
397
  if [ ! -f "$NODE_SCRIPT" ]; then
402
398
  cd "$current_dir"
@@ -410,23 +406,37 @@ handle_zip() {
410
406
  cd "$current_dir"
411
407
  exit $exit_code
412
408
  elif [ "$runtime" = "python" ]; then
413
- if [ ! -f "$PYTHON_SCRIPT" ]; then
409
+ if [ "$is_wheel" = true ]; then
410
+ if [ ! -f "$WHEEL_SCRIPT" ]; then
411
+ cd "$current_dir"
412
+ printf "${RED}Error: Wheel script not found at $WHEEL_SCRIPT${NC}\n"
413
+ exit 1
414
+ fi
415
+ printf "${BLUE}Creating Lambda layer from Wheel...${NC}\n"
416
+ bash "$WHEEL_SCRIPT" -w "$packages" "$@"
417
+ local exit_code=$?
414
418
  cd "$current_dir"
415
- printf "${RED}Error: Python script not found at $PYTHON_SCRIPT${NC}\n"
416
- printf "Please run scripts/install.sh first\n"
417
- exit 1
419
+ exit $exit_code
420
+ else
421
+ if [ ! -f "$PYTHON_SCRIPT" ]; then
422
+ cd "$current_dir"
423
+ printf "${RED}Error: Python script not found at $PYTHON_SCRIPT${NC}\n"
424
+ printf "Please run scripts/install.sh first\n"
425
+ exit 1
426
+ fi
427
+ printf "${BLUE}Creating Python Lambda layer (local zip)...${NC}\n"
428
+ bash "$PYTHON_SCRIPT" -i "$packages" "$@"
429
+ local exit_code=$?
430
+ cd "$current_dir"
431
+ exit $exit_code
418
432
  fi
419
- printf "${BLUE}Creating Python Lambda layer (local zip)...${NC}\n"
420
- bash "$PYTHON_SCRIPT" -i "$packages" "$@"
421
- local exit_code=$?
422
- cd "$current_dir"
423
- exit $exit_code
424
433
  fi
425
434
  }
426
435
 
427
436
  # Publish command handler - publishes layer directly to AWS
428
437
  handle_publish() {
429
438
  local runtime=""
439
+ local is_wheel=false
430
440
  local description=""
431
441
  local layer_name=""
432
442
  local packages=""
@@ -512,6 +522,11 @@ handle_publish() {
512
522
  --python|--py|-p)
513
523
  runtime="python"
514
524
  shift
525
+ # Check if the next argument is --wheel
526
+ if [[ "${1:-}" == "--wheel" || "${1:-}" == "-w" || "${1:-}" == "--whl" ]]; then
527
+ is_wheel=true
528
+ shift
529
+ fi
515
530
  ;;
516
531
  --runtime=*)
517
532
  runtime="${1#*=}"
@@ -544,14 +559,14 @@ handle_publish() {
544
559
  esac
545
560
  else
546
561
  printf "${RED}Error: --runtime requires an argument${NC}\n"
547
- printf "Example: --runtime=nodejs or --runtime python\n"
562
+ printf "Example: --runtime=nodejs, --runtime python\n"
548
563
  exit 1
549
564
  fi
550
565
  ;;
551
566
  *)
552
567
  printf "${RED}Error: Missing or invalid runtime specification${NC}\n"
553
- printf "Use --nodejs, --node, -n for Node.js or --python, --py, -p for Python\n"
554
- printf "Or use --runtime=nodejs or --runtime=python\n"
568
+ printf "Use --nodejs (-n) or --python (-p)\n"
569
+ printf "Or use --runtime=nodejs, --runtime=python\n"
555
570
  exit 1
556
571
  ;;
557
572
  esac
@@ -561,7 +576,7 @@ handle_publish() {
561
576
  packages="$1"
562
577
  shift
563
578
  else
564
- printf "${RED}Error: Missing packages argument${NC}\n"
579
+ printf "${RED}Error: Missing argument (packages or wheel file)${NC}\n"
565
580
  printf "Usage: aws-lambda-layer publish --nodejs <packages> [options]\n"
566
581
  printf "Example: aws-lambda-layer publish --nodejs express,axios --description \"My layer\"\n"
567
582
  exit 1
@@ -591,7 +606,13 @@ handle_publish() {
591
606
  printf "${BLUE}Building Lambda layer in output directory...${NC}\n"
592
607
 
593
608
  # Build the layer using the appropriate script
594
- local build_args=("-i" "$packages")
609
+ local build_args=()
610
+ if [ "$is_wheel" = true ]; then
611
+ build_args+=("-w" "$packages")
612
+ else
613
+ build_args+=("-i" "$packages")
614
+ fi
615
+
595
616
  if [ -n "$layer_name" ]; then
596
617
  build_args+=("--name" "${layer_name}.zip")
597
618
  fi
@@ -635,37 +656,75 @@ handle_publish() {
635
656
  local compatible_runtimes="nodejs${node_version}.x"
636
657
 
637
658
  elif [ "$runtime" = "python" ]; then
638
- if [ ! -f "$PYTHON_SCRIPT" ]; then
639
- cd "$current_dir"
640
- printf "${RED}Error: Python script not found${NC}\n"
641
- exit 1
642
- fi
643
- bash "$PYTHON_SCRIPT" "${build_args[@]}" 2>&1 | tee build.log
644
-
645
- # Check if build script succeeded
646
- if [ ${PIPESTATUS[0]} -ne 0 ]; then
647
- cd "$current_dir"
648
- printf "${RED}Error: Python layer build failed${NC}\n"
649
- printf "Check build log: $output_dir/build.log\n"
650
- exit 1
651
- fi
652
-
653
- # Extract zip file name from build output (just the filename, not full path)
654
- zip_file=$(grep -o "File: .*\.zip" "build.log" | cut -d' ' -f2 | tail -1)
655
- if [ -n "$zip_file" ]; then
656
- zip_file=$(basename "$zip_file")
659
+ if [ "$is_wheel" = true ]; then
660
+ if [ ! -f "$WHEEL_SCRIPT" ]; then
661
+ cd "$current_dir"
662
+ printf "${RED}Error: Wheel script not found${NC}\n"
663
+ exit 1
664
+ fi
665
+ bash "$WHEEL_SCRIPT" "${build_args[@]}" 2>&1 | tee build.log
666
+
667
+ if [ ${PIPESTATUS[0]} -ne 0 ]; then
668
+ cd "$current_dir"
669
+ printf "${RED}Error: Wheel layer build failed${NC}\n"
670
+ printf "Check build log: $output_dir/build.log\n"
671
+ exit 1
672
+ fi
673
+
674
+ zip_file=$(grep -o "File: .*\.zip" "build.log" | cut -d' ' -f2 | tail -1)
675
+ if [ -n "$zip_file" ]; then
676
+ zip_file=$(basename "$zip_file")
677
+ else
678
+ zip_file=$(find . -maxdepth 1 -name "*.zip" -type f | head -1 | sed 's|^\./||')
679
+ fi
680
+
681
+ local python_version=$(grep "Detected Python: " "build.log" | awk -F': ' '{print $2}' | tail -1)
682
+ if [ -z "$python_version" ]; then python_version="3.12"; fi
683
+ compatible_runtimes="python${python_version}"
684
+
685
+ local detected_arch=$(grep "Detected Architecture: " "build.log" | awk -F': ' '{print $2}' | tail -1)
686
+ if [ -n "$detected_arch" ]; then
687
+ if [ "$detected_arch" = "aarch64" ]; then compatible_architectures="arm64";
688
+ elif [ "$detected_arch" = "x86_64" ]; then compatible_architectures="x86_64";
689
+ fi
690
+ fi
691
+
692
+ if [ -n "${compatible_architectures:-}" ]; then
693
+ printf "${CYAN}Info: Using detected architecture: $compatible_architectures${NC}\n"
694
+ fi
657
695
  else
658
- # Try to find zip file in current directory
659
- zip_file=$(find . -maxdepth 1 -name "*.zip" -type f | head -1 | sed 's|^\./||')
660
- fi
661
-
662
- # Extract Python version for compatible runtimes
663
- # Pattern matches "Python version: X.Y" or "Python Version: X.Y"
664
- local python_version=$(grep -i "Python.*version: [0-9.]*" "build.log" | awk '{print $NF}' | tail -1)
665
- if [ -z "$python_version" ]; then
666
- python_version="3.14"
696
+ if [ ! -f "$PYTHON_SCRIPT" ]; then
697
+ cd "$current_dir"
698
+ printf "${RED}Error: Python script not found${NC}\n"
699
+ exit 1
700
+ fi
701
+ bash "$PYTHON_SCRIPT" "${build_args[@]}" 2>&1 | tee build.log
702
+
703
+ # Check if build script succeeded
704
+ if [ ${PIPESTATUS[0]} -ne 0 ]; then
705
+ cd "$current_dir"
706
+ printf "${RED}Error: Python layer build failed${NC}\n"
707
+ printf "Check build log: $output_dir/build.log\n"
708
+ exit 1
709
+ fi
710
+
711
+ # Extract zip file name from build output (just the filename, not full path)
712
+ zip_file=$(grep -o "File: .*\.zip" "build.log" | cut -d' ' -f2 | tail -1)
713
+ if [ -n "$zip_file" ]; then
714
+ zip_file=$(basename "$zip_file")
715
+ else
716
+ # Try to find zip file in current directory
717
+ zip_file=$(find . -maxdepth 1 -name "*.zip" -type f | head -1 | sed 's|^\./||')
718
+ fi
719
+
720
+ # Extract Python version for compatible runtimes
721
+ # Pattern matches "Python version: X.Y" or "Python Version: X.Y"
722
+ local python_version=$(grep -i "Python.*version: [0-9.]*" "build.log" | awk '{print $NF}' | tail -1)
723
+ if [ -z "$python_version" ]; then
724
+ python_version="3.14"
725
+ fi
726
+ local compatible_runtimes="python${python_version}"
667
727
  fi
668
- local compatible_runtimes="python${python_version}"
669
728
  fi
670
729
 
671
730
  # Check if zip file was created
@@ -681,7 +740,11 @@ handle_publish() {
681
740
  if [ "$runtime" = "nodejs" ]; then
682
741
  packages_info=$(grep -o "Installed packages: .*" "build.log" | cut -d' ' -f3- | tail -1)
683
742
  elif [ "$runtime" = "python" ]; then
684
- packages_info=$(grep -o "Installed packages: .*" "build.log" | cut -d' ' -f3- | tail -1)
743
+ if [ "$is_wheel" = true ]; then
744
+ packages_info=$(basename "$packages")
745
+ else
746
+ packages_info=$(grep -o "Installed packages: .*" "build.log" | cut -d' ' -f3- | tail -1)
747
+ fi
685
748
  fi
686
749
 
687
750
  # Determine layer name - use just the first package name if not specified
@@ -694,7 +757,11 @@ handle_publish() {
694
757
  layer_name=$(echo "$first_package" | sed 's/@[0-9^~<>=].*$//' | sed 's/^@//' | tr '/' '-')
695
758
  else
696
759
  # For Python: remove ==version, >=version, etc.
697
- layer_name=$(echo "$first_package" | sed 's/[=<>~!].*$//')
760
+ if [ "$is_wheel" = true ]; then
761
+ layer_name=$(basename "$first_package" | cut -d'-' -f1)
762
+ else
763
+ layer_name=$(echo "$first_package" | sed 's/[=<>~!].*$//')
764
+ fi
698
765
  fi
699
766
  fi
700
767
 
@@ -750,16 +817,32 @@ handle_publish() {
750
817
  printf " --layer-name \"$layer_name\"\n"
751
818
  printf " --description \"$final_description\"\n"
752
819
  printf " --zip-file \"fileb://$(convert_path "$current_dir/$output_dir/$zip_file")\"\n"
753
- printf " --compatible-runtimes \"$compatible_runtimes\"\n\n"
820
+ printf " --compatible-runtimes \"$compatible_runtimes\"\n"
821
+ if [ -n "${compatible_architectures:-}" ]; then
822
+ printf " --compatible-architectures \"$compatible_architectures\"\n"
823
+ fi
824
+ printf "\n"
754
825
 
826
+ # Build AWS CLI command array
827
+ local publish_cmd=(aws)
828
+ if [ ${#publish_aws_opts[@]} -gt 0 ]; then
829
+ publish_cmd+=("${publish_aws_opts[@]}")
830
+ fi
831
+ publish_cmd+=(lambda publish-layer-version)
832
+ publish_cmd+=(--layer-name "$layer_name")
833
+ publish_cmd+=(--description "$final_description")
834
+ publish_cmd+=(--zip-file "fileb://$(convert_path "$current_dir/$output_dir/$zip_file")")
835
+ publish_cmd+=(--compatible-runtimes "$compatible_runtimes")
836
+
837
+ if [ -n "${compatible_architectures:-}" ]; then
838
+ publish_cmd+=(--compatible-architectures "$compatible_architectures")
839
+ fi
840
+
841
+ publish_cmd+=(--query '[LayerVersionArn, Version, Description]')
842
+ publish_cmd+=(--output table)
843
+
755
844
  # Run AWS CLI command and capture output and exit code
756
- aws ${publish_aws_opts[@]+"${publish_aws_opts[@]}"} lambda publish-layer-version \
757
- --layer-name "$layer_name" \
758
- --description "$final_description" \
759
- --zip-file "fileb://$(convert_path "$current_dir/$output_dir/$zip_file")" \
760
- --compatible-runtimes "$compatible_runtimes" \
761
- --query '[LayerVersionArn, Version, Description]' \
762
- --output table 2>&1 | tee publish.log
845
+ "${publish_cmd[@]}" 2>&1 | tee publish.log
763
846
 
764
847
  local aws_exit_code=${PIPESTATUS[0]}
765
848
 
@@ -25,6 +25,7 @@ cp "$BASE_DIR/VERSION.txt" "$BUILD_DIR/"
25
25
  cp "$BASE_DIR/scripts/aws-lambda-layer-cli" "$ASSETS_DIR/"
26
26
  cp "$BASE_DIR/scripts/create_nodejs_layer.sh" "$ASSETS_DIR/"
27
27
  cp "$BASE_DIR/scripts/create_python_layer.sh" "$ASSETS_DIR/"
28
+ cp "$BASE_DIR/scripts/create_wheel_layer.sh" "$ASSETS_DIR/"
28
29
  cp "$BASE_DIR/scripts/uninstall.sh" "$ASSETS_DIR/"
29
30
 
30
31
  # Copy completion files
@@ -40,6 +41,6 @@ cd "$BASE_DIR"
40
41
  python3 -m build
41
42
 
42
43
  echo "Cleaning up temporary package files..."
43
- # rm -rf "$BUILD_DIR" "$BASE_DIR/aws_lambda_layer_cli.egg-info" "$BASE_DIR/build"
44
+ rm -rf "$BUILD_DIR" "$BASE_DIR/aws_lambda_layer_cli.egg-info" "$BASE_DIR/build"
44
45
 
45
46
  echo "Build complete! Artifacts are in dist/"
@@ -1,10 +1,10 @@
1
1
  #!/bin/bash
2
2
 
3
- # Python Lambda Layer Creator with UV and version specification
3
+ # Python Lambda Layer Creator with version specification
4
4
  # Usage:
5
5
  # ./create_python_layer.sh -i numpy==1.26.0,pandas==2.1.3
6
6
  # ./create_python_layer.sh -i numpy==1.26.0,pandas,boto3==1.34.0 -n my-layer.zip
7
- # ./create_python_layer.sh --packages=requests==2.31.0,boto3 --no-uv
7
+ # ./create_python_layer.sh --packages=requests==2.31.0,boto3
8
8
 
9
9
  set -e # Exit on error
10
10
  set -u # Treat unset variables as errors
@@ -140,20 +140,6 @@ while [[ $# -gt 0 ]]; do
140
140
  validate_python_version "$PYTHON_VERSION"
141
141
  shift
142
142
  ;;
143
- --platform)
144
- if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
145
- PLATFORM="$2"
146
- shift 2
147
- else
148
- printf "${RED}Error: $1 requires an argument${NC}\n"
149
- printf "Example: $1 manylinux_2_28_x86_64\n"
150
- exit 1
151
- fi
152
- ;;
153
- --platform=*)
154
- PLATFORM="${1#*=}"
155
- shift
156
- ;;
157
143
  -a|--architecture)
158
144
  if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
159
145
  ARCHITECTURE="$2"
@@ -180,18 +166,9 @@ Options:
180
166
  -i, --packages Comma-separated list of Python packages (with optional versions)
181
167
  -n, --name Name of the output zip file
182
168
  --python-version Python version (default: 3.14)
183
- --platform Target platform tag (optional, overrides architecture)
184
169
  -a, --architecture Target architecture (x86_64 or arm64, default: x86_64)
185
170
  -h, --help Show this help message
186
171
 
187
- Supported Platforms (optional):
188
- manylinux2014_x86_64 # Amazon Linux 2, RHEL 7+ (older)
189
- manylinux2014_aarch64 # ARM64 architecture
190
- manylinux_2_28_x86_64 # Amazon Linux 2023, RHEL 8+ (newer)
191
- manylinux_2_28_aarch64 # ARM64 with newer glibc
192
- linux_x86_64 # Generic Linux
193
- linux_aarch64 # Generic ARM64 Linux
194
-
195
172
  Version Specification:
196
173
  Package versions can be specified using standard Python version specifiers:
197
174
  numpy==1.26.0 # Exact version
@@ -356,12 +333,18 @@ if [ -z "$PLATFORM" ]; then
356
333
  PY_VER_MAJOR=$(echo "$PYTHON_VERSION" | cut -d. -f1)
357
334
  PY_VER_MINOR=$(echo "$PYTHON_VERSION" | cut -d. -f2)
358
335
 
359
- # Default to manylinux2014 (Amazon Linux 2)
360
- PLATFORM_PREFIX="manylinux2014"
361
-
362
- # Legacy: We previously checked for AL2023 (manylinux_2_28) here, but forcing it
363
- # causes issues with packages like NumPy that publish manylinux2014 or manylinux_2_17 wheels.
364
- # Since AL2023 is backward compatible with manylinux2014, we stick to that for max compatibility.
336
+ # Platform selection based on AWS Lambda Runtime
337
+ if [ "$PY_VER_MAJOR" -eq 3 ] && [ "$PY_VER_MINOR" -ge 12 ]; then
338
+ # Python 3.12+ runs on Amazon Linux 2023 (GLIBC 2.34)
339
+ # We use manylinux_2_28 (GLIBC 2.28) which is well-supported
340
+ PLATFORM_PREFIX="manylinux_2_28"
341
+ printf " Targeting Amazon Linux 2023 (Python $PYTHON_VERSION)\n"
342
+ else
343
+ # Python 3.11- runs on Amazon Linux 2 (GLIBC 2.26)
344
+ # We use manylinux2014 (GLIBC 2.17) for max compatibility
345
+ PLATFORM_PREFIX="manylinux2014"
346
+ printf " Targeting Amazon Linux 2 (Python $PYTHON_VERSION)\n"
347
+ fi
365
348
 
366
349
  PLATFORM="${PLATFORM_PREFIX}_${ARCHITECTURE}"
367
350
  printf "Auto-detected platform: $PLATFORM (Python $PYTHON_VERSION, Arch $ARCHITECTURE)\n"
@@ -393,9 +376,13 @@ if [ ${#INSTALL_OPTS[@]} -gt 0 ]; then
393
376
  # We use the site-packages directory of the current venv
394
377
  SITE_PACKAGES=$(python -c "import site; print(site.getsitepackages()[0])")
395
378
  printf " Targeting site-packages: $SITE_PACKAGES\n"
396
- pip install "${PKG_ARRAY[@]}" "${INSTALL_OPTS[@]}" --target "$SITE_PACKAGES"
379
+ CMD=(pip install "${PKG_ARRAY[@]}" "${INSTALL_OPTS[@]}" --target "$SITE_PACKAGES")
380
+ echo " Running: ${CMD[*]}"
381
+ "${CMD[@]}"
397
382
  else
398
- pip install "${PKG_ARRAY[@]}"
383
+ CMD=(pip install "${PKG_ARRAY[@]}")
384
+ echo " Running: ${CMD[*]}"
385
+ "${CMD[@]}"
399
386
  fi
400
387
 
401
388
  # Count packages from command argument
@@ -12,10 +12,19 @@ set -u
12
12
  WHEEL_FILE=""
13
13
  PACKAGES=""
14
14
  LAYER_NAME=""
15
- PYTHON_VERSION="3.12"
16
- PLATFORM="manylinux2014_x86_64"
15
+ # We now track user provided values separate from defaults
16
+ USER_PYTHON_VERSION=""
17
+ USER_ARCHITECTURE=""
18
+ USER_PLATFORM=""
19
+
20
+ DEFAULT_PYTHON_VERSION="3.12"
21
+ DEFAULT_ARCHITECTURE="x86_64"
22
+
23
+ PYTHON_VERSION="$DEFAULT_PYTHON_VERSION"
24
+ ARCHITECTURE="$DEFAULT_ARCHITECTURE"
25
+ PLATFORM=""
17
26
  IMPLEMENTATION="cp"
18
- ABI="cp312" # Default ABI tag
27
+ ABI="" # Will be calculated
19
28
 
20
29
  # Colors
21
30
  RED='\033[0;31m'
@@ -67,6 +76,7 @@ while [[ $# -gt 0 ]]; do
67
76
  ;;
68
77
  --python-version)
69
78
  if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
79
+ USER_PYTHON_VERSION="$2"
70
80
  PYTHON_VERSION="$2"
71
81
  shift 2
72
82
  else
@@ -75,20 +85,23 @@ while [[ $# -gt 0 ]]; do
75
85
  fi
76
86
  ;;
77
87
  --python-version=*)
88
+ USER_PYTHON_VERSION="${1#*=}"
78
89
  PYTHON_VERSION="${1#*=}"
79
90
  shift
80
91
  ;;
81
- --platform)
92
+ --architecture|-a)
82
93
  if [[ -n "${2:-}" && "${2:-}" != -* ]]; then
83
- PLATFORM="$2"
94
+ USER_ARCHITECTURE="$2"
95
+ ARCHITECTURE="$2"
84
96
  shift 2
85
97
  else
86
98
  printf "${RED}Error: $1 requires an argument${NC}\n"
87
99
  exit 1
88
100
  fi
89
101
  ;;
90
- --platform=*)
91
- PLATFORM="${1#*=}"
102
+ --architecture=*)
103
+ USER_ARCHITECTURE="${1#*=}"
104
+ ARCHITECTURE="${1#*=}"
92
105
  shift
93
106
  ;;
94
107
  -h|--help)
@@ -100,28 +113,18 @@ Options:
100
113
  -i, --packages Additional packages (comma or space separated)
101
114
  -n, --name Output zip filename
102
115
  --python-version Target Python version (default: 3.12)
103
- --platform Target platform (default: manylinux2014_x86_64)
104
-
105
- Supported Platforms:
106
- manylinux2014_x86_64 # Amazon Linux 2, RHEL 7+ (older)
107
- manylinux2014_aarch64 # ARM64 architecture
108
- manylinux_2_28_x86_64 # Amazon Linux 2023, RHEL 8+ (newer)
109
- manylinux_2_28_aarch64 # ARM64 with newer glibc
110
- linux_x86_64 # Generic Linux
111
- linux_aarch64 # Generic ARM64 Linux
116
+ -a, --architecture Target architecture (x86_64, arm64)
112
117
 
113
- Python Version Support:
114
- 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
118
+ Supported Architectures:
119
+ x86_64 (amd64) # Standard Intel/AMD 64-bit
120
+ arm64 (aarch64) # AWS Graviton (ARM 64-bit)
115
121
 
116
122
  Examples:
117
- # Build for Amazon Linux 2 (Python 3.12)
118
- ./create_wheel_layer.sh -w mypackage.whl --python-version=3.12 --platform=manylinux2014_x86_64
123
+ # Build for Amazon Linux 2 (Python 3.12, x86_64)
124
+ ./create_wheel_layer.sh -w mypackage.whl --python-version=3.12
119
125
 
120
- # Build for Amazon Linux 2023 (Python 3.13)
121
- ./create_wheel_layer.sh -w mypackage.whl --python-version=3.13 --platform=manylinux_2_28_x86_64
122
-
123
- # Build with additional packages for ARM64
124
- ./create_wheel_layer.sh -w mypackage.whl -i "numpy,pandas" --platform=manylinux_2_28_aarch64
126
+ # Build for ARM64
127
+ ./create_wheel_layer.sh -w mypackage.whl -a arm64
125
128
  EOF
126
129
  exit 0
127
130
  ;;
@@ -137,15 +140,233 @@ if [ -z "$WHEEL_FILE" ]; then
137
140
  printf "${RED}Error: Wheel file is required (-w)${NC}\n"
138
141
  exit 1
139
142
  fi
140
-
143
+ # Detect pip
144
+ PIP_EXE=""
145
+ if command -v pip &> /dev/null; then
146
+ PIP_EXE="pip"
147
+ elif command -v pip3 &> /dev/null; then
148
+ PIP_EXE="pip3"
149
+ else
150
+ printf "${RED}Error: pip or pip3 not found. Please install Python and pip.${NC}\n"
151
+ exit 1
152
+ fi
141
153
  if [ ! -f "$WHEEL_FILE" ]; then
142
154
  printf "${RED}Error: File $WHEEL_FILE not found${NC}\n"
143
155
  exit 1
144
156
  fi
145
157
 
146
- # Determine ABI tag based on Python version
147
- PY_MAJOR_MINOR=$(echo "$PYTHON_VERSION" | sed 's/\([0-9]\+\)\.\([0-9]\+\).*/\1\2/')
148
- ABI="cp${PY_MAJOR_MINOR}"
158
+ # ------------------------------------------------------------------
159
+ # WHEEL METADATA AUTO-DETECTION
160
+ # ------------------------------------------------------------------
161
+ # Extract metadata directly from filename/wheel to enforce strictness
162
+ # Format: Name-Ver-PyTag-AbiTag-PlatTag.whl
163
+
164
+ DETECTED_PY="any"
165
+ DETECTED_ABI="none"
166
+ DETECTED_PLAT="any"
167
+ DETECTED_ARCH="any"
168
+
169
+ # Helper python script to parse filename strictly
170
+ META_OUT=$(python3 -c "
171
+ import sys
172
+ import os
173
+
174
+ filename = os.path.basename(sys.argv[1])
175
+ if filename.endswith('.whl'):
176
+ filename = filename[:-4]
177
+
178
+ parts = filename.split('-')
179
+ # Minimal check: Name-Ver-Py-Abi-Plat
180
+ if len(parts) >= 5:
181
+ plat = parts[-1]
182
+ abi = parts[-2]
183
+ py = parts[-3]
184
+
185
+ # Arch mapping
186
+ arch = 'any'
187
+ if 'x86_64' in plat or 'amd64' in plat:
188
+ arch = 'x86_64'
189
+ elif 'aarch64' in plat or 'arm64' in plat:
190
+ arch = 'aarch64'
191
+
192
+ # Py Ver extraction (cp312->3.12)
193
+ py_ver = 'any'
194
+ if py.startswith('cp') and len(py) > 2 and py[2:].isdigit():
195
+ pv_raw = py[2:]
196
+ if len(pv_raw) == 2: # 39
197
+ py_ver = f'{pv_raw[0]}.{pv_raw[1]}'
198
+ elif len(pv_raw) >= 3: # 312
199
+ major = pv_raw[0]
200
+ minor = pv_raw[1:]
201
+ py_ver = f'{major}.{minor}'
202
+
203
+ print(f'{py_ver}|{arch}|{plat}|{abi}')
204
+ else:
205
+ print('any|any|any|none')
206
+ " "$WHEEL_FILE")
207
+
208
+ IFS='|' read -r DET_PY DET_ARCH DET_PLAT DET_ABI <<< "$META_OUT"
209
+
210
+ # STRICT MODE ENFORCEMENT
211
+ # If the wheel is binary (specific architecture or python), we ENFORCE it.
212
+ # If the wheel is 'any', we allow defaults or user args.
213
+
214
+ if [ "$DET_PY" != "any" ]; then
215
+ if [ -n "$USER_PYTHON_VERSION" ] && [ "$USER_PYTHON_VERSION" != "$DET_PY" ]; then
216
+ printf "${RED}Error: Wheel is for Python $DET_PY, but you requested $USER_PYTHON_VERSION.${NC}\n"
217
+ printf "Please remove the argument or use matching version.\n"
218
+ exit 1
219
+ fi
220
+ # Auto-set
221
+ PYTHON_VERSION="$DET_PY"
222
+ printf "Detected Python: $PYTHON_VERSION\n"
223
+ fi
224
+
225
+ if [ "$DET_ARCH" != "any" ]; then
226
+ if [ -n "$USER_ARCHITECTURE" ]; then
227
+ # Normalize user input for comparison
228
+ NORM_USER_ARCH="$USER_ARCHITECTURE"
229
+ if [ "$USER_ARCHITECTURE" == "arm64" ]; then NORM_USER_ARCH="aarch64"; fi
230
+ if [ "$USER_ARCHITECTURE" == "amd64" ]; then NORM_USER_ARCH="x86_64"; fi
231
+
232
+ if [ "$NORM_USER_ARCH" != "$DET_ARCH" ]; then
233
+ printf "${RED}Error: Wheel is for $DET_ARCH, but you requested $USER_ARCHITECTURE.${NC}\n"
234
+ exit 1
235
+ fi
236
+ fi
237
+ # Auto-set
238
+ ARCHITECTURE="$DET_ARCH"
239
+ printf "Detected Architecture: $ARCHITECTURE\n"
240
+ fi
241
+
242
+ if [ "$DET_PLAT" != "any" ] && [ -z "$USER_PLATFORM" ]; then
243
+ # Only override platform if user didn't specify one (pip might need specific one)
244
+ # But usually filename platform is correct for install
245
+ PLATFORM="$DET_PLAT"
246
+ fi
247
+
248
+ if [ "$DET_ABI" != "none" ]; then
249
+ ABI="$DET_ABI"
250
+ fi
251
+
252
+ # Normalize Architecture
253
+ AWS_ARCH="$ARCHITECTURE"
254
+ if [ "$ARCHITECTURE" = "arm64" ] || [ "$ARCHITECTURE" = "aarch64" ]; then
255
+ ARCHITECTURE="aarch64"
256
+ AWS_ARCH="arm64"
257
+ elif [ "$ARCHITECTURE" = "amd64" ] || [ "$ARCHITECTURE" = "x86_64" ]; then
258
+ ARCHITECTURE="x86_64"
259
+ AWS_ARCH="x86_64"
260
+ fi
261
+
262
+ # Determine Platform if still empty
263
+ if [ -z "$PLATFORM" ]; then
264
+ # Default to manylinux2014 as it is safe for both AL2 and AL2023
265
+ PLATFORM="manylinux2014_${ARCHITECTURE}"
266
+ fi
267
+
268
+
269
+ # Validate Wheel Suitability for Lambda (Linux) using metadata
270
+ printf "Validating wheel compatibility...\n"
271
+
272
+ # Only run python validation if python is available (it should be, given pip is used)
273
+ PYTHON_EXE=""
274
+ if command -v python3 &> /dev/null; then
275
+ PYTHON_EXE="python3"
276
+ elif command -v python &> /dev/null; then
277
+ PYTHON_EXE="python"
278
+ fi
279
+
280
+ if [ -n "$PYTHON_EXE" ]; then
281
+ # Use Python to inspect the WHEEL metadata for accurate tags
282
+ $PYTHON_EXE -c "
283
+ import sys, zipfile, os
284
+
285
+ try:
286
+ wheel_path = sys.argv[1]
287
+ target_arch = sys.argv[2]
288
+
289
+ # Define compatibility
290
+ compatible_os = ['manylinux', 'linux', 'any']
291
+
292
+ arch_map = {
293
+ 'x86_64': ['x86_64', 'amd64', 'any'],
294
+ 'arm64': ['aarch64', 'arm64', 'any'],
295
+ 'aarch64': ['aarch64', 'arm64', 'any']
296
+ }
297
+
298
+ with zipfile.ZipFile(wheel_path, 'r') as z:
299
+ # Find .dist-info/WHEEL
300
+ wheel_files = [f for f in z.namelist() if f.endswith('.dist-info/WHEEL')]
301
+ if not wheel_files:
302
+ # Fallback for old wheels without WHEEL metadata (rare)
303
+ print('Warning: No .dist-info/WHEEL found, skipping strict validation.')
304
+ sys.exit(0)
305
+
306
+ content = z.read(wheel_files[0]).decode('utf-8')
307
+ tags = []
308
+ for line in content.splitlines():
309
+ if line.startswith('Tag:'):
310
+ tags.append(line.split(':', 1)[1].strip())
311
+
312
+ has_linux = False
313
+ has_arch = False
314
+ detected_plats = set()
315
+
316
+ for tag in tags:
317
+ parts = tag.split('-')
318
+ if len(parts) >= 3:
319
+ plat = parts[2]
320
+ detected_plats.add(plat)
321
+
322
+ # Check OS
323
+ if any(x in plat for x in compatible_os):
324
+ has_linux = True
325
+
326
+ # Check Arch
327
+ target_valid_archs = arch_map.get(target_arch, [])
328
+
329
+ # Special handling for 'any' to avoid matching 'manylinux'
330
+ if plat == 'any' and 'any' in target_valid_archs:
331
+ has_arch = True
332
+ else:
333
+ # Filter out 'any' from search strings for substring check
334
+ search_archs = [x for x in target_valid_archs if x != 'any']
335
+ if any(x in plat for x in search_archs):
336
+ has_arch = True
337
+
338
+ if not has_linux:
339
+ print(f'Error: Wheel is not compatible with Linux.\nDetected platforms: {', '.join(sorted(detected_plats))}')
340
+ sys.exit(1)
341
+
342
+ if not has_arch:
343
+ print(f'Error: Wheel architecture mismatch.\nTarget: {target_arch}\nDetected platforms: {', '.join(sorted(detected_plats))}')
344
+ sys.exit(1)
345
+
346
+ except Exception as e:
347
+ print(f'Warning: Could not validate wheel metadata: {e}')
348
+ sys.exit(0) # Don't block build if validation script itself crashes
349
+ " "$WHEEL_FILE" "$ARCHITECTURE"
350
+
351
+ # Check exit code of python script
352
+ if [ $? -ne 0 ]; then
353
+ exit 1
354
+ fi
355
+ else
356
+ # Fallback to simple filename check if python not found (unlikely)
357
+ WHEEL_BASENAME=$(basename "$WHEEL_FILE")
358
+ if [[ "$WHEEL_BASENAME" == *"macosx"* ]] || [[ "$WHEEL_BASENAME" == *"win32"* ]]; then
359
+ printf "${YELLOW}Warning: Filename suggests non-Linux wheel ($WHEEL_BASENAME)${NC}\n"
360
+ fi
361
+ fi
362
+
363
+ # Determine ABI tag (If not auto-detected)
364
+ # e.g., 3.12 -> cp312, 3.10 -> cp310
365
+ if [ -z "$ABI" ] || [ "$ABI" == "none" ]; then
366
+ PY_MAJOR=$(echo "$PYTHON_VERSION" | cut -d. -f1)
367
+ PY_MINOR=$(echo "$PYTHON_VERSION" | cut -d. -f2)
368
+ ABI="cp${PY_MAJOR}${PY_MINOR}"
369
+ fi
149
370
 
150
371
  if [ -z "$LAYER_NAME" ]; then
151
372
  BASENAME=$(basename "$WHEEL_FILE" .whl)
@@ -166,14 +387,15 @@ printf "Wheel: $WHEEL_FILE\n"
166
387
  if [ -n "$PACKAGES" ]; then
167
388
  printf "Extra Packages: $PACKAGES\n"
168
389
  fi
169
- printf "Platform: $PLATFORM\n"
170
- printf "Python: $PYTHON_VERSION\n"
390
+ printf "Target Architecture: $AWS_ARCH\n"
391
+ printf "Platform Tag: $PLATFORM\n"
392
+ printf "Python: $PYTHON_VERSION (ABI: $ABI)\n"
171
393
 
172
394
  mkdir -p "$LAYER_DIR/python"
173
395
 
174
396
  # Install
175
397
  printf "${GREEN}Installing packages...${NC}\n"
176
- CMD=("pip" "install" "$WHEEL_FILE")
398
+ CMD=("$PIP_EXE" "install" "$WHEEL_FILE")
177
399
 
178
400
  if [ -n "$PACKAGES" ]; then
179
401
  # Replace commas with spaces
@@ -184,7 +406,14 @@ if [ -n "$PACKAGES" ]; then
184
406
  fi
185
407
 
186
408
  CMD+=("--target" "$LAYER_DIR/python")
187
- CMD+=("--platform" "$PLATFORM")
409
+
410
+ # Handle multiple platform tags (e.g. manylinux1_x86_64.linux_x86_64)
411
+ # Split by dot and add each as separate --platform argument
412
+ IFS='.' read -ra PLAT_TAGS <<< "$PLATFORM"
413
+ for tag in "${PLAT_TAGS[@]}"; do
414
+ CMD+=("--platform" "$tag")
415
+ done
416
+
188
417
  CMD+=("--implementation" "$IMPLEMENTATION")
189
418
  CMD+=("--python-version" "$PYTHON_VERSION")
190
419
  CMD+=("--abi" "$ABI")
@@ -208,10 +437,18 @@ find "$LAYER_DIR" -type d -name "*.dist-info" -exec rm -rf {} +
208
437
  # Zip
209
438
  printf "${GREEN}Zipping to $LAYER_NAME...${NC}\n"
210
439
  cd "$LAYER_DIR"
211
- if zip -r "$ORIGINAL_DIR/$LAYER_NAME" python > /dev/null; then
440
+
441
+ # Handle absolute vs relative path for LAYER_NAME
442
+ ZIP_DEST="$LAYER_NAME"
443
+ if [[ "$LAYER_NAME" != /* ]]; then
444
+ ZIP_DEST="$ORIGINAL_DIR/$LAYER_NAME"
445
+ fi
446
+
447
+ if zip -r "$ZIP_DEST" python > /dev/null; then
212
448
  printf "${GREEN}✅ Done! Created $LAYER_NAME${NC}\n"
449
+ printf "File: $(basename "$LAYER_NAME")\n"
213
450
  else
214
- printf "${RED}Error creating zip file${NC}\n"
451
+ printf "${RED}Error creating zip file at $ZIP_DEST${NC}\n"
215
452
  cd "$ORIGINAL_DIR"
216
453
  rm -rf "$LAYER_DIR"
217
454
  exit 1
@@ -44,7 +44,7 @@ if ([string]::IsNullOrEmpty($InstallDir)) {
44
44
  # Configuration
45
45
  $RepoUrl = "https://github.com/yukcw/aws-lambda-layer-cli"
46
46
  $ToolName = "aws-lambda-layer-cli"
47
- $Version = "2.1.3" # Fallback version
47
+ $Version = "2.2.0" # Fallback version
48
48
 
49
49
  # Colors for output
50
50
  $Green = "Green"
File without changes