From fc6f94f111f418d0a39c7b06b033da7ece70b3d2 Mon Sep 17 00:00:00 2001 From: Bradford Powell Date: Thu, 26 Sep 2024 00:47:26 -0400 Subject: [PATCH] refactor(cli): keep alteration scripts folder writable by gid 0 (#6328) facilitates running in rootless container with r/w mounted alteration-scripts directory (fixed #6327) --- Dockerfile | 1 + .../src/commands/database/alteration/utils.ts | 23 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index ecce9c4c4..8635cac4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,6 +40,7 @@ RUN rm -rf .scripts pnpm-*.yaml packages/cloud FROM node:20-alpine as app WORKDIR /etc/logto COPY --from=builder /etc/logto . +RUN mkdir -p /etc/logto/packages/cli/alteration-scripts && chmod g+w /etc/logto/packages/cli/alteration-scripts EXPOSE 3001 ENTRYPOINT ["npm", "run"] CMD ["start"] diff --git a/packages/cli/src/commands/database/alteration/utils.ts b/packages/cli/src/commands/database/alteration/utils.ts index 09242b7dc..4672858d6 100644 --- a/packages/cli/src/commands/database/alteration/utils.ts +++ b/packages/cli/src/commands/database/alteration/utils.ts @@ -44,8 +44,27 @@ export const getAlterationFiles = async (): Promise => { } // We need to copy alteration files to execute in the CLI context to make `slonik` available - await fs.rm(localAlterationDirectory, { force: true, recursive: true }); - await fs.cp(alterationDirectory, localAlterationDirectory, { recursive: true }); + // Notice that we don't remove the folder, + // this ensures that the writabiliy remains (and also allows this to be a separately-mounted directory. + if (!existsSync(localAlterationDirectory)) { + await fs.mkdir(localAlterationDirectory, { recursive: true }); + } + + const oldFiles = await fs.readdir(localAlterationDirectory); + await Promise.all( + oldFiles.map(async (file) => + fs.rm(path.join(localAlterationDirectory, file), { force: true, recursive: true }) + ) + ); + const newFiles = await fs.readdir(alterationDirectory); + await Promise.all( + newFiles.map(async (file) => + fs.cp(path.join(alterationDirectory, file), path.join(localAlterationDirectory, file), { + recursive: true, + preserveTimestamps: true, + }) + ) + ); const directory = await fs.readdir(localAlterationDirectory); const files = directory.filter((file) => alterationFilenameRegex.test(file));