Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions scripts/Dockerfile.script
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ RUN apt-get update && \
make \
cmake \
unzip \
libcurl4-openssl-dev
libcurl4-openssl-dev && \
rm -rf /var/lib/apt/lists/*
RUN npm install aws-lambda-ric
RUN npm ci --only=production
ENV PLAYWRIGHT_BROWSERS_PATH=0
RUN npx playwright install chromium --with-deps
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
RUN npx playwright install chromium --with-deps && \
npx playwright install-deps chromium
ENTRYPOINT ["/usr/local/bin/npx", "aws-lambda-ric"]
CMD ["dist/lambda-handler.handler"]
14 changes: 9 additions & 5 deletions scripts/build-lambda.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#!/bin/bash
set -e
docker buildx build --platform linux/arm64 --provenance=false -f Dockerfile.script -t lambda-script:test .
docker run --platform linux/arm64 -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
--entrypoint /aws-lambda/aws-lambda-rie \
lambda-script:test \
/usr/local/bin/npx aws-lambda-ric dist/lambda-handler.handler
docker buildx build --platform linux/amd64 --provenance=false -f Dockerfile.script -t pwp/pexels-image-scraper-lambda .
# docker run --platform linux/amd64 -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
# --entrypoint /aws-lambda/aws-lambda-rie \
# lambda-script:test \
# /usr/local/bin/npx aws-lambda-ric dist/lambda-handler.handler

docker tag pwp/pexels-image-scraper-lambda:latest 279892746640.dkr.ecr.us-west-2.amazonaws.com/pwp/pexels-image-scraper-lambda:latest

docker push 279892746640.dkr.ecr.us-west-2.amazonaws.com/pwp/pexels-image-scraper-lambda:latest
Comment on lines +3 to +11

Copilot AI Nov 1, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AWS account ID (279892746640) is hardcoded in the script. This should be parameterized using an environment variable (e.g., AWS_ACCOUNT_ID) to avoid exposing sensitive account information and to make the script reusable across different environments.

Suggested change
docker buildx build --platform linux/amd64 --provenance=false -f Dockerfile.script -t pwp/pexels-image-scraper-lambda .
# docker run --platform linux/amd64 -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
# --entrypoint /aws-lambda/aws-lambda-rie \
# lambda-script:test \
# /usr/local/bin/npx aws-lambda-ric dist/lambda-handler.handler
docker tag pwp/pexels-image-scraper-lambda:latest 279892746640.dkr.ecr.us-west-2.amazonaws.com/pwp/pexels-image-scraper-lambda:latest
docker push 279892746640.dkr.ecr.us-west-2.amazonaws.com/pwp/pexels-image-scraper-lambda:latest
if [ -z "$AWS_ACCOUNT_ID" ]; then
echo "Error: AWS_ACCOUNT_ID environment variable is not set."
exit 1
fi
docker buildx build --platform linux/amd64 --provenance=false -f Dockerfile.script -t pwp/pexels-image-scraper-lambda .
# docker run --platform linux/amd64 -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
# --entrypoint /aws-lambda/aws-lambda-rie \
# lambda-script:test \
# /usr/local/bin/npx aws-lambda-ric dist/lambda-handler.handler
docker tag pwp/pexels-image-scraper-lambda:latest ${AWS_ACCOUNT_ID}.dkr.ecr.us-west-2.amazonaws.com/pwp/pexels-image-scraper-lambda:latest
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.us-west-2.amazonaws.com/pwp/pexels-image-scraper-lambda:latest

Copilot uses AI. Check for mistakes.
8 changes: 7 additions & 1 deletion scripts/src/lambda-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export async function handler(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_context: Context,
): Promise<APIGatewayProxyResult> {
console.log("Lambda handler started");
try {
const pexelsUrl =
"https://www.pexels.com/@perry-z-1662054943/featured-uploads/";
console.log(`Fetching images from: ${pexelsUrl}`);
const imageLinks = await getImageLinksPlaywright(pexelsUrl);

if (imageLinks && imageLinks.length > 0) {
Expand All @@ -42,7 +44,11 @@ export async function handler(
};
}
} catch (error) {
console.log(`Error in lambdaHandler: ${error}`);
console.error(`Error in lambdaHandler: ${error}`);
if (error instanceof Error) {
console.error(`Error message: ${error.message}`);
console.error(`Error stack: ${error.stack}`);
}
return {
statusCode: 500,
body: JSON.stringify({
Expand Down
79 changes: 73 additions & 6 deletions scripts/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,68 @@ async function findLoadMoreButton(

async function getImageLinksPlaywright(url: string): Promise<string[]> {
let browser = null;
let context = null;
let page = null;

// Set environment variable to use system Chromium in Lambda
process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH || '/ms-playwright/chromium-*/chrome-linux/chrome';

Copilot AI Nov 1, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wildcard path '/ms-playwright/chromium-*/chrome-linux/chrome' will not work at runtime. Shell glob patterns are not resolved when setting environment variables. You need to use an explicit path or resolve the glob pattern programmatically using the fs module.

Copilot uses AI. Check for mistakes.

try {
console.log("Environment:", {
PLAYWRIGHT_BROWSERS_PATH: process.env.PLAYWRIGHT_BROWSERS_PATH,
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH,
NODE_ENV: process.env.NODE_ENV,
});

console.log("Launching browser...");
const launchStart = Date.now();
browser = await chromium.launch({
headless: true,
args: ["--disable-gpu", "--disable-blink-features=AutomationControlled"],
timeout: 120000,
args: [
"--disable-gpu",
"--disable-blink-features=AutomationControlled",
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
"--disable-software-rasterizer",
"--disable-extensions",
"--disable-background-networking",
"--disable-sync",
"--metrics-recording-only",
"--mute-audio",
"--no-first-run",
"--safebrowsing-disable-auto-update",
"--disable-component-update",
"--disable-default-apps",
"--no-zygote",
"--disable-accelerated-2d-canvas",
"--disable-webgl",
],
});
const launchDuration = Date.now() - launchStart;
console.log(`Browser launched successfully in ${launchDuration}ms`);

if (!browser.isConnected()) {
throw new Error("Browser disconnected after launch");
}

const context = await browser.newContext({
console.log("Creating browser context...");
context = await browser.newContext({
userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
});

const page = await context.newPage();
console.log("Browser context created successfully");

console.log("Creating new page...");
try {
page = await context.newPage();
console.log("New page created successfully");
} catch (pageError) {
console.error("Failed to create new page");
console.error(`Browser connected: ${browser.isConnected()}`);
throw pageError;
}
Comment on lines +108 to +115

Copilot AI Nov 1, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This nested try-catch block adds unnecessary complexity. The pageError will be caught by the outer catch block (line 179), making this inner try-catch redundant. The browser.isConnected() check could be added to the outer error handling instead.

Copilot uses AI. Check for mistakes.

console.log("Fetching URL with Playwright...");
await page.goto(url, {
Expand Down Expand Up @@ -128,10 +178,27 @@ async function getImageLinksPlaywright(url: string): Promise<string[]> {
return processedImgLinks;
} catch (error) {
console.error(`An error occurred: ${error}`);
if (error instanceof Error) {
console.error(`Error stack: ${error.stack}`);
}
return [];
} finally {
if (browser) {
await browser.close();
console.log("Cleaning up resources...");
try {
if (page) {
await page.close();
console.log("Page closed");
}
if (context) {
await context.close();
console.log("Context closed");
}
if (browser) {
await browser.close();
console.log("Browser closed");
}
} catch (cleanupError) {
console.error(`Error during cleanup: ${cleanupError}`);
}
}
}
Expand Down