This is a PM2 node.js service which accepts simple RESTful-compliant HTTP requests as a trigger for updating an on-chain Operations contract with a new release. It effectively provides a proxy for turning secret-authenticated RESTful requests into transactions sent to a chain's Operations contract.
The two requests it can act upon are both POSTs (with params passed as URL-encoded data) and are at:
/push-release/<branch>/<commit>
: Pushes a the new releasecommit
ofbranch
. Thebranch
should be one ofstable
,beta
,nightly
(equivalent tomaster
) ortesting
. Thecommit
should be the 40-digit hex-encoded Git commit hash of this release./push-build/<branch>/<platform>
: Pushes a singleplatform
's build of a release onbranch
. Thebranch
is as above. Theplatform
should be compliant according toOperations
contract. The additional POST data iscommit
(as above),filename
(the filename of the build in the build artefacts directory) andsha3
(the hex-encoded Keccak-256 hash of the binary).
To ensure only valid updates are processed, all requests must provide an authentication token. The Keccak-256 hash of this token is stored in this script and any authentication token which is passed must be the pre-image of this hash. It should be passed as a 64-digit, hex-encoded POST parameter with key secret
.
The configuration is managed in config
directory. The default.json
file as the name suggested is used as a base configuration, every entry can
be overwritten in env-specific config files (see kovan.json
as an example). Feel free to add your override to that directory.
To load a specific config file run with NODE_ENV
environment variable set to the name of the config file. E.g. NODE_ENV="kovan" node index.js
will run the server using kovan.json
settings.
Some parameters can also be overridden by environment variables. See config/custom-environment-variables.json
for all possible options. Notable ones:
ACCOUNT_ADDRESS
The address of the account used to send transactionsACCOUNT_PASSWORD
The password of the account. If no password is supplied, it is assumed that the account is already unlocked.HTTP_PORT
The HTTP port the service will be running on.RPC_PORT
The port of Parity's JSON-RPC HTTP interface.SECRET_HASH
The hash of the secret. The pre-image to this hash must be provided by any requests.
We assume you have a preselected signing account and secret token. The Operations contract on the chain this server will be deployed to must accept transactions from the signing account for the set of updates that this will proxy. You'll also need to work out the Keccak-256 hash of the secret token (you can use require('js-sha3').keccak_256(secret_token)
to determine this).
-
Deploy Node.js, NPM and
pm2
on the host:sudo apt-get install build-essential checkinstall libssl-dev curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash source ~/.bashrc nvm install stable nvm alias default stable npm install pm2 yarn -g
-
Install
parity
on the host:bash <(curl https://get.parity.io -kL)
-
Set it up to run as a service:
cat > run-parity.sh <<EOF #!/bin/bash /usr/bin/parity --jsonrpc-port 8545 --warp --unlock 0xsigning_account_address --password /root/password EOF
Ensure your signing account key is in the
parity
keys directory and that its address matches0xsigning_account_address
. Ensure this account is ready for use by creating a secured file containing its password at/root/password
, and don't forget tochmod 400 /root/password
to ensure maximum security. If this should run on Ropsten or some other chain, be sure to include the according--chain
parameter. -
Clone
push-release
repository on the desired host:git clone https://github.com/paritytech/push-release
-
Navigate in to the directory of push-release:
cd push-release
-
Edit
config/yournetwork.js
and run withNODE_ENV=yournetwork
or supply environment variables:- Set
SECRET_HASH
to reflect the hash of the secret token you created earlier. - Set
ACCOUNT_ADDRESS
to have theaddress:
of yoursigning account
you decided on earlier. If you are not--unlock
ing the account when runningparity
, you'll also need to provide theACCOUNT_PASSWORD
. - Set
ASSETS_BASE_URL
to reflect the base URL of your build artefact's server address.
- Set
-
Install any required NPM modules:
yarn install
-
Start the services:
pm2 start --name parity ../run-parity.sh pm2 start push-release.json --only push-release
Prior to setting up the server, it's important to deploy the contracts and have the accounts and keys set up. If you already have a functional Operations contract and master key then you can skip down to "Setting up Parity's OperationsProxy contract". This all assumes you are working from Parity Wallet.
-
Create the master key. This is the key which owns the Operations contract and should be kept in cold storage. Accounts -> New Account; write down the recovery phrase (and put it somewhere safe), and name the key master key. Back up the new JSON file.
-
Transfer some ether into the master key (Transfer button on an existing funded account).
-
Deploy the Operations contract:
- Contracts -> Develop Contract
- Paste contents of Operations contract
- Compile
- Deploy (From Account:
master key
, Contract Name: Operations) - Create, provide password and wait until confirmed.
-
Register Operations contract in Registry:
- Applications -> Registry
- Select account master key in top right - Manage names -> name: operations, reserve this name -> Reserve
- Provide password and wait until confirmed
- Manage entries of a name -> name: operations, A - Ethereum address, value: [Operations contract's address] -> Save - Provide password and wait until confirmed
-
Setting up Parity's OperationsProxy contract:
-
Create the manual key. This is the key which generally stays offline, but can be used to confirm stable and beta releases. Accounts -> New Account; write down the recovery phrase (and put it somewhere safe), and name the key manual key. Back up the new JSON file.
-
Create the server key. This is the key which our newly provisioned server uses to push stable, beta and nightly releases (however, all but the latter need to be confirmed manually). Accounts -> New Account; write down the recovery phrase (and put it somewhere safe), and name the key manual key. Back up the new JSON file.
-
Transfer some ether into these two accounts (Transfer button on an existing funded account).
-
Deploy the Parity-specific OperationsProxy contract:
- Contracts -> Develop Contract
- Paste contents of OperationsProxy contract
- Compile
- Deploy
- Create, provide password and wait until confirmed.
-
Register Parity's OperationsProxy contract in Registry:
- Applications -> Registry
- Select account master key in top right - Manage names -> name: parityoperations, reserve this name -> Reserve
- Provide password and wait until confirmed
- Manage entries of a name -> name: parityoperations, A - Ethereum address, value: [OperationsProxy contract's address] -> Save
- Provide password and wait until confirmed
-
Configure Parity's OperationsProxy to be the maintainer of Parity client releases in
Operations
:- Contracts -> Operations -> Execute
- from account: master key
- function to execute: setClientOwner
- newOwner: parity operations (the contract address)
- Execute, provide password and wait until confirmed
We assume this is set up on server resolving from update-server.parity.io
. At this point, the CI may use two requests, given here as curl
commands:
When a new release has been made (but before builds are known) use:
curl --data "secret=$SECRET" http://update-server.parity.io:1337/push-release/$BRANCH/$COMMIT
Ensure that $COMMIT
(the Git commit hash, 40-character hex) and $BRANCH
(the release branch name) are set properly from the CI's environment.
When a build is confirmed for a new release, you should use:
curl --data "commit=$COMMIT&sha3=$SHA3&filename=$FILENAME&secret=$SECRET" http://update-server.parity.io:1337/push-build/$BRANCH/$PLATFORM
Ensure that $COMMIT
(the Git commit hash, 40-character hex), $SHA3
(the build binary's Keccak-256 hash, 64-character hex), $BRANCH
(the release branch name), $FILENAME
(the filename of the build's binary in the build artefact's path) and $PLATFORM
(the host platform for this build) are set according to the release from the CI's environment.
In both cases, $SECRET
should be the secret token.
Under this configuration, when stable and beta builds are made, they will require confirming through the manual key prior to becoming active. At present there is no way of doing this except manually checking the events on the OperationsProxy
contract and issuing the according confirm
transactions from manual key account.