feat(scaffolder): Implementing the VCS steps in the processor
This commit is contained in:
+1
-5
@@ -1,7 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Move all template files to the root folder
|
||||
mv ./* ../
|
||||
cd ..
|
||||
rm -rf {{cookiecutter.component_id}}
|
||||
# # # # # # # #
|
||||
echo "Could do something here?"
|
||||
|
||||
+1
-4
@@ -1,9 +1,6 @@
|
||||
name: Frontend CI
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.'
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -43,6 +43,7 @@ export class FilePreparer implements PreparerBase {
|
||||
|
||||
await fs.copy(parentDirectory, tempDir, {
|
||||
filter: src => src !== location,
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
return tempDir;
|
||||
|
||||
@@ -13,3 +13,64 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Storer } from './types';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import { JsonValue } from '@backstage/config';
|
||||
import { RequiredTemplateValues } from '../templater';
|
||||
import { Repository, Remote, Signature, Cred } from 'nodegit';
|
||||
import gitUrlParse from 'git-url-parse';
|
||||
|
||||
export class GithubStorer implements Storer {
|
||||
private client: Octokit;
|
||||
constructor({ client }: { client: Octokit }) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async createRemote({
|
||||
values,
|
||||
}: {
|
||||
entity: TemplateEntityV1alpha1;
|
||||
values: RequiredTemplateValues & Record<string, JsonValue>;
|
||||
}) {
|
||||
const {
|
||||
data: { clone_url: cloneUrl },
|
||||
} = await this.client.repos.createInOrg({
|
||||
name: values.component_id,
|
||||
org: values.org as string,
|
||||
});
|
||||
|
||||
console.warn(cloneUrl);
|
||||
|
||||
return cloneUrl;
|
||||
}
|
||||
|
||||
async pushToRemote(directory: string, remote: string): Promise<void> {
|
||||
const repo = await Repository.init(directory, 0);
|
||||
const index = await repo.refreshIndex();
|
||||
await index.addAll();
|
||||
await index.write();
|
||||
const oid = await index.writeTree();
|
||||
await repo.createCommit(
|
||||
'HEAD',
|
||||
Signature.now('Foo bar', 'foo@bar.com'),
|
||||
Signature.now('Foo bar', 'foo@bar.com'),
|
||||
'initial commit',
|
||||
oid,
|
||||
[],
|
||||
);
|
||||
|
||||
const remoteRepo = await Remote.create(repo, 'origin', remote);
|
||||
await remoteRepo.push(['refs/heads/master:refs/heads/master'], {
|
||||
callbacks: {
|
||||
credentials: () => {
|
||||
return Cred.userpassPlaintextNew(
|
||||
process.env.GITHUB_ACCESS_TOKEN as string,
|
||||
'x-oauth-basic',
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { TemplateEntityV1alpha1 } from "@backstage/catalog-model";
|
||||
import { RequiredTemplateValues } from "../templater";
|
||||
import { JsonValue } from "@backstage/config";
|
||||
|
||||
export type Storer = {
|
||||
createRemote(opts: { entity: TemplateEntityV1alpha1, values: RequiredTemplateValues & Record<string, JsonValue>}): Promise<string>;
|
||||
pushToRemote(directory: string, remote: string): Promise<void>;
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { TemplaterBase, TemplaterRunOptions } from '.';
|
||||
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
@@ -18,7 +16,8 @@ import { TemplaterBase, TemplaterRunOptions } from '.';
|
||||
import fs from 'fs-extra';
|
||||
import { JsonValue } from '@backstage/config';
|
||||
import { runDockerContainer } from './helpers';
|
||||
|
||||
import { TemplaterBase, TemplaterRunOptions } from '.';
|
||||
import path from 'path';
|
||||
export class CookieCutter implements TemplaterBase {
|
||||
private async fetchTemplateCookieCutter(
|
||||
directory: string,
|
||||
@@ -66,6 +65,6 @@ export class CookieCutter implements TemplaterBase {
|
||||
dockerClient: options.dockerClient,
|
||||
});
|
||||
|
||||
return resultDir;
|
||||
return path.resolve(resultDir, options.values.component_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import Docker from 'dockerode';
|
||||
import {} from '@backstage/backend-common';
|
||||
import { StageContext } from '../scaffolder/jobs/types';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { GithubStorer } from '../scaffolder/stages/store/github';
|
||||
export interface RouterOptions {
|
||||
preparers: PreparerBuilder;
|
||||
templater: TemplaterBase;
|
||||
@@ -33,9 +35,11 @@ export async function createRouter(
|
||||
options: RouterOptions,
|
||||
): Promise<express.Router> {
|
||||
const router = Router();
|
||||
const { preparers, templater, logger: parentLogger, dockerClient } = options;
|
||||
const logger = parentLogger.child({ plugin: 'scaffolder' });
|
||||
|
||||
const githubClient = new Octokit({ auth: process.env.GITHUB_ACCESS_TOKEN });
|
||||
const { preparers, templater, logger: parentLogger, dockerClient } = options;
|
||||
const githubStorer = new GithubStorer({ client: githubClient });
|
||||
const logger = parentLogger.child({ plugin: 'scaffolder' });
|
||||
const jobProcessor = new JobProcessor();
|
||||
|
||||
router
|
||||
@@ -83,7 +87,7 @@ export async function createRouter(
|
||||
metadata: {
|
||||
annotations: {
|
||||
'backstage.io/managed-by-location':
|
||||
'github:https://github.com/benjdlambert/backstage-graphql-template/blob/master/template.yaml',
|
||||
'file:/Users/blam/dev/spotify/backstage/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml',
|
||||
},
|
||||
name: 'graphql-starter',
|
||||
title: 'GraphQL Service',
|
||||
@@ -96,13 +100,17 @@ export async function createRouter(
|
||||
},
|
||||
spec: {
|
||||
type: 'cookiecutter',
|
||||
path: './template',
|
||||
path: '.',
|
||||
},
|
||||
};
|
||||
|
||||
const job = jobProcessor.create({
|
||||
entity: mockEntity,
|
||||
values: { component_id: 'blob' },
|
||||
values: {
|
||||
component_id: `blob${Date.now()}`,
|
||||
org: 'hojden',
|
||||
description: 'test',
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
name: 'Prepare the skeleton',
|
||||
@@ -131,12 +139,21 @@ export async function createRouter(
|
||||
name: 'Create VCS Repo',
|
||||
handler: async (ctx: StageContext<{ resultDir: string }>) => {
|
||||
ctx.logger.info('Should now create the VCS repo');
|
||||
const remoteUrl = await githubStorer.createRemote({
|
||||
values: ctx.values,
|
||||
entity: ctx.entity,
|
||||
});
|
||||
|
||||
return { remoteUrl };
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Push to remote',
|
||||
handler: async ctx => {
|
||||
handler: async (
|
||||
ctx: StageContext<{ resultDir: string; remoteUrl: string }>,
|
||||
) => {
|
||||
ctx.logger.info('Should now push to the remote');
|
||||
await githubStorer.pushToRemote(ctx.resultDir, ctx.remoteUrl);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user