Skip to content

Commit

Permalink
Merge branch 'main' into boards-collections
Browse files Browse the repository at this point in the history
  • Loading branch information
MikaelSiidorow authored Jan 21, 2024
2 parents 4e58094 + 15bebfe commit 1b27742
Show file tree
Hide file tree
Showing 26 changed files with 257 additions and 59 deletions.
3 changes: 2 additions & 1 deletion .env.docker-compose.prod
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ PAYLOAD_PORT=3001
NEXT_REVALIDATION_KEY="veryprivatekey"

PUBLIC_FRONTEND_URL="http://localhost:3000"
SERVER_URL="http://cms:3001"
PUBLIC_SERVER_URL="http://cms:3001"
PUBLIC_ILMOMASIINA_URL="https://ilmo.tietokilta.fi"
13 changes: 10 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@ PAYLOAD_MONGO_CONNECTION_STRING="mongodb://127.0.0.1/payload"
PAYLOAD_SECRET="verysecretkey"
PAYLOAD_REVALIDATION_KEY="veryprivatekey"
PAYLOAD_PORT=3001
# for LOCAL_DEVELOPMENT autologin setup, DO NOT USE IN PRODUCTION :)
# default user setup, this user will be created if no users exist in the database
# NOTE: this is only used for seeding data, not for autologin
# if these are not set, the admin UI will ask for a user to be created on first login
PAYLOAD_DEFAULT_USER_EMAIL=[email protected]
PAYLOAD_DEFAULT_USER_PASSWORD=root

# for LOCAL_DEVELOPMENT autologin setup, DO NOT USE THESE IN PRODUCTION :)
#these should be set to the same values as the default user above
PAYLOAD_PUBLIC_DEVELOPMENT_AUTOLOGIN_EMAIL=[email protected]
PAYLOAD_PUBLIC_DEVELOPMENT_AUTOLOGIN_PASSWORD=root
PAYLOAD_PUBLIC_LOCAL_DEVELOPMENT=true

NEXT_REVALIDATION_KEY="veryprivatekey"

PUBLIC_FRONTEND_URL="http://localhost:3000"
SERVER_URL="http://localhost:3001"
PUBLIC_ILMOMASIINA_URL="https://tik-ilmo-prod-app.azurewebsites.net"
PUBLIC_SERVER_URL="http://localhost:3001"
PUBLIC_ILMOMASIINA_URL="https://ilmo.tietokilta.fi"

# variables required for Google OAuth 2.0, otherwise disabled
#GOOGLE_OAUTH_CLIENT_ID=
Expand Down
36 changes: 33 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ on:
push:
release:
types: [published]

