Skip to content

Commit

Permalink
Add test for mismatching checked out git tag when publishing (#1329)
Browse files Browse the repository at this point in the history
  • Loading branch information
fsoikin authored Feb 14, 2025
1 parent 01cc874 commit 3c25ef1
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 127 deletions.
19 changes: 19 additions & 0 deletions test-fixtures/publish/1109-tag-mismatch/expected-stderr.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Reading Spago workspace configuration...

✓ Selecting package to build: aaa

Downloading dependencies...
Building...
Src Lib All
Warnings 0 0 0
Errors 0 0 0

✓ Build succeeded.

Your package "aaa" is not ready for publishing yet, encountered 1 error:


✘ The tag (v0.0.1) does not match the expected tag (v0.0.2).
Fix all other publishing-related errors first before creating the correct tag. Do not push your created tag to its remote. Prematurely creating and pushing a tag can lead to unpublishable tags.
To create the tag, you can run:
git tag v0.0.2
12 changes: 12 additions & 0 deletions test-fixtures/publish/1109-tag-mismatch/spago.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package:
name: aaa
dependencies: []
publish:
version: 0.0.2
license: MIT
location:
githubOwner: purescript
githubRepo: aaa
workspace:
packageSet:
registry: 58.0.0
4 changes: 4 additions & 0 deletions test-fixtures/publish/1109-tag-mismatch/src/Main.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Lib where

anExport :: String
anExport = "Hello, World!"
10 changes: 6 additions & 4 deletions test/Spago.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,23 @@ import Test.Spago.Repl as Repl
import Test.Spago.Run as Run
import Test.Spago.Sources as Sources
import Test.Spago.Test as Test
import Test.Spago.Transfer as Transfer
import Test.Spago.Uninstall as Uninstall
import Test.Spago.Unit as Unit
import Test.Spago.Upgrade as Upgrade
import Test.Spec as Spec
import Test.Spec.Reporter as Spec.Reporter
import Test.Spec.Runner.Node (runSpecAndExitProcess')
import Test.Spec.Runner.Node.Config as Config
import Test.Spec.Runner.Node.Config as Cfg

testConfig :: Config.TestRunConfig
testConfig = Config.defaultConfig
testConfig :: Cfg.TestRunConfig
testConfig = Cfg.defaultConfig
{ timeout = Just (Milliseconds 120_000.0)
}

main :: Effect Unit
main = do
config <- Config.fromCommandLine' testConfig Config.commandLineOptionParsers
config <- Cfg.fromCommandLine' testConfig Cfg.commandLineOptionParsers
runSpecAndExitProcess' config [ Spec.Reporter.consoleReporter ] do
Spec.describe "spago" do
-- TODO: script
Expand All @@ -57,6 +58,7 @@ main = do
Docs.spec
Upgrade.spec
Publish.spec
Transfer.spec
Graph.spec
Spec.describe "miscellaneous" do
Lock.spec
Expand Down
217 changes: 94 additions & 123 deletions test/Spago/Publish.purs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module Test.Spago.Publish (spec) where
module Test.Spago.Publish
( doTheGitThing
, spec
)
where

import Test.Prelude

Expand Down Expand Up @@ -85,133 +89,100 @@ spec = Spec.around withTempDir do
spago [ "fetch" ] >>= shouldBeSuccess
spago [ "publish", "-p", "root", "--offline" ] >>= shouldBeFailureErr (fixture "publish/1307-publish-dependencies/expected-stderr.txt")

Spec.describe "transfer" do

Spec.it "fails if the publish config is not specified" \{ spago, fixture } -> do
spago [ "init", "--name", "aaaa" ] >>= shouldBeSuccess
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-publish-config.txt")

Spec.it "fails if the config does not specify an owner" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/basic.yaml", dst: testCwd </> "spago.yaml" }
Spec.it "#1110 installs versions of packages that are returned by the registry solver, but not present in cache" \{ spago, fixture, testCwd } -> do
let
shouldBeFailureErr' file = checkOutputs'
{ stdoutFile: Nothing
, stderrFile: Just file
, result: isLeft
, sanitize:
String.trim
>>> String.replaceAll (String.Pattern "\\") (String.Replacement "/")
>>> String.replaceAll (String.Pattern "\r\n") (String.Replacement "\n")
>>> Regex.replace buildOrderRegex "[x of 3] Compiling module-name"
}

-- We have to ignore lines like "[1 of 3] Compiling Effect.Console" when
-- comparing output, because the compiler will always compile in
-- different order, depending on how the system resources happened to
-- align at the moment of the test run.
buildOrderRegex = unsafeFromRight $ Regex.regex
"\\[\\d of 3\\] Compiling (Effect\\.Console|Effect\\.Class\\.Console|Lib)"
RF.global

FS.copyTree { src: fixture "publish/1110-solver-different-version", dst: testCwd }
spago [ "build" ] >>= shouldBeSuccess
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-owner.txt")

Spec.it "fails if the git tree is not clean" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/basic.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-git.txt")

Spec.it "fails if the package has never been published before" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/basic.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/never-published.txt")

Spec.it "fails if the new repo location is the same as the current one in the registry" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/transfer/aff.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/same-location.txt")
spago [ "fetch" ] >>= shouldBeSuccess

Spec.it "fails if can't find the private key" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/transfer/aff-new-location.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
-- The local `spago.yaml` specifies `console: 6.0.0` in `extraPackages`,
-- so that's what should be in local cache after running `fetch`.
-- Importantly, `console-6.1.0` should not be there yet.
FS.exists (testCwd </> ".spago/p/console-6.0.0") >>= (_ `shouldEqual` true)
FS.exists (testCwd </> ".spago/p/console-6.1.0") >>= (_ `shouldEqual` false)

spago [ "publish", "--offline" ] >>= shouldBeFailureErr' (fixture "publish/1110-solver-different-version/expected-stderr.txt")

-- When `publish` runs, it uses the registry solver, which returns
-- `console-6.1.0` version, so `publish` should fetch that into local
-- cache and build with it.
FS.exists (testCwd </> ".spago/p/console-6.1.0") >>= (_ `shouldEqual` true)

-- Now screw up the `console-6.1.0` package in the local cache, so that it
-- doesn't compile anymore, and check that the relevant compile error
-- happens on publish.
FS.unlink $ testCwd </> ".spago/p/console-6.1.0/src/Effect/Console.js"
rmRf $ testCwd </> ".spago/p/console-6.1.0/output"
spago [ "publish", "--offline" ] >>= shouldBeFailureErr' (fixture "publish/1110-solver-different-version/failure-stderr.txt")

Spec.describe "#1060 auto-filling the `publish.location` field" do
let
prepareProject spago fixture testCwd = do
FS.copyTree { src: fixture "publish/1060-autofill-location/project", dst: testCwd }
spago [ "build" ] >>= shouldBeSuccess
doTheGitThing
spago [ "fetch" ] >>= shouldBeSuccess

Spec.it "happens for root package" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
spago [ "publish", "-p", "aaa", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-root/expected-stderr.txt")
checkFixture (testCwd </> "spago.yaml")
(fixture "publish/1060-autofill-location/scenario-root/expected-spago.yaml")

Spec.it "errors out for non-root package" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
spago [ "publish", "-p", "bbb", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-subdir/expected-stderr.txt")

Spec.it "errors out for nested non-root package" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
spago [ "publish", "-p", "ccc", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-nested-subdir/expected-stderr.txt")

Spec.it "errors out when not a GitHub remote" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
git [ "remote", "set-url", "origin", "https://not.git-hub.net/foo/bar.git" ]
spago [ "publish", "-p", "aaa", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-non-github/expected-stderr.txt")
checkFixture (testCwd </> "spago.yaml")
(fixture "publish/1060-autofill-location/scenario-non-github/expected-spago.yaml")

Spec.it "prints error when no origin remote" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
git [ "remote", "remove", "origin" ]
git [ "remote", "add", "upstream", "[email protected]:foo/bar.git" ]
spago [ "publish", "-p", "aaa", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-no-origin/expected-stderr.txt")
checkFixture (testCwd </> "spago.yaml")
(fixture "publish/1060-autofill-location/project/spago.yaml")

Spec.it "#1109 fails if the checked out git tag does not match the publish config's version" \{ spago, fixture, testCwd } -> do
FS.copyTree { src: fixture "publish/1109-tag-mismatch", dst: testCwd }
spago [ "build" ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "-i", (Path.toRaw $ fixture "publish/no-key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-key.txt")
spago [ "publish", "--offline" ] >>= shouldBeFailureErr (fixture "publish/1109-tag-mismatch/expected-stderr.txt")

Spec.it "fails if running with --offline" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/transfer/aff-new-location.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/offline.txt")

Spec.it "#1110 installs versions of packages that are returned by the registry solver, but not present in cache" \{ spago, fixture, testCwd } -> do
let
shouldBeFailureErr' file = checkOutputs'
{ stdoutFile: Nothing
, stderrFile: Just file
, result: isLeft
, sanitize:
String.trim
>>> String.replaceAll (String.Pattern "\\") (String.Replacement "/")
>>> String.replaceAll (String.Pattern "\r\n") (String.Replacement "\n")
>>> Regex.replace buildOrderRegex "[x of 3] Compiling module-name"
}

-- We have to ignore lines like "[1 of 3] Compiling Effect.Console" when
-- comparing output, because the compiler will always compile in
-- different order, depending on how the system resources happened to
-- align at the moment of the test run.
buildOrderRegex = unsafeFromRight $ Regex.regex
"\\[\\d of 3\\] Compiling (Effect\\.Console|Effect\\.Class\\.Console|Lib)"
RF.global

FS.copyTree { src: fixture "publish/1110-solver-different-version", dst: testCwd }
spago [ "build" ] >>= shouldBeSuccess
doTheGitThing
spago [ "fetch" ] >>= shouldBeSuccess

-- The local `spago.yaml` specifies `console: 6.0.0` in `extraPackages`,
-- so that's what should be in local cache after running `fetch`.
-- Importantly, `console-6.1.0` should not be there yet.
FS.exists (testCwd </> ".spago/p/console-6.0.0") >>= (_ `shouldEqual` true)
FS.exists (testCwd </> ".spago/p/console-6.1.0") >>= (_ `shouldEqual` false)

spago [ "publish", "--offline" ] >>= shouldBeFailureErr' (fixture "publish/1110-solver-different-version/expected-stderr.txt")

-- When `publish` runs, it uses the registry solver, which returns
-- `console-6.1.0` version, so `publish` should fetch that into local
-- cache and build with it.
FS.exists (testCwd </> ".spago/p/console-6.1.0") >>= (_ `shouldEqual` true)

-- Now screw up the `console-6.1.0` package in the local cache, so that it
-- doesn't compile anymore, and check that the relevant compile error
-- happens on publish.
FS.unlink $ testCwd </> ".spago/p/console-6.1.0/src/Effect/Console.js"
rmRf $ testCwd </> ".spago/p/console-6.1.0/output"
spago [ "publish", "--offline" ] >>= shouldBeFailureErr' (fixture "publish/1110-solver-different-version/failure-stderr.txt")

Spec.describe "#1060 auto-filling the `publish.location` field" do
let
prepareProject spago fixture testCwd = do
FS.copyTree { src: fixture "publish/1060-autofill-location/project", dst: testCwd }
spago [ "build" ] >>= shouldBeSuccess
doTheGitThing
spago [ "fetch" ] >>= shouldBeSuccess

Spec.it "happens for root package" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
spago [ "publish", "-p", "aaa", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-root/expected-stderr.txt")
checkFixture (testCwd </> "spago.yaml")
(fixture "publish/1060-autofill-location/scenario-root/expected-spago.yaml")

Spec.it "errors out for non-root package" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
spago [ "publish", "-p", "bbb", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-subdir/expected-stderr.txt")

Spec.it "errors out for nested non-root package" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
spago [ "publish", "-p", "ccc", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-nested-subdir/expected-stderr.txt")

Spec.it "errors out when not a GitHub remote" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
git [ "remote", "set-url", "origin", "https://not.git-hub.net/foo/bar.git" ]
spago [ "publish", "-p", "aaa", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-non-github/expected-stderr.txt")
checkFixture (testCwd </> "spago.yaml")
(fixture "publish/1060-autofill-location/scenario-non-github/expected-spago.yaml")

Spec.it "prints error when no origin remote" \{ fixture, spago, testCwd } -> do
prepareProject spago fixture testCwd
git [ "remote", "remove", "origin" ]
git [ "remote", "add", "upstream", "[email protected]:foo/bar.git" ]
spago [ "publish", "-p", "aaa", "--offline" ] >>=
shouldBeFailureErr (fixture "publish/1060-autofill-location/scenario-no-origin/expected-stderr.txt")
checkFixture (testCwd </> "spago.yaml")
(fixture "publish/1060-autofill-location/project/spago.yaml")

doTheGitThing :: Aff Unit
doTheGitThing = do
Expand Down
51 changes: 51 additions & 0 deletions test/Spago/Transfer.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module Test.Spago.Transfer (spec) where

import Test.Prelude

import Spago.FS as FS
import Spago.Path as Path
import Test.Spago.Publish (doTheGitThing)
import Test.Spec (Spec)
import Test.Spec as Spec

spec :: Spec Unit
spec = Spec.around withTempDir do
Spec.describe "transfer" do

Spec.it "fails if the publish config is not specified" \{ spago, fixture } -> do
spago [ "init", "--name", "aaaa" ] >>= shouldBeSuccess
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-publish-config.txt")

Spec.it "fails if the config does not specify an owner" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/basic.yaml", dst: testCwd </> "spago.yaml" }
spago [ "build" ] >>= shouldBeSuccess
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-owner.txt")

Spec.it "fails if the git tree is not clean" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/basic.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-git.txt")

Spec.it "fails if the package has never been published before" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/basic.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/never-published.txt")

Spec.it "fails if the new repo location is the same as the current one in the registry" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/transfer/aff.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/same-location.txt")

Spec.it "fails if can't find the private key" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/transfer/aff-new-location.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "-i", (Path.toRaw $ fixture "publish/no-key") ] >>= shouldBeFailureErr (fixture "publish/transfer/no-key.txt")

Spec.it "fails if running with --offline" \{ spago, fixture, testCwd } -> do
FS.copyFile { src: fixture "publish/transfer/aff-new-location.yaml", dst: testCwd </> "spago.yaml" }
spago [ "auth", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeSuccess
doTheGitThing
spago [ "registry", "transfer", "--offline", "-i", (Path.toRaw $ fixture "publish/key") ] >>= shouldBeFailureErr (fixture "publish/transfer/offline.txt")

0 comments on commit 3c25ef1

Please sign in to comment.