Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

try to get deploy into a more testable state #590

Merged
merged 1 commit into from
Jul 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion csv/format/BUILD
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# empty
# empty
9 changes: 4 additions & 5 deletions csv/format/rules.bzl
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@

def csv_format(name, src = None, out = None, separator = ",", **kwargs):
if out == None:
out = src + "_formatted.csv"

native.genrule(
name = name,
exec_tools = [ "//go/cmd/csvpretty:csvpretty" ],
exec_tools = ["//go/cmd/csvpretty:csvpretty"],
cmd_bash = """
$(execpath //go/cmd/csvpretty:csvpretty) \\
--input "$<" \\
--output "$@" \\
--comma \"""" + separator + """\"
""",
outs = [ out ],
srcs = [ src ],
outs = [out],
srcs = [src],
**kwargs
)
)
5 changes: 2 additions & 3 deletions csv/lint/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ def csv_lint_test(name, srcs = [], **kwargs):
file1 = name + src + "_format",
file2 = src,
)

native.test_suite(
name = name,
tests = [name + src + "_test" for src in srcs ]
tests = [name + src + "_test" for src in srcs],
)

4 changes: 2 additions & 2 deletions csv/lint/testing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ load("//csv/lint:rules.bzl", "csv_lint_test")

csv_lint_test(
name = "test",
srcs = [ "test_out.csv" ]
)
srcs = ["test_out.csv"],
)
2 changes: 1 addition & 1 deletion deploy/deploy_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import program from './program';

test('deploy', async () => {
process.env.NPM_TOKEN = '123fake';
await program.parseAsync(['--dryRun', 'true']);
await program.parseAsync(['xxx', 'ok', '--dryRun', 'true']);
});
180 changes: 93 additions & 87 deletions deploy/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,48 +20,52 @@ interface ArtifactInfo {
kind: 'artifact';
filename: string;
buildTag: string;
published: Promise<void>;
publish: (c: Context) => Promise<void>;
}

