generateRepo function

Future<void> generateRepo(
  1. GitlabClient gl,
  2. String studyId
)

Implementation

Future<void> generateRepo(GitlabClient gl, String studyId) async {
  print('Generating repo...');
  final dotEnv = DotEnv()..load();
  final generatedProjectPath = dotEnv['STUDYU_PROJECT_PATH'] ?? 'generated';

  // Fetch study schema and subjects data
  print('Fetching study data...');
  final study = await fetchStudySchema(studyId);
  final subjects = await fetchSubjects(studyId);

  print('Creating gitlab repo ${study.title}');
  // Create Gitlab project
  final projectProperties = await gl.createProject(study.title!);
  if (projectProperties == null) {
    print('Could not create project');
    return;
  }
  final projectId = (projectProperties['id'] as int).toString();

  // Generate ssh key
  print('Generating RSA key pair...');
  try {
    File('gitlabkey.pub').deleteSync();
    File('gitlabkey').deleteSync();
  } catch (e) {
    print(e);
  }
  await cliGenerateSshKey();
  final public = File('gitlabkey.pub').readAsStringSync();
  final private = File('gitlabkey').readAsStringSync();

  print('Adding deploy key...');
  await gl.addDeployKey(projectId: projectId, title: 'update_key', key: public, canPush: true);

  print('Creating project variables for session, studyId and key');
  // session cannot be masked due to format
  await gl.createProjectVariable(
    projectId: projectId,
    key: 'session',
    value: env.client.auth.session()!.persistSessionString,
  );
  await gl.createProjectVariable(projectId: projectId, key: 'study_id', value: studyId, masked: true);
  // Key cannot be masked due to format
  await gl.createProjectVariable(projectId: projectId, key: 'key', value: private);

  print('Creating project environment variables for supabase');
  await gl.createProjectVariable(
    projectId: projectId,
    key: 'STUDYU_SUPABASE_URL',
    value: env.supabaseUrl,
    masked: true,
  );
  await gl.createProjectVariable(
    projectId: projectId,
    key: 'STUDYU_SUPABASE_PUBLIC_ANON_KEY',
    value: env.supabaseAnonKey,
    masked: true,
  );

  // Generate files from nbconvert-template copier CLI
  print('Generating project files with copier...');
  final scaleQuestionIds = study.observations.expand((observation) {
    return (observation as QuestionnaireTask)
        .questions
        .questions
        .where((q) => q.type == AnnotatedScaleQuestion.questionType || q.type == VisualAnalogueQuestion.questionType)
        .map((q) => q.id);
  }).toList(growable: false);
  await cliGenerateCopierProject(
    generatedProjectPath,
    study.title!,
    scaleQuestionIds,
    Uri.encodeComponent(projectProperties['http_url_to_repo'] as String),
  );

  // Save study schema and subjects data
  print('Saving study schema and subjects as json...');
  await File(p.join(generatedProjectPath, 'data', 'study.schema.json')).writeAsString(prettyJson(study.toJson()));
  await File(p.join(generatedProjectPath, 'data', 'subjects.csv')).writeAsString(subjects);

  // Read all files in generated and make commit
  print('Collecting files into Gitlab commit...');
  final commitActions = allFilesInDir(generatedProjectPath).map((file) {
    final unixFilePath =
        p.Context(style: p.Style.posix).joinAll(p.split(p.relative(file.path, from: generatedProjectPath)));

    return gl.commitAction(filePath: unixFilePath, content: file.readAsStringSync());
  }).toList();

  print('Committing to Gitlab...');
  await gl.makeCommit(
    projectId: projectId,
    message: 'Generated project from copier-studyu\n\nhttps://github.com/hpi-studyu/copier-studyu',
    actions: commitActions,
  );

  print('Add repo entry to database...');
  try {
    await Repo(
      projectId,
      env.client.auth.user()!.id,
      studyId,
      GitProvider.gitlab,
      projectProperties['web_url'] as String,
      projectProperties['http_url_to_repo'] as String,
    ).save();
  } catch (e) {
    print(e);
  }

  print('Deleting generated files...');
  File(generatedProjectPath).deleteSync(recursive: true);
  print('Finished generating project');
}