Skip to content
This repository has been archived by the owner on Jun 11, 2020. It is now read-only.

Publish types-registry to npm AND github package registry #661

Merged
merged 8 commits into from Oct 2, 2019

Conversation

sandersn
Copy link
Member

@sandersn sandersn commented Oct 2, 2019

Publish types-registry to @definitelytyped/types-registry before publishing to types-registry.

Note that, for testing purposes, the time-limit per publish is 10 minutes instead of 1 week. I'll change that after this PR is merged and I have verified that it works.

You can see the results of my local testing; 0.1.456 was published from my machine using the below PR. 0.1.450 is a manual publish from @andrewbranch when we first tested the gihub package registry.

Plus cleanup needed to make it readable(ish).
Also
1. Rename "oldVersion" to "npmVersion"
2. Correctly log why we skipped publishing -- the predicate was
backward.
@sandersn
Copy link
Member Author

sandersn commented Oct 2, 2019

Hide whitespace helps a lot with this review since I moved a whole block of code into a function in order to call it twice.

@@ -9,11 +9,7 @@ import { createTgz } from "../util/tgz";
import { identity, joinPaths, mapToRecord, recordToMap } from "../util/util";

import { getSecret, Secret } from "./secrets";
import { npmApi, npmRegistry, npmRegistryHostName } from "./settings";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lint

@@ -9,11 +9,7 @@ import { createTgz } from "../util/tgz";
import { identity, joinPaths, mapToRecord, recordToMap } from "../util/util";

import { getSecret, Secret } from "./secrets";
import { npmApi, npmRegistry, npmRegistryHostName } from "./settings";

function packageUrl(packageName: string): string {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function was only used once so I inlined it

}

private constructor(private readonly client: RegClient, private readonly auth: RegClient.Credentials) {}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readonly seems superfluous for a 20-line class.

return new this(new RegClient(config), { token });
static async create(config?: RegClient.Config, registryName: "github" | "npm" = "npm"): Promise<NpmPublishClient> {
if (registryName === "github") {
return new this(new RegClient(config), { token: await getSecret(Secret.GITHUB_PUBLISH_ACCESS_TOKEN) }, githubRegistry);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the secret github-publish-access-token on azure. It's using a token from my account for now, but after this merges we should give typescript-bot a publish token. Unfortunately, these tokens currently require full repo access, which I would prefer to not give to types-publisher.

return promisifyVoid(cb => {
if (dry) {
log(`(dry) Skip tag of ${packageName}@${distTag} as ${version}`);
cb(undefined);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a less clunky way to write this? I haven't written much promisified code, so I fell back to my base knowledge of the monads+continuations. (It also made me want to rename cb to k or return_, but I refrained.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not familiar with promisifyVoid, but you could move if (dry) { ... } outside the closure and return Promise.resolve() instead of cb(undefined)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a utility function lower in the file, but it doesn't seem that useful.

I'll use return Promise.resolve().

log(`(dry) Skip tag of ${packageName}@${distTag} as ${version}`);
cb(undefined);
} else {
this.client.distTags.add(this.registry, { package: packageName, version, distTag, auth: this.auth }, cb);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched from tag to distTags.add because it allows me to separately specify the registry URL.

@@ -32,6 +32,11 @@ export enum Secret {
* We only need one token in existence, so delete old tokens at: https://www.npmjs.com/settings/tokens
*/
NPM_TOKEN,
/**
* Token used to publish packages to Github.
* This *could* be the same as GITHUB_ACCESS_TOKEN, but I think it's better if they remain separate.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not actually sure about this. It might be OK to have one token which can

  1. publish
  2. search for issues
  3. comment on issues

I'll have to think about security a bit before deciding. I think it's fine to start with them separate.

await writeLog("publish-registry.md", logResult());

async function publishToRegistry(registryName: "github" | "npm") {
const packageName = registryName === "github" ? "@definitelytyped/" + typesRegistry : typesRegistry;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line, plus the calls to publishToRegistry, are almost all the new code except for registryName in generateJson. Everything else is renames or reordering.

// This may have just been due to a timeout, so test if types-registry@next is a subset of the one we're about to publish.
// If so, we should just update it to "latest" now.
log("Old version of types-registry was never tagged latest, so updating");
await validateIsSubset(await readNotNeededPackages(dt), log);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this throw? An error here (or anywhere in this function) publishing to GitHub will stop us from attempting a publish to npm. Not sure whether that’s intentional or not. If the goal is to keep them in sync, that seems good. If the goal is to try publishing to GitHub without effect on current npm infrastructure, that seems bad.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! It does. The intention is to avoid publishing whenever anything goes wrong even if we're not quite sure why, since an old types-registry is way less bad than a new wrong one.

I don't think it's a problem here, but I'll need to inspect the rest of the code.

(I inspected a bunch of code and concluded that there WERE a few problems that got complicated to fix)

I think the safest thing here is to make sure, as long as we're publishing to two places, that github never gets ahead of npm. It's fine if github misses some updates compared to npm, but not the other way around since we always check against npm. That also means, unfortunately, that github needs to update first so that validateIsSubset checks against the current version of npm, not current+1.

I think the right fix is to surround await publishToRegistry('github') with try { ... } catch { }, so that if github fails, npm tries as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my hunch (that npm should still try to publish even if GitHub fails), but wanted to double check.

@sandersn sandersn merged commit b70c1e3 into master Oct 2, 2019
@sandersn sandersn deleted the double-publish-types-registry branch October 2, 2019 21:14
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants