Skip to content

Commit 1b70cf8

Browse files
authored
Merge pull request #577 from constructive-io/feat/cloud-fn-test
Feat/cloud fn test
2 parents f2fdebe + ada5524 commit 1b70cf8

48 files changed

Lines changed: 6231 additions & 7329 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/run-tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ jobs:
3333
env: {}
3434
- package: packages/cli
3535
env: {}
36+
- package: jobs/knative-job-service
37+
env: {}
3638
- package: packages/client
3739
env:
3840
TEST_DATABASE_URL: postgres://postgres:password@localhost:5432/postgres

functions/send-email-link/README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,22 @@ Recommended / optional:
8585
- `LOCAL_APP_PORT`
8686
Optional port suffix for localhost-style hosts (e.g. `3000`). When the resolved hostname is `localhost` / `*.localhost` and `SEND_EMAIL_LINK_DRY_RUN=true`, links are generated as `http://localhost:LOCAL_APP_PORT/...`. Ignored for non-local hostnames and in production.
8787

88-
Email delivery (used by `@launchql/postmaster`):
88+
Email delivery (default: `@launchql/postmaster`):
8989

90-
- Typically Mailgun or another provider; consult `@launchql/postmaster` docs. A common pattern is:
90+
- Set `EMAIL_SEND_USE_SMTP=true` to switch to `@constructive-io/smtppostmaster` (SMTP). Otherwise it uses `@launchql/postmaster`.
91+
92+
- Mailgun or another provider; consult `@launchql/postmaster` docs. A common pattern is:
9193
- `MAILGUN_API_KEY`
9294
- `MAILGUN_DOMAIN`
9395
- `MAILGUN_FROM`
9496

97+
- SMTP variables when `EMAIL_SEND_USE_SMTP=true`:
98+
- `SMTP_HOST`
99+
- `SMTP_PORT`
100+
- `SMTP_USER`
101+
- `SMTP_PASS`
102+
- `SMTP_FROM`
103+
95104
## Building locally
96105

97106
From the repo root:

functions/send-email-link/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
},
1616
"dependencies": {
1717
"@constructive-io/knative-job-fn": "workspace:^",
18+
"@constructive-io/smtppostmaster": "workspace:^",
1819
"@launchql/mjml": "0.1.1",
1920
"@launchql/postmaster": "0.1.4",
2021
"@launchql/styled-email": "0.1.0",
2122
"@pgpmjs/env": "workspace:^",
23+
"@pgpmjs/logger": "workspace:^",
2224
"graphql-request": "^7.1.2",
2325
"graphql-tag": "^2.12.6"
2426
}

functions/send-email-link/src/index.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import app from '@constructive-io/knative-job-fn';
1+
import { createJobApp } from '@constructive-io/knative-job-fn';
22
import { GraphQLClient } from 'graphql-request';
33
import gql from 'graphql-tag';
44
import { generate } from '@launchql/mjml';
5-
import { send } from '@launchql/postmaster';
5+
import { send as sendPostmaster } from '@launchql/postmaster';
6+
import { send as sendSmtp } from '@constructive-io/smtppostmaster';
67
import { parseEnvBoolean } from '@pgpmjs/env';
8+
import { createLogger } from '@pgpmjs/logger';
79

810
const isDryRun = parseEnvBoolean(process.env.SEND_EMAIL_LINK_DRY_RUN) ?? false;
11+
const useSmtp = parseEnvBoolean(process.env.EMAIL_SEND_USE_SMTP) ?? false;
12+
const logger = createLogger('send-email-link');
13+
const app = createJobApp();
914

