Skip to content

Commit

Permalink
feature/fix sb rollout (#83)
Browse files Browse the repository at this point in the history
* small landing fixes

* update-presets and stories

* commit removed sanity folder

* add random hash to project name, to avoid conflicts

* remove backup stories, add condition to execute removal only if no DEBUG flag is provided, fix vercel env, sort before create folders

* Remove sanity project

* Remove sanity project

* refactor file util

* Remove sanity project

* Remove sanity project

* Cleanup

* Cleanup

* Cleanup

* Cleanup

* remove read file

* move to the correct place

* fix script

* create public token for storyblok project for peoduction env

* fix variable
  • Loading branch information
dogfrogfog authored Jan 16, 2025
1 parent 9296fce commit 69f9f50
Show file tree
Hide file tree
Showing 18 changed files with 2,078 additions and 3,976 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,11 @@ REPO_NAME="[nickname]/[repo name]"

```bash
# Created by Vercel CLI
NEXT_PUBLIC_API_GATE="https://api.storyblok.com/v2/cdn"
NEXT_PUBLIC_DOMAIN="https://localhost:4050"
NEXT_PUBLIC_IS_PREVIEW="true"
NEXT_PUBLIC_SB_REGION="EU"
NEXT_PUBLIC_DOMAIN="https://localhost:4050"
NEXT_PUBLIC_STORYBLOK_TOKEN="[storyblok space preview token]"
NEXT_PUBLIC_STORYBLOK_API_GATE="https://api.storyblok.com/v2/cdn"
VERCEL_REDEPLOY_HOOK_URL="https://api.vercel.com/v1/integrations/deploy/[KEY]/[KEY"
SB_WEBHOOK_REVALIDATE_SECRET="[storyblok webhook revalidate key]"
```

Expand Down
2 changes: 2 additions & 0 deletions apps/storyblok/.env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ NEXT_PUBLIC_STORYBLOK_API_GATE="https://api.storyblok.com/v2/cdn"
# 3. "Deploy Hooks" section
# 4. create and paste deploy hook
VERCEL_REDEPLOY_HOOK_URL="https://api.vercel.com/v1/integrations/deploy/[KEY]/[KEY]"

SB_WEBHOOK_REVALIDATE_SECRET="YOUR_SECRET"
49 changes: 34 additions & 15 deletions apps/storyblok/CLI/sb.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { execSync } from "child_process";
import fs from "fs";
import ora from "ora";

import {
createAccessToken,
createStoryblokSpace,
createStoryblokWebhook,
updatePageComponentSectionsField,
Expand All @@ -12,7 +14,7 @@ import {
createProjectDeployment,
createVercelProject,
} from "./services/vercel.mjs";
import { modifyFile } from "./utils/file.mjs";
import { modifyJsonFile, replaceTextInFile } from "./utils/file.mjs";
import { openUrlAndConfirm } from "./utils/open.mjs";
import {
promptForProjectName,
Expand Down Expand Up @@ -80,8 +82,13 @@ const main = async () => {
await uploadBackupStories(spaceId);
spinner.succeed("Successfully filled new space with data 🎉");

// Create Vercel production and preview projects
console.log(
"Creating public storyblok token for production environment ⏳",
);
const { token: publicToken } = await createAccessToken(spaceId, "public");
console.log("Successfully created public storyblok token ✅");

// Create Vercel production and preview projects
spinner.start("Creating Vercel production and preview projects ⏳");
const whRevalidateSecret = crypto.randomUUID();
const {
Expand All @@ -92,8 +99,7 @@ const main = async () => {
projectName,
sbParams: {
isPreview: false,
spaceId,
previewToken,
storyblokToken: publicToken,
whRevalidateSecret,
},
});
Expand All @@ -106,8 +112,7 @@ const main = async () => {
projectName,
sbParams: {
isPreview: true,
spaceId,
previewToken,
storyblokToken: previewToken,
whRevalidateSecret,
},
});
Expand All @@ -119,7 +124,7 @@ const main = async () => {

spinner.start("Updating Storyblok space with Vercel data⏳");
await updateStoryblokSpace(spaceId, {
domain: `${previewDeploymentUrl}/`,
domain: `${previewDeploymentUrl}/live-preview/`,
});
await createStoryblokWebhook(
spaceId,
Expand All @@ -142,16 +147,30 @@ const main = async () => {
"Successfully created Vercel production and preview deployments 🎉",
);

spinner.start("Updating apps/storyblok/package.json ⏳");
modifyFile("../package.json", "293915", spaceId);
spinner.succeed("apps/storyblok/package.json updated ✅");
if (!process.env.DEBUG) {
spinner.start("Removing unrelated files and scripts ⏳");
execSync("rm -rf ../../sanity", {
stdio: "ignore",
});

spinner.start("Removing unrelated files and scripts ⏳");
execSync("rm -rf ../../sanity", {
stdio: "ignore",
});
execSync("rm -rf ../src/generated/dump", {
stdio: "ignore",
});

replaceTextInFile("../package.json", "293915", spaceId);
// remove pull-schemas script from package.json
modifyJsonFile("../package.json", (contentJson) => {
delete contentJson.scripts["pull-stories"];

return contentJson;
});

execSync("git add . && git commit -m 'Cleanup' && git push", {
stdio: "ignore",
});

spinner.succeed("Sanity folder removed ✅");
spinner.succeed("Sanity folder removed ✅");
}

console.log(
colorText(
Expand Down
85 changes: 68 additions & 17 deletions apps/storyblok/CLI/services/storyblok.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ async function getSectionsFolder(spaceId) {
}

const globalComponentNames = ["header", "footer"];

export async function uploadBackupStories(spaceId) {
// Get directory path relative to current file
const __filename = fileURLToPath(import.meta.url);
Expand All @@ -205,30 +206,51 @@ export async function uploadBackupStories(spaceId) {
}),
);

const { parentStories, childStories, globalComponents } = stories.reduce(
(acc, story) => {
if (story.is_folder) {
acc.parentStories.push(story);
} else {
if (globalComponentNames.includes(story.content.component)) {
acc.globalComponents.push(story);
const { parentFoldersStories, pageStories, globalComponentsStories } =
stories.reduce(
(acc, story) => {
if (story.is_folder) {
acc.parentFoldersStories.push(story);
} else {
acc.childStories.push(story);
if (globalComponentNames.includes(story.content.component)) {
acc.globalComponentsStories.push(story);
} else {
acc.pageStories.push(story);
}
}
}

return acc;
},
{ parentStories: [], childStories: [], globalComponents: [] },
);
return acc;
},
{
pageStories: [],
parentFoldersStories: [],
globalComponentsStories: [],
},
);

// Map to track old ID to new ID relationships
const idMap = new Map();

// since all folders are inside components/ folder, it should be created first
const sortedParentFoldersStories = parentFoldersStories.sort((a, b) => {
if (a.slug === "components") return -1;
if (b.slug === "components") return 1;

return 0;
});

// Create all parent stories first
for (const story of parentStories) {
for (const story of sortedParentFoldersStories) {
try {
const newStory = await createStory(spaceId, story);
const newParentId = idMap.get(story.parent_id) || null;

const storyData = {
...story,
content: story.content,
parent_id: newParentId,
};

const newStory = await createStory(spaceId, storyData);
idMap.set(story.id, newStory.story.id);
} catch (error) {
console.error(`Failed to create parent story: ${error.message}`);
Expand All @@ -240,7 +262,7 @@ export async function uploadBackupStories(spaceId) {
let headerUuid = null;
let footerUuid = null;

for (const story of globalComponents) {
for (const story of globalComponentsStories) {
// Update the parent_id to use the new ID
const newParentId = idMap.get(story.parent_id) || null;

Expand All @@ -260,7 +282,7 @@ export async function uploadBackupStories(spaceId) {
}

// Create child stories with updated parent IDs
for (const story of childStories) {
for (const story of pageStories) {
try {
// Update the parent_id to use the new ID
const newParentId = idMap.get(story.parent_id) || null;
Expand Down Expand Up @@ -375,3 +397,32 @@ export async function updateStory(spaceId, storyId, storyData) {

return data;
}

export async function createAccessToken(spaceId, access = "public") {
const envs = loadEnvVariables();
const token = envs.SB_PERSONAL_ACCESS_TOKEN;

const response = await fetch(
`https://mapi.storyblok.com/v1/spaces/${spaceId}/api_keys/`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: token,
},
body: JSON.stringify({
api_key: {
access,
name: `${access} access Token`,
},
}),
},
);

if (!response.ok) {
console.log(response.status, response.statusText, await response.json());
throw new Error(`❌ HTTP error! Status: ${response.status}`);
}

return await response.json();
}
37 changes: 3 additions & 34 deletions apps/storyblok/CLI/services/vercel.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,10 @@ export async function getVercelUserInfo() {
}

export async function createVercelProject({ projectName, sbParams }) {
const { isPreview, spaceId, previewToken, whRevalidateSecret } = sbParams;
const { isPreview, storyblokToken, whRevalidateSecret } = sbParams;
const envs = loadEnvVariables();
const repoName = envs.REPO_NAME;
const vercelToken = envs.VERCEL_PERSONAL_AUTH_TOKEN;
const repoId = envs.REPO_ID;
const repoType = envs.REPO_TYPE;
const repoProdBranch = envs.REPO_PROD_BRANCH;
// const rollOutApiToken = envs.ROLL_OUT_API_TOKEN;
const vercelTeamId = envs.VERCEL_TEAM_ID;

Expand All @@ -86,49 +83,21 @@ export async function createVercelProject({ projectName, sbParams }) {
value: `https://${finalProjectName}.vercel.app`,
},
{
key: "NEXT_PUBLIC_DOMAIN",
value: `https://${finalProjectName}.vercel.app`,
},
{
key: "NEXT_PUBLIC_API_GATE",
key: "NEXT_PUBLIC_STORYBLOK_API_GATE",
value: "https://api.storyblok.com/v2/cdn",
},
{
key: "NEXT_PUBLIC_IS_PREVIEW",
value: isPreview ? "true" : "false",
},
{
key: "NEXT_PUBLIC_SB_REGION",
value: "EU",
},
{
key: "NEXT_PUBLIC_STORYBLOK_TOKEN",
value: previewToken,
value: storyblokToken,
},
{
key: "SB_WEBHOOK_REVALIDATE_SECRET",
value: whRevalidateSecret,
},
{
key: "SB_SPACE_ID",
value: spaceId + "",
},
{
key: "REPO_ID",
value: repoId,
},
{
key: "REPO_TYPE",
value: repoType,
},
{
key: "REPO_PROD_BRANCH",
value: repoProdBranch,
},
// {
// key: "ROLL_OUT_API_TOKEN",
// value: rollOutApiToken,
// },
].map((v) => ({
...v,
target: ["production", "preview", "development"],
Expand Down
15 changes: 14 additions & 1 deletion apps/storyblok/CLI/utils/file.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from "fs";

export function modifyFile(path, oldText, newText) {
export function replaceTextInFile(path, oldText, newText) {
fs.readFile(path, "utf8", (err, data) => {
if (err) {
console.error(err);
Expand All @@ -17,3 +17,16 @@ export function modifyFile(path, oldText, newText) {
});
});
}

export function modifyJsonFile(path, transformer) {
try {
const data = fs.readFileSync(path, "utf8");
const content = JSON.parse(data);
const modifiedContent = transformer(content);

fs.writeFileSync(path, JSON.stringify(modifiedContent, null, 2) + "\n");
} catch (err) {
console.error(err);
return;
}
}
4 changes: 3 additions & 1 deletion apps/storyblok/CLI/utils/prompts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,7 @@ export async function promptForProjectName() {
default: "nextjs-storyblok-fast",
});

return projectName;
const hash = Math.random().toString(36).substring(2, 7);

return `${projectName}-${hash}`;
}
22 changes: 9 additions & 13 deletions apps/storyblok/src/components/SectionContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,15 @@ export default function SectionContainer({
return (
<section
{...storyblokEditable(blok)}
className={cn(
"bg-bgColor overflow-x-hidden",
className,
backgroundColor,
{
"mt-0": marginTop === "none",
"mb-0": marginBottom === "none",
"mt-sectionBase": marginTop === "base",
"mb-sectionBase": marginBottom === "base",
"mt-sectionLg": marginTop === "lg",
"mb-sectionLg": marginBottom === "lg",
},
)}
className={cn("overflow-x-hidden", className, backgroundColor, {
"bg-bgColor": backgroundColor && backgroundColor !== "none",
"mt-0": marginTop === "none",
"mb-0": marginBottom === "none",
"mt-sectionBase": marginTop === "base",
"mb-sectionBase": marginBottom === "base",
"mt-sectionLg": marginTop === "lg",
"mb-sectionLg": marginBottom === "lg",
})}
id={_uid}
style={style}
>
Expand Down
Loading

0 comments on commit 69f9f50

Please sign in to comment.