const artifact =
(filename: string, buildTag: string) =>
async ({ publish }: Context): Promise<ArtifactInfo> => {
(filename: string, buildTag: string) => async (): Promise<ArtifactInfo> => {
return {
kind: 'artifact',
filename,
buildTag,
published: publish(
filename,
await fs.readFile(runfiles.resolveWorkspaceRelative(buildTag))
),
publish: async ({ publish }: Context) =>
publish(
filename,
await fs.readFile(
runfiles.resolveWorkspaceRelative(buildTag)
)
),
};
};

interface NpmPackageInfo {
kind: 'npm_publication';
package_name: string;
buildTag: string;
published: Promise<void>;
publish: (c: Context) => Promise<void>;
}

const npmPackage =
(packageName: string, buildTag: string) =>
async ({ exec }: Context): Promise<NpmPackageInfo> => {
if (!('NPM_TOKEN' in process.env))
throw new Error(
"Missing NPM_TOKEN. We won't be able to publish any NPM packages."
);
async (): Promise<NpmPackageInfo> => {
return {
buildTag,
kind: 'npm_publication',
package_name: packageName,
published: exec(runfiles.resolveWorkspaceRelative(buildTag)),
async publish({ exec }: Context) {
if (!('NPM_TOKEN' in process.env))
throw new Error(
"Missing NPM_TOKEN. We won't be able to publish any NPM packages."
);
exec(runfiles.resolveWorkspaceRelative(buildTag));
},
};
};

interface ReleaseProps<T> {
interface ReleaseProps {
dryRun: boolean;
releaseNotes: (items: T[]) => string;
releaseNotes: (items: (ArtifactInfo | NpmPackageInfo)[]) => string;
createRelease(data: { body: string }): Promise<{ release_id: number }>;
uploadReleaseAsset(data: {
release_id: number;
Expand All @@ -71,30 +75,29 @@ interface ReleaseProps<T> {
}

const release =
<T extends { published: Promise<void> }>(
...fns: ((c: Context) => Promise<T>)[]
) =>
(...fns: (() => Promise<ArtifactInfo | NpmPackageInfo>)[]) =>
async ({
dryRun,
createRelease,
releaseNotes,
uploadReleaseAsset,
}: ReleaseProps<T>) => {
let set_release_id: ((release_id: number) => void) | undefined;
const release_id = new Promise<number>(ok => (set_release_id = ok));

const publish: Context['publish'] = dryRun
? async (filename: string, content: Buffer) => {
if (!filename) throw new Error('Empty filename.');
if (content.length == 0)
throw new Error(`Empty content for ${filename}`);
}
: async (file: string, content: Buffer) =>
uploadReleaseAsset({
release_id: await release_id,
name: file,
data: content,
});
}: ReleaseProps) => {
const logInfo = await Promise.all(fns.map(f => f()));

const { release_id } = await createRelease({
body: releaseNotes(logInfo),
});

const publish: Context['publish'] = async (
file: string,
content: Buffer
) =>
uploadReleaseAsset({
release_id,
name: file,
data: content,
});

const exec: Context['exec'] = dryRun
? async (filename: string) => {
if (filename == '')
Expand All @@ -103,17 +106,9 @@ const release =
: async (filename: string) =>
void (await promisify(child_process.execFile)(filename));

const logInfo = await Promise.all(fns.map(f => f({ publish, exec })));

const { release_id: concreteReleaseId } = await createRelease({
body: releaseNotes(logInfo),
});

if (!set_release_id) throw new Error();

set_release_id(concreteReleaseId);

await Promise.all(logInfo.map(itm => itm.published));
await Promise.all(
logInfo.map(({ publish: p }) => p({ publish, exec }))
);
};

export const program = Program.name('release')
Expand All @@ -130,17 +125,17 @@ export const program = Program.name('release')
? getOctokit(process.env['GITHUB_TOKEN']!)
: undefined;

const releaser = release<NpmPackageInfo | ArtifactInfo>(
const releaser = release(
artifact(
'recursive_vassals.zip',
'project/ck3/recursive-vassals/mod_zip.zip'
'//project/ck3/recursive-vassals/mod_zip.zip'
),
artifact(
'recursive_vassals.patch',
'//project/ck3/recursive-vassals/mod.patch'
),
artifact('svgshot.tar.gz', 'ts/cmd/svgshot/svgshot.tgz'),
npmPackage('svgshot', 'ts/cmd/svgshot/npm_pkg.publish.sh')
artifact('svgshot.tar.gz', '//ts/cmd/svgshot/svgshot.tgz'),
npmPackage('svgshot', '//ts/cmd/svgshot/npm_pkg.publish.sh')
);

releaser({
Expand All @@ -160,57 +155,68 @@ export const program = Program.name('release')
if (!data) throw new Error('data is empty');
},

createRelease: Github
? async ({ body }) => ({
release_id: (
await Github.rest.repos.createRelease({
// could probably use a spread operator here
// but i also think that would be uglier...
owner: context.repo.owner,
repo: context.repo.repo,

tag_name: syntheticVersion,

body,

generate_release_notes: true,

name: syntheticVersion,

target_commitish: context.ref,
})
).data.id,
})
: async ({ body }) => {
if (body === '')
throw new Error('Release body is empty.');
return { release_id: 0 };
},
createRelease:
Github !== undefined
? async ({ body }) => ({
release_id: (
await Github.rest.repos.createRelease({
// could probably use a spread operator here
// but i also think that would be uglier...
owner: context.repo.owner,
repo: context.repo.repo,

tag_name: syntheticVersion,

body,

generate_release_notes: true,

name: syntheticVersion,

target_commitish: context.ref,
})
).data.id,
})
: async ({ body }) => {
if (body === '')
throw new Error(`Release body is empty.`);
return { release_id: 0 };
},
dryRun: dryRun,
releaseNotes: (notes: (NpmPackageInfo | ArtifactInfo)[]) => {
const artifacts: ArtifactInfo[] = [];
const npmPackages: NpmPackageInfo[] = [];

for (const note of notes) {
if (note.kind === 'artifact') artifacts.push(note);
if (note.kind === 'npm_publication') npmPackages.push(note);
throw new Error();
if (note.kind === 'artifact') {
artifacts.push(note);
continue;
}
if (note.kind === 'npm_publication') {
npmPackages.push(note);
continue;
}
throw new Error(`Unknown kind ${(note as any).kind}`);
}

return `${
artifacts.length
? `This release contains the following artifacts:\n ${artifacts.map(
artifact =>
` - ${artifact.buildTag} → ${artifact.filename}`
)}`
? `This release contains the following artifacts:\n ${artifacts
.map(
artifact =>
` - ${artifact.buildTag} → ${artifact.filename}`
)
.join('\n')}`
: ''
}
${
npmPackages.length
? `This release contains the following NPM packages:\n: ${npmPackages.map(
pkg =>
` - ${pkg.buildTag} → [${pkg.package_name}](https://npmjs.com/package/svgshot)`
)}`
? `This release contains the following NPM packages:\n ${npmPackages
.map(
pkg =>
` - ${pkg.buildTag} → [${pkg.package_name}](https://npmjs.com/package/svgshot)`
)
.join('\n')}`
: ''
}
`;
Expand Down