1015
const GetUser = gql`
1116
query GetUser($userId: UUID!) {
@@ -273,15 +278,15 @@ export const sendEmailLink = async (
273278
});
274279

275280
if (isDryRun) {
276-
// eslint-disable-next-line no-console
277-
console.log('[send-email-link] DRY RUN email (skipping send)', {
281+
logger.info('DRY RUN email (skipping send)', {
278282
email_type: params.email_type,
279283
email: params.email,
280284
subject,
281285
link
282286
});
283287
} else {
284-
await send({
288+
const sendEmail = useSmtp ? sendSmtp : sendPostmaster;
289+
await sendEmail({
285290
to: params.email,
286291
subject,
287292
html
@@ -330,7 +335,6 @@ if (require.main === module) {
330335
const port = Number(process.env.PORT ?? 8080);
331336
// @constructive-io/knative-job-fn exposes a .listen method that delegates to the Express app
332337
(app as any).listen(port, () => {
333-
// eslint-disable-next-line no-console
334-
console.log(`[send-email-link] listening on port ${port}`);
338+
logger.info(`listening on port ${port}`);
335339
});
336340
}

functions/simple-email/README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
Simple Knative-compatible email function used with the Constructive jobs system.
44

55
This function is intentionally minimal: it reads an email payload from the job
6-
body and **logs it only** (dry‑run mode). It does **not** send any email. This
7-
is useful while wiring up jobs and Knative without needing a real mail
8-
provider configured.
6+
body and **logs it only** in dry‑run mode. When not in dry‑run, it sends via
7+
the configured email provider. This is useful while wiring up jobs and Knative
8+
without needing a real mail provider configured.
99

1010
## Expected job payload
1111

@@ -62,10 +62,26 @@ callback for the worker.
6262

6363
## Environment variables
6464

65-
This function does **not** depend on any GraphQL or email provider
66-
configuration. There are currently **no required environment variables** for
67-
its core behavior; it will simply log the email payload and return a successful
68-
response.
65+
Email provider configuration is only required when not running in dry‑run mode.
66+
67+
Optional:
68+
69+
- `SIMPLE_EMAIL_DRY_RUN` (`true`/`false`): log only, skip send.
70+
- `EMAIL_SEND_USE_SMTP` (`true`/`false`): use SMTP (`@constructive-io/smtppostmaster`).
71+
72+
Mailgun (`@launchql/postmaster`) env vars when `EMAIL_SEND_USE_SMTP` is false:
73+
74+
- `MAILGUN_API_KEY`
75+
- `MAILGUN_DOMAIN`
76+
- `MAILGUN_FROM`
77+
78+
SMTP env vars when `EMAIL_SEND_USE_SMTP` is true:
79+
80+
- `SMTP_HOST`
81+
- `SMTP_PORT`
82+
- `SMTP_USER`
83+
- `SMTP_PASS`
84+
- `SMTP_FROM`
6985

7086
## Building locally
7187

functions/simple-email/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
},
1616
"dependencies": {
1717
"@constructive-io/knative-job-fn": "workspace:^",
18+
"@constructive-io/smtppostmaster": "workspace:^",
1819
"@launchql/postmaster": "0.1.4",
19-
"@pgpmjs/env": "workspace:^"
20+
"@pgpmjs/env": "workspace:^",
21+
"@pgpmjs/logger": "workspace:^"
2022
}
2123
}

functions/simple-email/src/index.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import app from '@constructive-io/knative-job-fn';
1+
import { createJobApp } from '@constructive-io/knative-job-fn';
2+
import { send as sendSmtp } from '@constructive-io/smtppostmaster';
3+
import { send as sendPostmaster } from '@launchql/postmaster';
24
import { parseEnvBoolean } from '@pgpmjs/env';
3-
import { send as sendEmail } from '@launchql/postmaster';
5+
import { createLogger } from '@pgpmjs/logger';
46

57
type SimpleEmailPayload = {
68
to: string;
@@ -26,6 +28,9 @@ const getRequiredField = (
2628
};
2729

2830
const isDryRun = parseEnvBoolean(process.env.SIMPLE_EMAIL_DRY_RUN) ?? false;
31+
const useSmtp = parseEnvBoolean(process.env.EMAIL_SEND_USE_SMTP) ?? false;
32+
const logger = createLogger('simple-email');
33+
const app = createJobApp();
2934

3035
app.post('/', async (req: any, res: any, next: any) => {
3136
try {
@@ -41,7 +46,7 @@ app.post('/', async (req: any, res: any, next: any) => {
4146
throw new Error("Either 'html' or 'text' must be provided");
4247
}
4348

44-
const fromEnv = process.env.MAILGUN_FROM;
49+
const fromEnv = useSmtp ? process.env.SMTP_FROM : process.env.MAILGUN_FROM;
4550
const from = isNonEmptyString(payload.from)
4651
? payload.from
4752
: isNonEmptyString(fromEnv)
@@ -62,10 +67,10 @@ app.post('/', async (req: any, res: any, next: any) => {
6267
};
6368

6469
if (isDryRun) {
65-
// eslint-disable-next-line no-console
66-
console.log('[simple-email] DRY RUN email (no send)', logContext);
70+
logger.info('DRY RUN email (no send)', logContext);
6771
} else {
6872
// Send via the Postmaster package (Mailgun or configured provider)
73+
const sendEmail = useSmtp ? sendSmtp : sendPostmaster;
6974
await sendEmail({
7075
to,
7176
subject,
@@ -75,8 +80,7 @@ app.post('/', async (req: any, res: any, next: any) => {
7580
...(replyTo && { replyTo })
7681
});
7782

78-
// eslint-disable-next-line no-console
79-
console.log('[simple-email] Sent email', logContext);
83+
logger.info('Sent email', logContext);
8084
}
8185

8286
res.status(200).json({ complete: true });
@@ -93,7 +97,6 @@ if (require.main === module) {
9397
const port = Number(process.env.PORT ?? 8080);
9498
// @constructive-io/knative-job-fn exposes a .listen method that delegates to the underlying Express app
9599
(app as any).listen(port, () => {
96-
// eslint-disable-next-line no-console
97-
console.log(`[simple-email] listening on port ${port}`);
100+
logger.info(`listening on port ${port}`);
98101
});
99102
}

0 commit comments

Comments
 (0)