Repository: spotify/backstage
File: plugins/scaffolder-backend-module-gitlab/src/actions/gitlabRepoPush.ts (TypeScript)

Code before:

      const fileContents = await serializeDirectoryContents(fileRoot, {
        gitignore: true,
      });

      let remoteFiles: RepositoryTreeSchema[] = [];
      if ((ctx.input.commitAction ?? 'auto') === 'auto') {
        try {
          remoteFiles = await api.Repositories.allRepositoryTrees(repoID, {
            ref: branchName,
            recursive: true,
            path: targetPath ?? undefined,
          });
        } catch (e) {
          ctx.logger.warn(
            `Could not retrieve the list of files for ${repoID} (branch: ${branchName}) : ${getErrorMessage(
              e,
            )}`,
          );
        }
      }

      const actions: CommitAction[] = (
        (
          await Promise.all(
            fileContents.map(async file => {
              const action = await getFileAction(
                { file, targetPath },
                { repoID, branch: branchName },
                api,
                ctx.logger,
                remoteFiles,
                ctx.input.commitAction,
              );
              return { file, action };
            }),
          )
        ).filter(o => o.action !== 'skip') as {
          file: SerializedFile;
          action: CommitAction['action'];
        }[]
      ).map(({ file, action }) => ({
        action,
        filePath: targetPath
          ? path.posix.join(targetPath, file.path)
          : file.path,
        encoding: 'base64',
        content: file.content.toString('base64'),
        execute_filemode: file.executable,
      }));


Review comment (refactor):
Im a little concerned that this could throw a lot of requests of to gitlab in parallel. Should we move this to do something like:

```ts

for (const file of fileContents) {
   const action = await getFileAction(...)
}
```

Instead so that it least it does one at a time?

Or use something like `p-limit` to make sure that we only send of a few in parallel rather than for every file in the workspace?

Code after:

      const fileContents = await serializeDirectoryContents(fileRoot, {
        gitignore: true,
      });

      let remoteFiles: RepositoryTreeSchema[] = [];
      if ((ctx.input.commitAction ?? 'auto') === 'auto') {
        try {
          remoteFiles = await api.Repositories.allRepositoryTrees(repoID, {
            ref: branchName,
            recursive: true,
            path: targetPath ?? undefined,
          });
        } catch (e) {
          ctx.logger.warn(
            `Could not retrieve the list of files for ${repoID} (branch: ${branchName}) : ${getErrorMessage(
              e,
            )}`,
          );
        }
      }

      const fileActionMap: {
        file: SerializedFile;
        action: 'create' | 'delete' | 'update' | 'skip';
      }[] = [];
      for (const file of fileContents) {
        const action = await getFileAction(
          { file, targetPath },
          { repoID, branch: branchName },
          api,
          ctx.logger,
          remoteFiles,
          ctx.input.commitAction,
        );
        fileActionMap.push({ file, action });
      }

      const actions: CommitAction[] = fileActionMap
        .filter(o => o.action !== 'skip')
        .map(({ file, action }) => ({
          action: action as CommitAction['action'],
          filePath: targetPath
            ? path.posix.join(targetPath, file.path)
            : file.path,
          encoding: 'base64',
          content: file.content.toString('base64'),
          execute_filemode: file.executable,
        }));

      const branchExists = await ctx.checkpoint({