Permalink
Browse files

[DEVOPS-1195] Merge lastest develop and fix conflict

  • Loading branch information...
nikolaglumac committed Feb 10, 2019
2 parents d3f24ab + 411a09e commit 5e7c6577f12075ee706abd24af60335e5ceccb6b
Showing with 4,285 additions and 1,436 deletions.
  1. +15 −0 CHANGELOG.md
  2. +3 −2 default.nix
  3. +1 −1 features/step_definitions/paper-wallets-certificate-steps.js
  4. +4 −4 features/step_definitions/receive-steps.js
  5. +3 −2 features/step_definitions/wallets-steps.js
  6. +3 −1 installers/.gitignore
  7. +40 −0 installers/Spec.hs
  8. +113 −1 installers/common/AppVeyor.hs
  9. +3 −3 installers/common/MacInstaller.hs
  10. +8 −7 installers/daedalus-installer.cabal
  11. +1 −2 installers/default.nix
  12. +10 −0 installers/dhall/shell.nix
  13. +1 −1 installers/dhall/win64.dhall
  14. +9 −0 installers/nix/nix-installer.nix
  15. +1 −1 installers/overlays/add-test-stubs.nix
  16. +1 −1 installers/shell.nix
  17. +1 −0 package.json
  18. +3 −3 scripts/build-installer-win64.bat
  19. +20 −2 source/common/ipc/api.js
  20. +2 −0 source/common/types/environment.types.js
  21. +50 −0 source/common/types/logging.types.js
  22. +81 −0 source/common/utils/logging.js
  23. +54 −49 source/main/cardano/CardanoNode.js
  24. +9 −9 source/main/cardano/setupCardanoNodeMode.js
  25. +7 −7 source/main/cardano/setupFrontendOnlyMode.js
  26. +4 −1 source/main/config.js
  27. +4 −0 source/main/environment.js
  28. +57 −79 source/main/index.js
  29. +8 −9 source/main/ipc/compress-logs.js
  30. +12 −0 source/main/ipc/getNumberOfEpochsConsolidated.ipc.js
  31. +12 −0 source/main/ipc/getSystemStartTime.ipc.js
  32. +1 −1 source/main/ipc/parse-redemption-code-from-pdf.js
  33. +10 −0 source/main/ipc/rebuild-application-menu.js
  34. +2 −3 source/main/ipc/reportRequestChannel.js
  35. +23 −0 source/main/locales/en-US.json
  36. +23 −0 source/main/locales/ja-JP.json
  37. +2 −1 source/main/menus/MenuActions.types.js
  38. +30 −19 source/main/menus/osx.js
  39. +31 −20 source/main/menus/win-linux.js
  40. +14 −0 source/main/preload.js
  41. +97 −0 source/main/utils/buildAppMenus.js
  42. +3 −2 source/main/utils/ensureDirectoryExists.js
  43. +15 −0 source/main/utils/getLocale.js
  44. +22 −0 source/main/utils/getNumberOfEpochsConsolidated.js
  45. +8 −0 source/main/utils/getTranslation.js
  46. +1 −2 source/main/utils/handleDiskSpace.js
  47. +2 −1 source/main/utils/installChromeExtensions.js
  48. +23 −2 source/main/utils/logging.js
  49. +3 −3 source/main/utils/mainErrorHandler.js
  50. +1 −1 source/main/utils/processes.js
  51. +2 −3 source/main/utils/rendererErrorHandler.js
  52. +53 −8 source/main/utils/setupLogging.js
  53. +51 −17 source/main/windows/main.js
  54. +4 −1 source/renderer/app/App.js
  55. +2 −2 source/renderer/app/Routes.js
  56. +3 −0 source/renderer/app/actions/app-actions.js
  57. +1 −0 source/renderer/app/actions/network-status-actions.js
  58. +153 −81 source/renderer/app/api/api.js
  59. +1 −0 source/renderer/app/api/transactions/requests/getTransactionHistory.js
  60. +6 −3 source/renderer/app/api/transactions/requests/redeemPaperVendedAda.js
  61. +4 −0 source/renderer/app/api/transactions/types.js
  62. +8 −9 source/renderer/app/api/utils/patchAdaApi.js
  63. BIN source/renderer/app/assets/fonts/SFMono-Light.otf
  64. BIN source/renderer/app/assets/fonts/SFMono-Light.ttf
  65. +3 −0 source/renderer/app/assets/images/back-arrow-thin-ic.inline.svg
  66. BIN source/renderer/app/assets/images/block-consolidation/epochs.png
  67. +14 −22 source/renderer/app/components/layout/TopBar.js
  68. +1 −1 source/renderer/app/components/layout/TopBar.scss
  69. +22 −24 source/renderer/app/components/loading/Loading.js
  70. +1 −1 source/renderer/app/components/profile/terms-of-use/TermsOfUseText.scss
  71. +1 −1 source/renderer/app/components/static/About.scss
  72. +195 −0 source/renderer/app/components/status/BlockConsolidationStatus.js
  73. +191 −0 source/renderer/app/components/status/BlockConsolidationStatus.scss
  74. +1 −1 source/renderer/app/components/status/NetworkStatus.scss
  75. +3 −3 source/renderer/app/components/wallet/WalletSendConfirmationDialog.scss
  76. +1 −0 source/renderer/app/components/wallet/layouts/WalletWithNavigation.scss
  77. +1 −1 source/renderer/app/components/wallet/paper-wallet-certificate/CompletionDialog.scss
  78. +8 −2 source/renderer/app/components/wallet/paper-wallet-certificate/InstructionsDialog.js
  79. +5 −0 source/renderer/app/components/wallet/paper-wallet-certificate/InstructionsDialog.scss
  80. +51 −0 source/renderer/app/components/wallet/receive/Address.js
  81. +53 −0 source/renderer/app/components/wallet/receive/Address.scss
  82. +110 −0 source/renderer/app/components/wallet/receive/VirtualAddressesList.js
  83. +23 −0 source/renderer/app/components/wallet/receive/VirtualAddressesList.scss
  84. +69 −79 source/renderer/app/components/wallet/{ → receive}/WalletReceive.js
  85. +21 −67 source/renderer/app/components/wallet/{ → receive}/WalletReceive.scss
  86. +2 −2 source/renderer/app/components/wallet/skins/AmountInputSkin.scss
  87. +5 −6 source/renderer/app/components/wallet/summary/WalletSummary.js
  88. +2 −2 source/renderer/app/components/wallet/summary/WalletSummary.scss
  89. +20 −13 source/renderer/app/components/wallet/transactions/Transaction.js
  90. +18 −4 source/renderer/app/components/wallet/transactions/Transaction.scss
  91. +160 −61 source/renderer/app/components/wallet/transactions/WalletTransactionsList.js
  92. +33 −22 source/renderer/app/components/wallet/transactions/WalletTransactionsList.scss
  93. +32 −0 source/renderer/app/components/wallet/transactions/render-strategies/SimpleTransactionList.js
  94. +3 −0 source/renderer/app/components/wallet/transactions/render-strategies/SimpleTransactionList.scss
  95. +247 −0 source/renderer/app/components/wallet/transactions/render-strategies/VirtualTransactionList.js
  96. +28 −0 source/renderer/app/components/wallet/transactions/render-strategies/VirtualTransactionList.scss
  97. +31 −0 source/renderer/app/components/wallet/transactions/types.js
  98. +8 −2 source/renderer/app/components/widgets/BorderedBox.js
  99. +4 −0 source/renderer/app/components/widgets/BorderedBox.scss
  100. +21 −2 source/renderer/app/components/widgets/NotificationMessage.js
  101. +28 −0 source/renderer/app/components/widgets/NotificationMessage.scss
  102. +17 −0 source/renderer/app/config/epochsConfig.js
  103. +4 −0 source/renderer/app/config/numbersConfig.js
  104. +3 −1 source/renderer/app/config/timingConfig.js
  105. +60 −2 source/renderer/app/containers/LoadingPage.js
  106. +23 −7 source/renderer/app/containers/Root.js
  107. +13 −7 source/renderer/app/containers/TopBarContainer.js
  108. +3 −1 source/renderer/app/containers/profile/LanguageSelectionPage.js
  109. +3 −1 source/renderer/app/containers/settings/categories/GeneralSettingsPage.js
  110. +66 −7 source/renderer/app/containers/settings/categories/SupportSettingsPage.js
  111. +2 −3 source/renderer/app/containers/static/AboutDialog.js
  112. +49 −0 source/renderer/app/containers/status/BlockConsolidationStatusPage.js
  113. +22 −13 source/renderer/app/containers/status/{NetworkStatusPage.js → NetworkStatusDialog.js}
  114. +14 −0 source/renderer/app/containers/status/NetworkStatusDialog.scss
  115. +30 −23 source/renderer/app/containers/wallet/WalletReceivePage.js
  116. +14 −14 source/renderer/app/containers/wallet/WalletSummaryPage.js
  117. +10 −4 source/renderer/app/containers/wallet/WalletTransactionsPage.js
  118. +19 −10 source/renderer/app/domains/Wallet.js
  119. +14 −0 source/renderer/app/i18n/locales/de-DE.json
  120. +431 −230 source/renderer/app/i18n/locales/defaultMessages.json
  121. +18 −4 source/renderer/app/i18n/locales/en-US.json
  122. +14 −0 source/renderer/app/i18n/locales/hr-HR.json
  123. +18 −4 source/renderer/app/i18n/locales/ja-JP.json
  124. +14 −0 source/renderer/app/i18n/locales/ko-KR.json
  125. +14 −0 source/renderer/app/i18n/locales/zh-CN.json
  126. +2 −3 source/renderer/app/index.js
  127. +11 −0 source/renderer/app/ipc/getNumberOfEpochsConsolidatedChannel.js
  128. +11 −0 source/renderer/app/ipc/getSystemStartTime.ipc.js
  129. +10 −0 source/renderer/app/ipc/rebuild-application-menu.js
  130. +1 −1 source/renderer/app/routes-config.js
  131. +4 −4 source/renderer/app/stores/AdaRedemptionStore.js
  132. +60 −20 source/renderer/app/stores/AppStore.js
  133. +82 −23 source/renderer/app/stores/NetworkStatusStore.js
  134. +2 −4 source/renderer/app/stores/ProfileStore.js
  135. +97 −62 source/renderer/app/stores/TransactionsStore.js
  136. +10 −11 source/renderer/app/stores/UiNotificationsStore.js
  137. +1 −1 source/renderer/app/stores/WalletSettingsStore.js
  138. +26 −42 source/renderer/app/stores/WalletsStore.js
  139. +13 −1 source/renderer/app/themes/daedalus/cardano.js
  140. +13 −1 source/renderer/app/themes/daedalus/dark-blue.js
  141. +13 −1 source/renderer/app/themes/daedalus/light-blue.js
  142. +16 −0 source/renderer/app/themes/index.global.scss
  143. +24 −2 source/renderer/app/utils/logging.js
  144. +51 −1 source/renderer/app/utils/network.js
  145. +6 −1 source/renderer/index.html
  146. +7 −0 source/renderer/webpack.config.js
  147. +32 −0 storybook/stories/BlockConsolidationStatus.stories.js
  148. +4 −4 storybook/stories/WalletScreens.stories.js
  149. +2 −2 storybook/stories/WalletSummary.stories.js
  150. +17 −1 storybook/stories/WalletTransactionsList.stories.js
  151. +2 −0 storybook/stories/index.js
  152. +4 −0 storybook/stories/support/environment.js
  153. +35 −12 storybook/stories/support/utils.js
  154. +6 −0 storybook/webpack.config.js
  155. +290 −227 yarn.lock
  156. +3 −1 yarn2nix.nix
