Skip to content

Commit 3e7bdaa

Browse files
authored
fix(publish): Publish candidate to hackage (#21)
* fix(publish): Publish candidate to hackage * delete unnecessary code in prepare * update tests * improve logging in prepare step * sent new file to form in postReleaseCandidate * new publish tests * fix linter warnings * avoid File usage for request * use axios automate deserialization
1 parent 6887e06 commit 3e7bdaa

File tree

4 files changed

+29
-35
lines changed

4 files changed

+29
-35
lines changed

Diff for: src/prepare.ts

+2-9
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,10 @@ export const prepare = async (
2222
const realCwd = cwd ?? process.cwd();
2323
logger.log("Current working directory: ", realCwd);
2424
const cabalFileName = cabalFile ?? lookupCabalFilename(realCwd, logger);
25-
const { version } = nextRelease ?? {};
26-
27-
logger.log("Checking new version");
28-
if (!version) {
29-
throw new Error("Could not determine the version from semantic release. Check the plugin configuration");
30-
}
31-
32-
logger.log("Checking cabal file");
25+
const { version } = nextRelease;
3326
const fullCabalPath = resolve(realCwd, cabalFileName);
3427
const fullVersion = `${versionPrefix}${version}`;
35-
logger.log("Reading .cabal file", fullCabalPath);
28+
logger.log("Reading .cabal file: ", fullCabalPath);
3629
await readAndWriteNewCabal(fullCabalPath, fullVersion);
3730
logger.log("Writing new version %s to `%s`", version, fullCabalPath);
3831

Diff for: src/publish.ts

+21-20
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,47 @@
11
import axios from "axios";
2-
import { BaseContext } from "semantic-release";
2+
import { PublishContext } from "semantic-release";
33

44
import { PluginConfig } from "./types/pluginConfig";
5-
import { runExecCommand } from "./utils/exec";
65

7-
export const HACKAGE_PACKAGES_URL = "https://hackage.haskell.org/package";
8-
export const CANDIDATES_PATH = "candidates/";
6+
import fs from "fs";
7+
8+
export const HACKAGE_CANDIDATES_URL = "https://hackage.haskell.org/packages/candidates";
99

1010
export const postReleaseCandidate = async (
1111
sdistPath: string,
12-
packageName: string,
1312
hackageToken?: string,
1413
): Promise<number | undefined> => {
15-
const url = `${HACKAGE_PACKAGES_URL}/${packageName}/${CANDIDATES_PATH}`;
1614
try {
1715
const headers = {
1816
Accept: "text/plain",
1917
Authorization: `X-ApiKey ${hackageToken}`,
18+
"Content-Type": "multipart/form-data",
2019
};
2120

22-
const formData = new FormData();
23-
formData.append("package", sdistPath);
24-
25-
const req = await axios.post(url, formData, { headers });
21+
const req = await axios.post(HACKAGE_CANDIDATES_URL, { package: fs.createReadStream(sdistPath) }, { headers });
2622

2723
return req.status;
2824
} catch (e: unknown) {
29-
throw e instanceof Error ? new Error(`You do not have access to POST a file to ${url}, ${e.message}`) : e;
25+
throw e instanceof Error
26+
? new Error(`You do not have access to POST a file to ${HACKAGE_CANDIDATES_URL} , ${e.message}`)
27+
: e;
3028
}
3129
};
3230

33-
export const publish = async ({ packageName }: PluginConfig, { logger }: BaseContext): Promise<void> => {
34-
logger.log("Getting sdist path");
35-
const { error, output } = await runExecCommand(`ls dist-newstyle/sdist/${packageName}-*.tar.gz`);
36-
37-
if (error) {
38-
logger.error(error);
39-
throw new Error(error);
40-
}
31+
export const publish = async (
32+
{ packageName, versionPrefix }: PluginConfig,
33+
{ logger, nextRelease, cwd }: PublishContext,
34+
): Promise<void> => {
35+
const realCwd = cwd ?? process.cwd();
36+
logger.log("Current working directory: ", realCwd);
37+
const { version } = nextRelease;
38+
logger.log("Getting sdist path with version: ", version);
39+
const filename = `${packageName}-${versionPrefix}${version}.tar.gz`;
40+
const sdistPath = `${realCwd}/dist-newstyle/sdist/${filename}`;
41+
logger.log("Uploading sdist: ", sdistPath);
4142

4243
logger.log("Post release candidate in hackage");
43-
const status = await postReleaseCandidate(output.trim(), packageName, process.env.HACKAGE_TOKEN);
44+
const status = await postReleaseCandidate(sdistPath, process.env.HACKAGE_TOKEN);
4445

4546
if (status !== 200) {
4647
throw new Error(`Cannot post release candidate now, status: ${status}`);

Diff for: test/fixtures/my-package-1.0.0.tar.gz

Whitespace-only changes.

Diff for: test/unit/publish.test.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,28 @@ import { expect } from "@assertive-ts/core";
22
import axios from "axios";
33
import sinon from "sinon";
44

5-
import { CANDIDATES_PATH, HACKAGE_PACKAGES_URL, postReleaseCandidate } from "../../src/publish";
5+
import { HACKAGE_CANDIDATES_URL, postReleaseCandidate } from "../../src/publish";
66

7-
const sdistPath = "sdist/path";
8-
const packageName = "my-hackage-package";
7+
const filename = "my-package-1.0.0.tar.gz";
8+
const sdistPath = `${process.cwd()}/test/fixtures/${filename}`;
99
const hackageToken = "my-fake-token";
1010

1111
describe("postReleaseCandidate", () => {
1212
it("returns the status code when request is successful", async () => {
1313
const axiosPostStub = sinon.stub(axios, "post").resolves({ status: 200 });
1414

15-
const statusCode = await postReleaseCandidate(sdistPath, packageName, hackageToken);
15+
const statusCode = await postReleaseCandidate(sdistPath, hackageToken);
1616

1717
expect(statusCode).toBeEqual(200);
1818
expect(axiosPostStub.calledOnce).toBeTruthy();
19-
expect(axiosPostStub.firstCall.args[0]).toBeEqual(`${HACKAGE_PACKAGES_URL}/${packageName}/${CANDIDATES_PATH}`);
19+
expect(axiosPostStub.firstCall.args[0]).toBeEqual(HACKAGE_CANDIDATES_URL);
2020
});
2121

2222
it("throws an error on unsuccessful request", async () => {
2323
const errorMsg = "Error message from server";
2424
const axiosPostStub = sinon.stub(axios, "post").rejects({ message: errorMsg });
2525

26-
const request = postReleaseCandidate(sdistPath, packageName, hackageToken);
26+
const request = postReleaseCandidate(sdistPath, hackageToken);
2727

2828
await expect(request).toBeRejected();
2929
expect(axiosPostStub.calledOnce).toBeTruthy();

0 commit comments

Comments
 (0)