8000 Merge pull request #8 from coderoad/feature/version · coderoad/coderoad-cli@ecb6e5e · GitHub
[go: up one dir, main page]

Skip to content

Commit ecb6e5e

Browse files
authored
Merge pull request #8 from coderoad/feature/version
Feature/version
2 parents d53c378 + a7d615b commit ecb6e5e

File tree

11 files changed

+439
-408
lines changed
  • utils
  • tests
  • typings
  • 11 files changed

    +439
    -408
    lines changed

    package-lock.json

    Lines changed: 1 addition & 1 deletion
    Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

    package.json

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,6 @@
    11
    {
    22
    "name": "@coderoad/cli",
    3-
    "version": "0.0.3",
    3+
    "version": "0.0.4",
    44
    "description": "A CLI to build the configuration file for Coderoad Tutorials",
    55
    "main": "src/main.js",
    66
    "bin": {

    src/build.ts

    Lines changed: 57 additions & 174 deletions
    Original file line numberDiff line numberDiff line change
    @@ -2,197 +2,80 @@ import * as yamlParser from "js-yaml";
    22
    import * as path from "path";
    33
    import * as _ from "lodash";
    44
    import * as fs from "fs";
    5-
    import * as T from "../typings/tutorial";
    5+
    import * as util from "util";
    66
    import { parse } from "./utils/parse";
    7-
    // import validate from './validator';
    8-
    9-
    // import not working
    10-
    const simpleGit = require("simple-git/promise");
    11-
    12-
    const workingDir = "tmp";
    13-
    14-
    function rmDir(dir: string, rmSelf = false) {
    15-
    try {
    16-
    let files;
    17-
    rmSelf = rmSelf === undefined ? true : rmSelf;
    18-
    19-
    try {
    20-
    files = fs.readdirSync(dir);
    21-
    } catch (e) {
    22-
    console.log(`Sorry, directory '${dir}' doesn't exist.`);
    23-
    return;
    24-
    }
    25-
    26-
    if (files.length > 0) {
    27-
    files.forEach(function (filePath: string) {
    28-
    if (fs.statSync(path.join(dir, filePath)).isDirectory()) {
    29-
    rmDir(path.join(dir, filePath));
    30-
    } else {
    31-
    fs.unlinkSync(path.join(dir, filePath));
    32-
    }
    33-
    });
    34-
    }
    35-
    36-
    if (rmSelf) {
    37-
    // check if user want to delete the directory ir just the files in this directory
    38-
    fs.rmdirSync(dir);
    39-
    }
    40-
    } catch (error) {
    41-
    return error;
    42-
    }
    43-
    }
    7+
    import { getArg } from "./utils/args";
    8+
    import { getCommits, CommitLogObject } from "./utils/commits";
    9+
    import * as T from "../typings/tutorial";
    4410

    45-
    async function cleanupFiles(workingDir: string) {
    46-
    try {
    47-
    const gitModule = simpleGit(process.cwd());
    11+
    const write = util.promisify(fs.writeFile);
    12+
    const read = util.promisify(fs.readFile);
    4813

    49-
    await gitModule.subModule(["deinit", "-f", workingDir]);
    50-
    await gitModule.rm(workingDir);
    51-
    await gitModule.reset(["HEAD"]);
    52-
    rmDir(path.join(process.cwd(), ".git", "modules", workingDir));
    53-
    rmDir(workingDir);
    54-
    } catch (error) {
    55-
    return error;
    56-
    }
    57-
    }
    14+
    export type BuildConfigOptions = {
    15+
    text: string; // text document from markdown
    16+
    config: T.Tutorial; // yaml config file converted to json
    17+
    commits: CommitLogObject; // an object of tutorial positions with a list of commit hashes
    18+
    };
    5819

    59-
    export type BuildOptions = {
    60-
    repo: string; // Git url to the repo. It should finish with .git
    61-
    codeBranch: string; // The branch containing the tutorial code
    62-
    setupBranch: string; // The branch containing the tutorialuration files
    63-
    isLocal: boolean; // define if the repo is local or remote
    20+
    type BuildArgs = {
    21+
    dir: string;
    22+
    markdown: string;
    23+
    yaml: string;
    6424
    output: string;
    6525
    };
    6626

    67-
    async function build({ repo, codeBranch, setupBranch, isLocal }: BuildOptions) {
    68-
    let git: any;
    69-
    let isSubModule = false;
    70-
    let localPath: string;
    71-
    72-
    if (isLocal) {
    73-
    git = simpleGit(repo);
    74-
    localPath = repo;
    75-
    } else {
    76-
    const gitTest = simpleGit(process.cwd());
    77-
    const isRepo = await gitTest.checkIsRepo();
    78-
    localPath = path.join(process.cwd(), workingDir);
    79-
    80-
    if (isRepo) {
    81-
    await gitTest.submoduleAdd(repo, workingDir);
    82-
    83-
    isSubModule = true;
    84-
    } else {
    85-
    await gitTest.clone(repo, localPath);
    86-
    }
    87-
    88-
    git = simpleGit(localPath);
    89-
    }
    90-
    91-
    await git.fetch();
    92-
    93-
    // checkout the branch to load tutorialuration and content branch
    94-
    await git.checkout(setupBranch);
    95-
    96-
    // Load files
    97-
    const _content = fs.readFileSync(path.join(localPath, "TUTORIAL.md"), "utf8");
    98-
    let _config = fs.readFileSync(path.join(localPath, "coderoad.yaml"), "utf8");
    99-
    100-
    const tutorial = parse(_content, _config);
    101-
    102-
    // Checkout the code branches
    103-
    await git.checkout(codeBranch);
    104-
    105-
    // Load all logs
    106-
    const logs = await git.log();
    27+
    const parseArgs = (args: string[]): BuildArgs => {
    28+
    // default .
    29+
    const dir = args[0] || ".";
    30+
    // -o --output - default coderoad.json
    31+
    const output =
    32+
    getArg(args, { name: "output", alias: "o" }) || "coderoad.json";
    33+
    // -m --markdown - default TUTORIAL.md
    34+
    const markdown =
    35+
    getArg(args, { name: "markdown", alias: "m" }) || "TUTORIAL.md";
    36+
    // -y --yaml - default coderoad-config.yml
    37+
    const yaml =
    38+
    getArg(args, { name: "coderoad-config.yml", alias: "y" }) ||
    39+
    "coderoad-config.yml";
    40+
    41+
    return {
    42+
    dir,
    43+
    output,
    44+
    markdown,
    45+
    yaml,
    46+
    };
    47+
    };
    10748

    108-
    // Filter relevant logs
    109-
    const parts = new Set();
    49+
    async function build(args: string[]) {
    50+
    const options = parseArgs(args);
    11051

    111-
    for (const commit of logs.all) {
    112-
    const matches = commit.message.match(
    113-
    /^(?<stepId>(?<levelId>L\d+)S\d+)(?<stepType>[QA])?/
    114-
    );
    52+< 87FD /span>
    // path to run build from
    53+
    const localPath = path.join(process.cwd(), options.dir);
    11554

    116-
    if (matches && !parts.has(matches[0])) {
    117-
    // Uses a set to make sure only the latest commit is proccessed
    118-
    parts.add(matches[0]);
    55+
    // load files
    56+
    const [_markdown, _yaml] = await Promise.all([
    57+
    read(path.join(localPath, options.markdown), "utf8"),
    58+
    read(path.join(localPath, options.yaml), "utf8"),
    59+
    ]);
    11960

    120-
    // Add the content and git hash to the tutorial
    121-
    if (matches.groups.stepId) {
    122-
    // If it's a step: add the content and the setup/solution hashes depending on the type
    123-
    const level: T.Level | null =
    124-
    tutorial.levels.find(
    125-
    (level: T.Level) => level.id === matches.groups.levelId
    126-
    ) || null;
    127-
    if (!level) {
    128-
    console.log(`Level ${matches.groups.levelId} not found`);
    129-
    } else {
    130-
    const theStep: T.Step | null =
    131-
    level.steps.find(
    132-
    (step: T.Step) => step.id === matches.groups.stepId
    133-
    ) || null;
    61+
    const config = yamlParser.load(_yaml);
    13462

    135-
    if (!theStep) {
    136-
    console.log(`Step ${matches.groups.stepId} not found`);
    137-
    } else {
    138-
    if (matches.groups.stepType === "Q") {
    139-
    theStep.setup.commits.push(commit.hash.substr(0, 7));
    140-
    } else if (
    141-
    matches.groups.stepType === "A" &&
    142-
    theStep.solution &&
    143-
    theStep.solution.commits
    144-
    ) {
    145-
    theStep.solution.commits.push(commit.hash.substr(0, 7));
    146-
    }
    147-
    }
    148-
    }
    149-
    } else {
    150-
    // If it's level: add the commit hash (if the level has the commit key) and the content to the tutorial
    151-
    const theLevel: T.Level | null =
    152-
    tutorial.levels.find(
    153-
    (level: T.Level) => level.id === matches.groups.levelId
    154-
    ) || null;
    63+
    const commits: CommitLogObject = await getCommits(config.config.repo.branch);
    15564

    156-
    if (!theLevel) {
    157-
    console.log(`Level ${matches.groups.levelId} not found`);
    158-
    } else {
    159-
    if (_.has(theLevel, "tutorial.commits")) {
    160-
    if (theLevel.setup) {
    161-
    theLevel.setup.commits.push(commit.hash.substr(0, 7));
    162-
    }
    163-
    }
    164-
    }
    165-
    }
    166-
    }
    167-
    }
    65+
    // Otherwise, continue with the other options
    66+
    const tutorial: T.Tutorial = await parse({
    67+
    text: _markdown,
    68+
    config,
    69+
    commits,
    70+
    });
    16871

    169-
    // cleanup the submodules
    170-
    if (!isLocal) {
    171-
    let cleanupErr;
    172-
    173-
    if (isSubModule) {
    174-
    cleanupErr = await cleanupFiles(workingDir);
    72+
    if (tutorial) {
    73+
    if (options.output) {
    74+
    await write(options.output, JSON.stringify(tutorial), "utf8");
    17575
    } else {
    176-
    cleanupErr = rmDir(path.join(process.cwd(), workingDir));
    177-
    }
    178-
    179-
    if (cleanupErr) {
    180-
    console.log(
    181-
    `Error when deleting temporary files on ${
    182-
    isSubModule ? "module" : "folder"
    183-
    } ${workingDir}.`
    184-
    );
    76+
    console.log(JSON.stringify(tutorial, null, 2));
    18577
    }
    18678
    }
    187-
    188-
    // const isValid = validate(tutorial);
    189-
    190-
    // if (!isValid) {
    191-
    // console.log(JSON.stringify(validate.errors, null, 2));
    192-
    // return;
    193-
    // }
    194-
    195-
    return tutorial;
    19679
    }
    19780

    19881
    export default build;

    0 commit comments

    Comments
     (0)
    0