@@ -5,6 +5,13 @@ Changelog

### Features

- Structured the Daedalus logs in the same format as the Cardano logs, which follows the structured logging specification ([PR 1299](https://github.com/input-output-hk/daedalus/pull/1299))
- Implemented an extra explanation line in the Create Paper Wallet Certificate dialog ([PR 1309](https://github.com/input-output-hk/daedalus/pull/1309))
- Improve performance of rendering huge lists of transactions and addresses ([PR 1276](https://github.com/input-output-hk/daedalus/pull/1276), [PR 1303](https://github.com/input-output-hk/daedalus/pull/1303), [PR 1305](https://github.com/input-output-hk/daedalus/pull/1305), ([PR 1306](https://github.com/input-output-hk/daedalus/pull/1306)))
- Implemented a "System-info.json" file, containing the system specification of the machine user is running Daedalus ([PR 1292](https://github.com/input-output-hk/daedalus/pull/1292))
- Implemented a block-consolidation status screen ([PR 1275](https://github.com/input-output-hk/daedalus/pull/1275), [PR 1294](https://github.com/input-output-hk/daedalus/pull/1294))
- Implemented translations for the application menu ([PR 1262](https://github.com/input-output-hk/daedalus/pull/1262), [PR 1296](https://github.com/input-output-hk/daedalus/pull/1296))
- Implemented a success message for logs download ([PR 1228](https://github.com/input-output-hk/daedalus/pull/1228))
- Implemented a better handling for "No disk space" error ([PR 1157](https://github.com/input-output-hk/daedalus/pull/1157))
- Improved the NTP check logic ([PR 1258](https://github.com/input-output-hk/daedalus/pull/1258))
- Added support for "frontend-only" mode ([PR 1241](https://github.com/input-output-hk/daedalus/pull/1241), [PR 1260](https://github.com/input-output-hk/daedalus/pull/1260))
@@ -16,6 +23,10 @@ Changelog

### Fixes

- Fixed Dev-Tools initialization in development mode ([PR 1302](https://github.com/input-output-hk/daedalus/pull/1302))
- Fixed text selection issues (disabled drag and drop of selected text and enabled unselect option) ([PR 1289](https://github.com/input-output-hk/daedalus/pull/1289))
- Disabled the default behavior of the context menu following a right click for non-input elements ([PR 1281](https://github.com/input-output-hk/daedalus/pull/1281))
- Decoupled initial setup of language locale and terms of use from loading and syncing screens ([PR 1279](https://github.com/input-output-hk/daedalus/pull/1279), [PR 1284](https://github.com/input-output-hk/daedalus/pull/1284))
- Fixed `ps-list` buffer issues which caused false "Another Daedalus instance is already running" error messages ([PR 1266](https://github.com/input-output-hk/daedalus/pull/1266))
- Fixed `getTransactionHistory` API endpoint account index query parameter name ([PR 1255](https://github.com/input-output-hk/daedalus/pull/1255))
- Fixed issues with custom lock files by implementing "instance-lock" feature from Electron 3 ([PR 1229](https://github.com/input-output-hk/daedalus/pull/1229), [PR 1244](https://github.com/input-output-hk/daedalus/pull/1244))
@@ -29,6 +40,10 @@ Changelog

### Chores

- Added support for newly introduced `UtxoNotEnoughFragmented` API error message ([PR 1297](https://github.com/input-output-hk/daedalus/pull/1297))
- Changed the behavior of "Network status" from screen to dialog ([PR 1286](https://github.com/input-output-hk/daedalus/pull/1286))
- Updated the list of contributors on the "About" screen ([PR 1282](https://github.com/input-output-hk/daedalus/pull/1282))
- Added more logging for API errors ([PR 1278](https://github.com/input-output-hk/daedalus/pull/1278)
- Removed node version check as nix shell is enforcing the version ([PR 1236](https://github.com/input-output-hk/daedalus/pull/1236))
- Fixed Daedalus shell to evaluate embedded variables properly ([PR 1235](https://github.com/input-output-hk/daedalus/pull/1235))
- Added `--rp` prefixed CSS variables to Daedalus themes to configure styles of React-Polymorph components and removed SimpleTheme imports previously used for React-Polymorph overrides in favor of using ThemeProvider's themeOverrides feature ([PR 1139](https://github.com/input-output-hk/daedalus/pull/1139))
@@ -39,10 +39,11 @@ let
# TODO, use this cross-compiled fastlist when we no longer build windows installers on windows
fastlist = pkgs.pkgsCross.mingwW64.callPackage ./fastlist.nix {};
## TODO: move to installers/nix
daedalus-installer = import ./installers/default.nix {
hsDaedalusPkgs = import ./installers {
inherit (cardanoSL) daedalus-bridge;
inherit localLib system;
};
daedalus-installer = self.hsDaedalusPkgs.daedalus-installer;
daedalus = self.callPackage ./installers/nix/linux.nix {};
rawapp = self.callPackage ./yarn2nix.nix {
inherit buildNum;
@@ -162,7 +163,7 @@ let
newBundle = let
daedalus' = self.daedalus.override { sandboxed = true; };
in (import ./installers/nix/nix-installer.nix {
inherit (self) postInstall preInstall cluster;
inherit (self) postInstall preInstall cluster rawapp;
inherit pkgs;
installationSlug = installPath;
installedPackages = [ daedalus' self.postInstall self.namespaceHelper daedalus'.cfg self.daedalus-bridge daedalus'.daedalus-frontend self.xdg-open ];
@@ -160,7 +160,7 @@ When(/^I toggle "Spending password" switch on the restore wallet with certificat
});

Then(/^I should see that address was used$/, async function () {
const addressSelector = '.WalletReceive_usedWalletAddress .WalletReceive_addressId';
const addressSelector = '.Address_usedWalletAddress .Address_addressId';
await this.client.waitForVisible(addressSelector);
const usedAddress = await this.client.getText(addressSelector);
expect(usedAddress).to.equal(this.certificateWalletAddress);
@@ -12,21 +12,21 @@ When('I click the ShowUsed switch', async function () {
await waitAndClick(this.client, '.SimpleSwitch_switch');
});

Then('I should see {int} used addresses', { timeout: 40000 }, async function (numberOfAddresses) {
const addressesFound = await getVisibleElementsCountForSelector(this.client, '.WalletReceive_usedWalletAddress', '.WalletReceive_usedWalletAddress', 40000);
Then('I should see {int} used addresses', { timeout: 60000 }, async function (numberOfAddresses) {
const addressesFound = await getVisibleElementsCountForSelector(this.client, '.Address_usedWalletAddress', '.Address_usedWalletAddress', 60000);
expect(addressesFound).to.equal(numberOfAddresses);
});

Then('I should see {int} addresses', async function (numberOfAddresses) {
const addressesFound = await getVisibleElementsCountForSelector(this.client, '.WalletReceive_walletAddress');
const addressesFound = await getVisibleElementsCountForSelector(this.client, '.Address_component');
expect(addressesFound).to.equal(numberOfAddresses);
});

Then('I should see the following addresses:', async function (table) {
const expectedAdresses = table.hashes();
let addresses;
await this.client.waitUntil(async () => {
addresses = await this.client.getAttribute('.WalletReceive_walletAddress', 'class');
addresses = await this.client.getAttribute('.Address_component', 'class');
return addresses.length === expectedAdresses.length;
});
addresses.forEach((address, index) => expect(address).to.include(expectedAdresses[index].ClassName));
@@ -295,8 +295,9 @@ When(/^I click on recovery phrase mnemonics in correct order$/, async function (
for (let i = 0; i < this.recoveryPhrase.length; i++) {
const text = this.recoveryPhrase[i];
const selector = 'MnemonicWord_root';
const disabledSelector = 'MnemonicWord_disabled';
await this.waitAndClick(
`//button[contains(@class,'${selector}') and contains(text(), '${text}')]`
`//button[contains(@class,'${selector}') and not(contains(@class, '${disabledSelector}')) and contains(text(), '${text}')]`
);
}
});
@@ -459,7 +460,7 @@ Then(/^the balance of "([^"]*)" wallet should be:$/, { timeout: 60000 }, async f
Then(/^I should see newly generated address as active address on the wallet receive screen$/, async function () {
return this.client.waitUntil(async () => {
const activeAddress = await this.client.getText('.WalletReceive_hash');
const generatedAddress = await this.client.getText('.generatedAddress-1 .WalletReceive_addressId');
const generatedAddress = await this.client.getText('.generatedAddress-1 .Address_addressId');
return generatedAddress === activeAddress;
});
});
@@ -1,9 +1,11 @@
.stack-work/
dist/
dist-newstyle/

configuration.yaml
launcher-config.yaml
wallet-topology.yaml

*genesis*.json
*.windows
*.zip
*.zip
@@ -13,18 +13,24 @@ import Data.Aeson.Types (Value)
import Data.Aeson.Lens
import qualified Control.Foldl as Fold
import System.Directory
import qualified Data.ByteString.Lazy as BL
import qualified Data.Map as M
import qualified GitHub as GH
import Data.Aeson (decode)

import Config
import Types
import qualified MacInstaller as Mac
import Util
import AppVeyor

main :: IO ()
main = hspec $ do
describe "Utility functions" utilSpec
describe "MacInstaller build" macBuildSpec
describe "Config generation" configSpec
describe "recursive directory deletion" deleteSpec
describe "Hydra downloads for AppVeyor" hydraSpec

macBuildSpec :: Spec
macBuildSpec = do
@@ -143,3 +149,37 @@ utilSpec = do
it "generates a good filename for windows" $ do
let f = packageFileName Win64 Mainnet (Version "0.4.2") (Cardano "") "9.9" (Just "job.id")
f `shouldBe` (fromText "daedalus-0.4.2-cardano-sl-9.9-mainnet-windows-job.id.exe")

----------------------------------------------------------------------------
-- Tests for Hydra downloading (yes it's in the AppVeyor module)

hydraBuildJSON :: BL.ByteString
hydraBuildJSON = "{\"stoptime\":1548312357,\"starttime\":1548312357,\"timestamp\":1548312190,\"buildstatus\":0,\"nixname\":\"daedalus-mingw32-pkg\",\"id\":545198,\"finished\":1,\"buildmetrics\":{},\"releasename\":null,\"jobset\":\"cardano-sl-pr-4001\",\"priority\":100,\"buildproducts\":{\"1\":{\"type\":\"file\",\"path\":\"/nix/store/ifswlpnvvw4z5xj7wwhygc4alvrs7whj-daedalus-mingw32-pkg/CardanoSL.zip\",\"sha1hash\":\"b844f4a8ce40782f0764151d1e0b3c6e4432254a\",\"subtype\":\"binary-dist\",\"defaultpath\":\"\",\"filesize\":168,\"name\":\"CardanoSL.zip\",\"sha256hash\":\"9fe1bf5e7b8b07628fd25f0ffd07ea297c12dd820d4c433a9f20efcbc0104a82\"}},\"buildoutputs\":{\"out\":{\"path\":\"/nix/store/ifswlpnvvw4z5xj7wwhygc4alvrs7whj-daedalus-mingw32-pkg\"}},\"drvpath\":\"/nix/store/yy9cs24y0gcacpl0646n083vnvbfj85g-daedalus-mingw32-pkg.drv\",\"jobsetevals\":[484201],\"job\":\"daedalus-mingw32-pkg\",\"system\":\"x86_64-linux\",\"project\":\"serokell\"}"

hydraBuildURL :: Text
hydraBuildURL = "https://hydra.iohk.io/build/545273"

githubStatusJSON :: BL.ByteString
githubStatusJSON = "[{\"url\":\"https://api.github.com/repos/input-output-hk/cardano-sl/statuses/b57ede2df60658750bb7629d3946e984187a3224\",\"avatar_url\":\"https://avatars1.githubusercontent.com/u/29731078?v=4\",\"id\":6137719519,\"node_id\":\"MDEzOlN0YXR1c0NvbnRleHQ2MTM3NzE5NTE5\",\"state\":\"success\",\"description\":\"Hydra build #550173 of serokell:cardano-sl-pr-4001:required\",\"target_url\":\"https://hydra.iohk.io/build/550173\",\"context\":\"ci/hydra:serokell:cardano-sl:required\",\"created_at\":\"2019-01-25T00:50:50Z\",\"updated_at\":\"2019-01-25T00:50:50Z\",\"creator\":{\"login\":\"iohk-devops\",\"id\":29731078,\"node_id\":\"MDQ6VXNlcjI5NzMxMDc4\",\"avatar_url\":\"https://avatars1.githubusercontent.com/u/29731078?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/iohk-devops\",\"html_url\":\"https://github.com/iohk-devops\",\"followers_url\":\"https://api.github.com/users/iohk-devops/followers\",\"following_url\":\"https://api.github.com/users/iohk-devops/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/iohk-devops/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/iohk-devops/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/iohk-devops/subscriptions\",\"organizations_url\":\"https://api.github.com/users/iohk-devops/orgs\",\"repos_url\":\"https://api.github.com/users/iohk-devops/repos\",\"events_url\":\"https://api.github.com/users/iohk-devops/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/iohk-devops/received_events\",\"type\":\"User\",\"site_admin\":false}},{\"url\":\"https://api.github.com/repos/input-output-hk/cardano-sl/statuses/b57ede2df60658750bb7629d3946e984187a3224\",\"avatar_url\":\"https://avatars1.githubusercontent.com/u/29731078?v=4\",\"id\":6137711125,\"node_id\":\"MDEzOlN0YXR1c0NvbnRleHQ2MTM3NzExMTI1\",\"state\":\"pending\",\"description\":\"Hydra build #550173 of serokell:cardano-sl-pr-4001:required\",\"target_url\":\"https://hydra.iohk.io/build/550173\",\"context\":\"ci/hydra:serokell:cardano-sl:required\",\"created_at\":\"2019-01-25T00:48:58Z\",\"updated_at\":\"2019-01-25T00:48:58Z\",\"creator\":{\"login\":\"iohk-devops\",\"id\":29731078,\"node_id\":\"MDQ6VXNlcjI5NzMxMDc4\",\"avatar_url\":\"https://avatars1.githubusercontent.com/u/29731078?v=4\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/iohk-devops\",\"html_url\":\"https://github.com/iohk-devops\",\"followers_url\":\"https://api.github.com/users/iohk-devops/followers\",\"following_url\":\"https://api.github.com/users/iohk-devops/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/iohk-devops/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/iohk-devops/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/iohk-devops/subscriptions\",\"organizations_url\":\"https://api.github.com/users/iohk-devops/orgs\",\"repos_url\":\"https://api.github.com/users/iohk-devops/repos\",\"events_url\":\"https://api.github.com/users/iohk-devops/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/iohk-devops/received_events\",\"type\":\"User\",\"site_admin\":false}}]"

hydraSpec :: Spec
hydraSpec = do
describe "Hydra API parsing" $ do
let build = decode hydraBuildJSON

it "parses build status" $
hydraBuildStatus <$> build `shouldBe` Just 0

it "parses the job filename" $
map (fmap bpName) . M.toList . hydraBuildProducts <$> build `shouldBe` Just [("1", "CardanoSL.zip")]

it "makes the correct download url" $ do
let findUrl = findHydraBuildProductURL "CardanoSL.zip" (GH.URL hydraBuildURL) . hydraBuildProducts
let Just mUrl = findUrl <$> build
mUrl `shouldBe` Just (hydraBuildURL <> "/download/1/CardanoSL.zip")

describe "GitHub status API parsing" $ do
let statuses = decode githubStatusJSON

it "finds the build URL from a successful github status blob" $
hydraURL' "required" <$> statuses `shouldBe` Just (Just (GH.URL "https://hydra.iohk.io/build/550173"))
@@ -1,6 +1,14 @@
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, LambdaCase, RecordWildCards, DeriveDataTypeable, DeriveGeneric #-}

module AppVeyor (downloadCardanoSL, AppVeyorError(..)) where
module AppVeyor
( downloadCardanoSL
, downloadCardanoSLOld
, AppVeyorError(..)
, HydraBuild(..)
, HydraBuildProduct(..)
, hydraURL'
, findHydraBuildProductURL
) where

import Universum hiding (get)
import Data.Aeson
@@ -10,6 +18,9 @@ import qualified GitHub as GH
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.Text as T
import qualified Data.Map as M
import Data.Map (Map)
import Data.Text (Text)
import Network.URI
import Data.Maybe (mapMaybe)
import Network.Wreq
@@ -20,6 +31,37 @@ import System.Environment (lookupEnv)

downloadCardanoSL :: FilePath -> IO L8.ByteString
downloadCardanoSL srcJson = do
src <- getCardanoRev srcJson
downloadCardanoSLHydraBuildProduct src

-- | Filename of the hydra build product which contains windows
-- executables.
theBuildProduct = "CardanoSL.zip" :: Text
-- | Where to find the windows build product.
theHydraJob = "daedalus-mingw32-pkg" :: Text

-- | Gets CardanoSL.zip corresponding to the src json revision from Hydra
downloadCardanoSLHydraBuildProduct :: CardanoSource -> IO L8.ByteString
downloadCardanoSLHydraBuildProduct src@CardanoSource{..} = do
printf ("Fetching GitHub CI status for commit "%n%" of "%n%"/"%n%"\n") srcRev srcOwner srcRepo
buildURL <- hydraURL theHydraJob src
printf ("Build URL is "%s%"\n") (getUrl buildURL)

build <- getHydraBuild buildURL
let bp = hydraBuildProducts build

printf ("Build has "%d%" build product(s), status "%w%".\n")
(M.size bp) (hydraBuildStatus build)

printf ("Artifacts are: "%ss%"\n") (map bpName (M.elems bp))
case findHydraBuildProductURL theBuildProduct buildURL bp of
Just url -> downloadHydra url
Nothing -> throwM (MissingArtifactsError $ getUrl buildURL)

-- | Old download method -- first try S3 then look for an AppVeyor
-- build in the github status.
downloadCardanoSLOld :: FilePath -> IO L8.ByteString
downloadCardanoSLOld srcJson = do
src <- getCardanoRev srcJson
maybeZip <- downloadCardanoSLS3 src
case maybeZip of
@@ -154,6 +196,76 @@ instance ToJSON Job -- Only required for _JSON prism

----------------------------------------------------------------------------

data HydraBuild = HydraBuild
{ hydraBuildStatus :: Int
, hydraBuildProducts :: Map Text HydraBuildProduct
, hydraBuildJobsetEvals :: [Int]
} deriving (Show, Eq, Generic)

data HydraBuildProduct = HydraBuildProduct
{ bpName :: Text
, bpSHA256Hash :: Text
, bpStorePath :: Text
} deriving (Show, Eq, Generic)

instance FromJSON HydraBuild where
parseJSON = withObject "HydraBuild" $ \o -> HydraBuild
<$> o .: "buildstatus"
<*> o .: "buildproducts"
<*> o .: "jobsetevals"

instance FromJSON HydraBuildProduct where
parseJSON = withObject "HydraBuildProduct" $ \o -> HydraBuildProduct
<$> o .: "name"
<*> o .: "sha256hash"
<*> o .: "path"

-- | Use GitHub API to find the first Hydra build status.
-- The result will be something like =https://hydra.iohk.io/build/544009=
hydraURL :: Text -> CardanoSource -> IO GH.URL
hydraURL job src = fmap (hydraURL' job . toList) <$> statusFor' src >>= \case
Right (Just u) -> pure u
Right Nothing -> throwM $ StatusMissingError src
Left err -> throwM $ GitHubStatusError src err

-- | Find the CI URL for the first Hydra "required" job status.
-- An example status name: "ci/hydra:serokell:cardano-sl:required"
hydraURL' :: Text -> [GH.Status] -> Maybe GH.URL
hydraURL' job = safeHead . mapMaybe statusTargetUrl . filter isHydraStatus
where
isHydraStatus st = maybe False isHydraJob (statusContext st)
isHydraJob st = T.isPrefixOf "ci/hydra:" st && T.isSuffixOf (":" <> job) st

-- | Fetch information about a hydra build. Hydra will return JSON if
-- the Accept header asks for it.
getHydraBuild :: GH.URL -> IO HydraBuild
getHydraBuild url = do
printf ("Fetching "%w%" ... ") url
let opts = defaults & header "Accept" .~ ["application/json"]
r <- asJSON =<< getWith opts (T.unpack $ getUrl url)
printf "Done\n"
pure (r ^. responseBody)

-- | Download a file with logging.
downloadHydra :: Text -> IO L8.ByteString
downloadHydra url = do
printf ("Downloading "%w%" ... ") url
r <- get (T.unpack url)
let bs = r ^. responseBody
printf "Done\n"
pure bs

-- | Look in the build products for a match filename and then return
-- a download URL which looks like:
-- https://hydra.iohk.io/build/362609/download/1/blockchain-spec.pdf
findHydraBuildProductURL :: Text -> GH.URL -> Map Text HydraBuildProduct -> Maybe Text
findHydraBuildProductURL name buildUrl = fmap url . find isCSL . M.toList
where
isCSL = (== name) . bpName . snd
url (num, bp) = getUrl buildUrl <> "/download/" <> num <> "/" <> bpName bp

----------------------------------------------------------------------------

-- | Load commit hash and GitHub repo name from cardano-sl-src.json.
getCardanoRev :: FilePath -> IO CardanoSource
getCardanoRev src = eitherDecode <$> L8.readFile src >>= \case
Oops, something went wrong.

0 comments on commit 5e7c657

Please sign in to comment.