Skip to content

Commit

Permalink
chore: add a release script, version number in metadata.json file and… (
Browse files Browse the repository at this point in the history
Qovery#129)

* chore: add a release script, version number in metadata.json file and rename backups to dumps

* refactor: add a trait to easily add more migrations
  • Loading branch information
fabriceclementz authored May 22, 2022
1 parent b71f6b8 commit ab75d76
Show file tree
Hide file tree
Showing 21 changed files with 971 additions and 230 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ replibyte -c conf.yaml dump restore remote -v latest

## Features

- [x] Support data backup and restore for PostgreSQL, MySQL and MongoDB
- [x] Support data dump and restore for PostgreSQL, MySQL and MongoDB
- [x] Replace sensitive data with fake data
- [x] Works on large database (> 10GB)
- [x] Database Subsetting: Scale down a production database to a more reasonable size 🔥
Expand Down
8 changes: 4 additions & 4 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,20 @@ replicate the data in a stream of bytes and does not store anything on a local d
### Limitations

- Tested with PostgreSQL 13 and 14. It should work with prior versions.
- RepliByte as not been designed to run multiple backups targeting the same Bridge. The Index File does not manage concurrent write (ATM).
- RepliByte as not been designed to run multiple dumps targeting the same Bridge. The Index File does not manage concurrent write (ATM).

### Index file structure

An index file describe the structure of your backups and all of them.
An index file describe the structure of your dumps and all of them.

Here is the manifest file that you can find at the root of your target `Bridge` (E.g: S3).

```json
{
"backups": [
"dumps": [
{
"size": 1024000,
"directory_name": "backup-{epoch timestamp}",
"directory_name": "dump-{epoch timestamp}",
"created_at": "epoch timestamp",
"compressed": true,
"encrypted": true
Expand Down
6 changes: 3 additions & 3 deletions dump-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dump-parser"
version = "0.1.0"
version = "0.7.3"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -9,11 +9,11 @@ edition = "2021"
bson = "2.1"
serde = "1.0"

########## WARNING #############
########## WARNING #############
# DO NOT UPGRADE THE CRC CRATE #
# version 2 (or higher) is not compatible with the current crc64 algorithm that 'mongorestore' uses in its archive parser.
# mongorestore ECMA: https://go.dev/src/hash/crc64/crc64.go#L28
# crc-rs 1.8 ECMA: https://github.com/mrhooray/crc-rs/blob/1.8.1/build.rs#L41 (COMPATIBLE)
# crc-rs ^2.0 ECMA: https://github.com/akhilles/crc-catalog/blob/2.0.1/src/catalog.rs#L104 (INCOMPATIBLE)
crc = "1.8"
crc = "1.8"
################################
84 changes: 84 additions & 0 deletions release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env bash

set -e

TOML_FILES="\
replibyte/Cargo.toml \
subset/Cargo.toml \
dump-parser/Cargo.toml
"

old=$1
new=$2

if [ -z "${old}" ] || [ -z "${new}" ]
then
echo "please run: $0 <old version> <new version>"
exit 1
fi

if [ "$(git status --porcelain=v1 2>/dev/null | wc -l)" -ne 0 ]
then
git status
echo "There are unsaved changes in the repository, press CTRL-C to abort now or return to continue."
read -r answer
fi

echo -n "Release process from starting from '${old}' -> '${new}', do you want to continue? [y/N] "
read -r answer


case "${answer}" in
Y*|y*)
;;
*)
echo "Aborting"
exit 0
;;
esac;

echo "==> ${answer}"

echo -n "Updating TOML files:"
for toml in ${TOML_FILES}
do
echo -n " ${toml}"
sed -e "s/^version = \"${old}\"$/version = \"${new}\"/" -i.release "${toml}"
done
echo "."

echo "Please review the following changes. (return to continue)"
read -r answer

git diff

echo "Do you want to Continue or Rollback? [c/R]"
read -r answer

case "${answer}" in
C*|c*)
git checkout -b "release-v${new}"
git commit -sa -m "Release v${new}"
git push --set-upstream origin "release-v${new}"
;;
*)
git checkout .
exit
;;
esac;

echo "Please open the following pull request we'll wait here continue when it is merged."
echo
echo " >> https://github.com/qovery/replibyte/pull/new/release-v${new} <<"
echo
echo "Once you continue we'll generate and push the release tag with the latest 'main'"
read -r answer

echo "Generating release tag v${new}"

git checkout main
git pull
git tag -a -m"Release v${new}" "v${new}"
git push --tags

echo "Congrats release v${new} is done!"
2 changes: 1 addition & 1 deletion replibyte/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
edition = "2021"
version = "0.1.0"
version = "0.7.3"
name = "replibyte"
authors = ["Qovery Team", "Fab", "Benny", "Contributos"]

Expand Down
33 changes: 17 additions & 16 deletions replibyte/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use clap::{Args, Parser, Subcommand};

/// Replibyte is a tool to seed your databases with your production data while keeping sensitive data safe, just pass `-h`
#[derive(Parser, Debug)]
#[clap(about, long_about = None)]
#[clap(version, about, long_about = None)]
#[clap(propagate_version = true)]
pub struct CLI {
/// Replibyte configuration file
#[clap(short, long, parse(from_os_str), value_name = "configuration file")]
Expand All @@ -19,7 +20,7 @@ pub struct CLI {
/// sub commands
#[derive(Subcommand, Debug)]
pub enum SubCommand {
/// all backup commands
/// all dump commands
#[clap(subcommand)]
Dump(DumpCommand),
/// all transformers command
Expand All @@ -30,14 +31,14 @@ pub enum SubCommand {
/// all dump commands
#[derive(Subcommand, Debug)]
pub enum DumpCommand {
/// list available backups
/// list available dumps
List,
/// launch backup -- use `-h` to show all the options
/// launch dump -- use `-h` to show all the options
Create(DumpCreateArgs),
/// all restore commands
#[clap(subcommand)]
Restore(RestoreCommand),
/// delete a backup from the defined datastore
/// delete a dump from the defined datastore
Delete(DumpDeleteArgs),
}

Expand All @@ -51,28 +52,28 @@ pub enum TransformerCommand {
/// all restore commands
#[derive(Subcommand, Debug)]
pub enum RestoreCommand {
/// Restore backup inside a local Docker container
/// Restore dump inside a local Docker container
Local(RestoreLocalArgs),
/// Restore backup inside the configured destination
/// Restore dump inside the configured destination
Remote(RestoreArgs),
}

/// all restore commands
#[derive(Args, Debug)]
pub struct RestoreArgs {
/// restore backup -- set `latest` or `<backup name>` - use `backup list` command to list all backups available
#[clap(short, long, value_name = "[latest | backup name]")]
/// restore dump -- set `latest` or `<dump name>` - use `dump list` command to list all dumps available
#[clap(short, long, value_name = "[latest | dump name]")]
pub value: String,
/// stream output on stdout
#[clap(short, long)]
pub output: bool,
}

/// restore backup in a local Docker container
/// restore dump in a local Docker container
#[derive(Args, Debug)]
pub struct RestoreLocalArgs {
/// restore backup -- set `latest` or `<backup name>` - use `backup list` command to list all backups available
#[clap(short, long, value_name = "[latest | backup name]")]
/// restore dump -- set `latest` or `<dump name>` - use `dump list` command to list all dumps available
#[clap(short, long, value_name = "[latest | dump name]")]
pub value: String,
/// stream output on stdout
#[clap(short, long)]
Expand All @@ -91,7 +92,7 @@ pub struct RestoreLocalArgs {
pub image: Option<String>,
}

/// all backup run commands
/// all dump run commands
#[derive(Args, Debug)]
pub struct DumpCreateArgs {
#[clap(name = "source_type", short, long, value_name = "[postgresql | mysql | mongodb]", possible_values = &["postgresql", "mysql", "mongodb"], requires = "input")]
Expand All @@ -111,13 +112,13 @@ pub struct DumpCreateArgs {
#[derive(Args, Debug)]
#[clap(group = clap::ArgGroup::new("delete-mode").multiple(false))]
pub struct DumpDeleteArgs {
/// Name of the backup to delete
/// Name of the dump to delete
#[clap(group = "delete-mode")]
pub dump: Option<String>,
/// Remove all backups older than the specified number of days. Example: `14d` for deleting backups older than 14 days
/// Remove all dumps older than the specified number of days. Example: `14d` for deleting dumps older than 14 days
#[clap(long, group = "delete-mode")]
pub older_than: Option<String>,
/// Keep only the last N backups
/// Keep only the last N dumps
#[clap(long, group = "delete-mode")]
pub keep_last: Option<usize>,
}
17 changes: 8 additions & 9 deletions replibyte/src/commands/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,27 @@ use clap::CommandFactory;

/// List all dumps
pub fn list(datastore: &mut Box<dyn Datastore>) -> Result<(), Error> {
let _ = datastore.init()?;
let mut index_file = datastore.index_file()?;

if index_file.backups.is_empty() {
if index_file.dumps.is_empty() {
println!("<empty> no dumps available\n");
return Ok(());
}

index_file.backups.sort_by(|a, b| a.cmp(b).reverse());
index_file.dumps.sort_by(|a, b| a.cmp(b).reverse());

let mut table = table();
table.set_titles(row!["name", "size", "when", "compressed", "encrypted"]);
let formatter = Formatter::new();
let now = epoch_millis();

for backup in index_file.backups {
for dump in index_file.dumps {
table.add_row(row![
backup.directory_name.as_str(),
to_human_readable_unit(backup.size),
formatter.convert(Duration::from_millis((now - backup.created_at) as u64)),
backup.compressed,
backup.encrypted,
dump.directory_name.as_str(),
to_human_readable_unit(dump.size),
formatter.convert(Duration::from_millis((now - dump.created_at) as u64)),
dump.compressed,
dump.encrypted,
]);
}

Expand Down
Loading

0 comments on commit ab75d76

Please sign in to comment.