permissions:
id-token: write
contents: read
env:
# Change this to upload the built image to your own organization.
docker_tag_prefix: ghcr.io/tietokilta
jobs:
build:
name: Format, Lint, Check types & Build
Expand Down Expand Up @@ -32,7 +39,7 @@ jobs:
run: pnpm codegen && git diff --quiet
- name: Build all
run: pnpm build
docker:
docker-build-and-push:
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'release' && github.event.action == 'published')
needs: build
strategy:
Expand All @@ -58,11 +65,11 @@ jobs:
id: meta
uses: docker/metadata-action@v4
with:
images: ghcr.io/tietokilta/${{matrix.project}}
images: ${{env.docker_tag_prefix}}/${{matrix.project}}
tags: |
type=semver,pattern={{version}},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},enable=${{ github.ref_type == 'tag' }}
type=sha
type=raw,value=sha-${{github.sha}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Push to GitHub Packages
Expand All @@ -74,3 +81,26 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
build-args: |
PROJECT=${{matrix.project}}
GIT_COMMIT_SHA=${{github.sha}}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
# only run on published releases, enable this when we release
#if: github.event_name == 'release' && github.event.action == 'published'
name: Deploy to Azure
runs-on: ubuntu-latest
needs: docker-build-and-push
strategy:
matrix:
project: [web, cms]
steps:
- name: Login via Azure CLI
uses: azure/login@v1
with:
client-id: ${{secrets.AZURE_CLIENT_ID}}
subscription-id: ${{secrets.AZURE_SUBSCRIPTION_ID}}
tenant-id: ${{secrets.AZURE_TENANT_ID}}
- uses: azure/webapps-deploy@v2
with:
app-name: tikweb-${{matrix.project}}-prod # TODO: if we ever setup more envs than prod, make this variable customizable
images: "${{ env.docker_tag_prefix }}/${{matrix.project}}:sha-${{ github.sha }}"
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ RUN pnpm install --global turbo
# Build argument for specifying the project
# Introduce a build argument 'PROJECT' to specify which project in the monorepo to build.
ARG PROJECT=web

ARG GIT_COMMIT_SHA=development
ENV GIT_COMMIT_SHA=$GIT_COMMIT_SHA
# Install all dependencies in the monorepo
# Start a new stage for handling dependencies. This stage uses the previously setup image with pnpm and turbo installed.
FROM setup AS dependencies
Expand All @@ -26,14 +27,14 @@ WORKDIR /app
COPY packages/ ./packages/
COPY turbo.json ./
COPY package.json turbo.json packages ./
COPY apps/${PROJECT} ./apps/${PROJECT}
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
# Install dependencies as per the lockfile to ensure consistent dependency resolution.
RUN pnpm install --frozen-lockfile

# Prune projects to focus on the specified project scope
# Start a new stage to prune the monorepo, focusing only on the necessary parts for the specified project.
FROM dependencies AS pruner
COPY apps/${PROJECT} ./apps/${PROJECT}
RUN turbo prune --scope=${PROJECT} --docker
# Remove all empty node_modules folders. This is a cleanup step to remove unnecessary directories and reduce image size.
RUN rm -rf /app/out/full/*/*/node_modules
Expand Down Expand Up @@ -71,6 +72,8 @@ RUN rm -rf ./**/*/src
FROM base AS runner
#this needs to be here for some reason again, otherwise the WORKDIR command doesn't pick it up
ARG PROJECT=web
ARG GIT_COMMIT_SHA=development
ENV GIT_COMMIT_SHA=$GIT_COMMIT_SHA
# Create a non-root user and group for better security.
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nodejs
Expand Down
4 changes: 2 additions & 2 deletions apps/cms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "MIT",
"main": "dist/server.js",
"scripts": {
"build": "pnpm copyfiles && pnpm build:payload && pnpm build:server",
"build": "NODE_ENV=production pnpm copyfiles && pnpm build:payload && pnpm build:server",
"build:payload": "payload build",
"build:server": "tsc",
"clean": "rm -rf dist",
Expand All @@ -15,7 +15,7 @@
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema",
"generate:types": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
"lint": "eslint \"./src/**/*.{js,ts}\"",
"start": "PAYLOAD_CONFIG_PATH=dist/payload.config.js node dist/server.js",
"start": "NODE_ENV=production PAYLOAD_CONFIG_PATH=dist/payload.config.js node dist/server.js",
"typecheck": "tsc --noEmit"
},
"dependencies": {
Expand Down
25 changes: 17 additions & 8 deletions apps/cms/src/hooks/revalidate-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,26 @@ export const revalidatePage =
(!("_status" in doc) || doc._status === "published")
) {
const revalidate = async (): Promise<void> => {
const revalidationKey = process.env.PAYLOAD_REVALIDATION_KEY;
if (!revalidationKey) {
req.payload.logger.error(
"PAYLOAD_REVALIDATION_KEY not set, cannot revalidate",
);
return;
}
try {
const fetchData = JSON.stringify(await getFetchData(doc, req));
const res = await fetch(
`${
process.env.PUBLIC_FRONTEND_URL
}/api/revalidate?${new URLSearchParams({
secret: process.env.PAYLOAD_REVALIDATION_KEY ?? "",
collection,
fetchData,
}).toString()}`,
const fetchUrl = `${
process.env.PUBLIC_FRONTEND_URL
}/next_api/revalidate?${new URLSearchParams({
secret: revalidationKey,
collection,
fetchData,
}).toString()}`;
req.payload.logger.info(
`sending revalidate request ${fetchUrl.replace(revalidationKey, "REDACTED")}`,
);
const res = await fetch(fetchUrl);
if (res.ok) {
req.payload.logger.info(
`Revalidated collection ${collection} with data ${fetchData}`,
Expand Down
8 changes: 4 additions & 4 deletions apps/cms/src/payload.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const {

export default buildConfig({
// TODO: should probably enable this for production but it breaks auth in development
// serverURL: process.env.SERVER_URL,
// serverURL: process.env.PUBLIC_SERVER_URL,
admin: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- stupid eslint doesn't find the type
bundler: webpackBundler(),
Expand All @@ -70,7 +70,7 @@ export default buildConfig({
},
upload: {
limits: {
fileSize: 5000000, // 5MB, written in bytes
fileSize: 10000000, // 10MB, written in bytes
},
},
collections: [Users, Pages, Media, Topics, BoardMembers, Boards],
Expand Down Expand Up @@ -99,8 +99,8 @@ export default buildConfig({
connectOptions: {
dbName: process.env.PAYLOAD_MONGO_DB_NAME,
},
// @ts-expect-error DATABASE_URL is validated by payload on start
url: process.env.PAYLOAD_MONGO_CONNECTION_STRING,
// webpack build crashes if these are not set i.e. have to default empty
url: process.env.PAYLOAD_MONGO_CONNECTION_STRING ?? "",
}),
editor: lexicalEditor({
features: [
Expand Down
2 changes: 1 addition & 1 deletion apps/cms/src/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import type { GeneratePreviewURL } from "payload/config";
export const generatePreviewUrl =
<T>(getUrl: (doc: T) => string): GeneratePreviewURL =>
(doc) =>
`${process.env.PUBLIC_FRONTEND_URL}/api/preview?url=${getUrl(doc as T)}`;
`${process.env.PUBLIC_FRONTEND_URL}/next_api/preview?url=${getUrl(doc as T)}`;
29 changes: 18 additions & 11 deletions apps/cms/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ const secret = process.env.PAYLOAD_SECRET;
if (!secret) {
throw new Error("PAYLOAD_SECRET is not set");
}
const app = express();
const gitSha = process.env.GIT_COMMIT_SHA ?? "dev";

const app = express();
app.use((_, res, next) => {
res.setHeader("X-Git-Commit-Sha", gitSha);
next();
});
// Redirect root to Admin panel
app.get("/", (_, res) => {
res.redirect("/admin");
Expand All @@ -27,13 +32,14 @@ const start = async (): Promise<void> => {
if (useGoogleAuth()) {
payloadInstance.logger.info("Using Google OAuth2");
}
if (process.env.PAYLOAD_PUBLIC_LOCAL_DEVELOPMENT === "true") {
const email = process.env.PAYLOAD_PUBLIC_DEVELOPMENT_AUTOLOGIN_EMAIL;
const password =
process.env.PAYLOAD_PUBLIC_DEVELOPMENT_AUTOLOGIN_PASSWORD;
const { PAYLOAD_DEFAULT_USER_EMAIL, PAYLOAD_DEFAULT_USER_PASSWORD } =
process.env;
if (PAYLOAD_DEFAULT_USER_EMAIL && PAYLOAD_DEFAULT_USER_PASSWORD) {
const email = PAYLOAD_DEFAULT_USER_EMAIL;
const password = PAYLOAD_DEFAULT_USER_PASSWORD;
if (!email || !password) {
throw new Error(
"PAYLOAD_PUBLIC_DEVELOPMENT_AUTOLOGIN_EMAIL and PAYLOAD_PUBLIC_DEVELOPMENT_AUTOLOGIN_PASSWORD must be set when PAYLOAD_PUBLIC_LOCAL_DEVELOPMENT is true",
payloadInstance.logger.warn(
`PAYLOAD_DEFAULT_USER_EMAIL and PAYLOAD_DEFAULT_USER_PASSWORD are not set, first user has to be created manually through the admin panel`,
);
}
// check if the user exists, if not, create it
Expand All @@ -43,17 +49,18 @@ const start = async (): Promise<void> => {
});
if (user.totalDocs === 0) {
payloadInstance.logger.warn(`user ${email} not found, creating...`);
payloadInstance.logger.warn(
"NOTE that it is recommended to use the seeding scripts (`pnpm db:reset`) to a get filled database for local development",
);
if (process.env.NODE_ENV !== "production") {
payloadInstance.logger.warn(
"NOTE that it is recommended to use the seeding scripts (`pnpm db:reset`) to a get filled database for local development",
);
}
await payloadInstance.create({
collection: "users",
data: {
email,
password,
},
});
payloadInstance.logger.warn("Payload autologin enabled!");
}
}
},
Expand Down
21 changes: 20 additions & 1 deletion apps/web/next.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/** @type {import("next").NextConfig} */
const isProd = process.env.NODE_ENV === "production";
const gitSha = process.env.GIT_COMMIT_SHA ?? "dev";
const cdnUrl = "https://next-cdn-endpoint-prod.azureedge.net";
module.exports = {
reactStrictMode: true,
images: {
Expand All @@ -15,5 +17,22 @@ module.exports = {
]
: undefined,
},
assetPrefix: isProd ? "https://cdn.alpha.tietokilta.fi" : undefined,
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "x-git-commit-sha",
value: gitSha,
},
// {
// key: "Access-Control-Allow-Origin",
// value: cdnUrl,
// },
],
},
];
},
// assetPrefix: isProd ? cdnUrl : undefined,
};
File renamed without changes.
13 changes: 13 additions & 0 deletions apps/web/src/app/next_api/health/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
// this is here for CDN probePath
export function GET(_: NextRequest): NextResponse {
return NextResponse.json(
{
status: "ok",
},
{
status: 200,
},
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function GET(
}

// validate the Payload token
const userReq = await fetch(`${process.env.SERVER_URL}/api/users/me`, {
const userReq = await fetch(`${process.env.PUBLIC_SERVER_URL}/api/users/me`, {
headers: {
Authorization: `JWT ${payloadToken}`,
},
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion apps/web/src/components/admin-bar-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function AdminBarClient({
return (
<PayloadAdminBar
className="bottom-0"
cmsURL={process.env.SERVER_URL ?? window.location.origin}
cmsURL={process.env.PUBLIC_SERVER_URL ?? window.location.origin}
collection={collection}
id={id}
onPreviewExit={void exitPreview}
Expand Down
7 changes: 6 additions & 1 deletion apps/web/src/components/events-display/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@ async function EventList({
}) {
const events = await fetchEvents();

if (!events.ok) {
console.warn("Failed to fetch events from Ilmomasiina", events.error);
return null;
}

return (
<ul className="space-y-4">
{events.map((event) => (
{events.data.map((event) => (
<EventItem
event={event}
ilmolinkText={ilmolinkText}
Expand Down
3 changes: 3 additions & 0 deletions apps/web/src/dictionaries/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
},
"heading": {
"Upcoming events": "Upcoming events"
},
"errors": {
"ilmomasiina-fetch-fail": "Failed to fetch events from Ilmomasiina. Please try again later."
}
}
3 changes: 3 additions & 0 deletions apps/web/src/dictionaries/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
},
"heading": {
"Upcoming events": "Tulevat tapahtumat"
},
"errors": {
"ilmomasiina-fetch-fail": "Ilmomasiinassa tapahtui virhe. Yritä myöhemmin uudelleen."
}
}
Loading

0 comments on commit 1b27742

Please sign in to comment.