Skip to content

Commit 03d613f

Browse files
committed
gnd: Integration tests (#6035)
* node/gnd: Make ports configurable * node/gnd: Deploy all subgraphs on startup * tests: Refactor subgraph datasources in TestCase * tests: refactor Testcase method for source subgraphs * tests: Add integration tests for gnd * store: Use bundled pq-sys * gnd: remove temp database directory on exit * gnd: use pgtemp from graphprotocol org * gnd: add alias for pgtemp db for windows * gnd: use deep codesigning for macos binaries * update workflow to add entitlements.plist
1 parent a6677a5 commit 03d613f

File tree

12 files changed

+459
-90
lines changed

12 files changed

+459
-90
lines changed

.github/workflows/gnd-binary-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ jobs:
109109
certificate-data: ${{ secrets.APPLE_CERT_DATA }}
110110
certificate-password: ${{ secrets.APPLE_CERT_PASSWORD }}
111111
certificate-id: ${{ secrets.APPLE_TEAM_ID }}
112-
options: --options runtime
112+
options: --options runtime --entitlements entitlements.plist
113113

114114
- name: Notarize macOS binary
115115
if: startsWith(matrix.runner, 'macos')

Cargo.lock

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ diesel = { version = "2.2.7", features = [
5454
"chrono",
5555
"i-implement-a-third-party-backend-and-opt-into-breaking-changes",
5656
] }
57+
pq-sys = { version = "0.6", features = ["bundled"] }
5758
diesel-derive-enum = { version = "2.1.0", features = ["postgres"] }
5859
diesel-dynamic-schema = { version = "0.2.3", features = ["postgres"] }
5960
diesel_derives = "2.2.5"

entitlements.plist

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.security.cs.allow-jit</key>
6+
<true/>
7+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
8+
<true/>
9+
<key>com.apple.security.cs.disable-executable-page-protection</key>
10+
<true/>
11+
</dict>
12+
</plist>

node/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ globset = "0.4.16"
4747
notify = "8.0.0"
4848

4949
[target.'cfg(unix)'.dependencies]
50-
pgtemp = { git = "https://github.com/incrypto32/pgtemp", branch = "initdb-args" }
50+
pgtemp = { git = "https://github.com/graphprotocol/pgtemp", branch = "initdb-args" }

node/src/bin/dev.rs

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{mem, path::Path, sync::Arc};
1+
use std::{path::Path, sync::Arc};
22

33
use anyhow::{Context, Result};
44
use clap::Parser;
@@ -13,14 +13,23 @@ use graph::{
1313
};
1414
use graph_core::polling_monitor::ipfs_service;
1515
use graph_node::{
16+
dev::watcher,
1617
dev::watcher::{parse_manifest_args, watch_subgraphs},
1718
launcher,
1819
opt::Opt,
1920
};
2021
use lazy_static::lazy_static;
2122

2223
#[cfg(unix)]
23-
use pgtemp::PgTempDBBuilder;
24+
use pgtemp::{PgTempDB, PgTempDBBuilder};
25+
26+
// Add an alias for the temporary Postgres DB handle. On non unix
27+
// targets we don’t have pgtemp, but we still need the type to satisfy the
28+
// function signatures.
29+
#[cfg(unix)]
30+
type TempPgDB = PgTempDB;
31+
#[cfg(not(unix))]
32+
type TempPgDB = ();
2433

2534
git_testament!(TESTAMENT);
2635
lazy_static! {
@@ -90,6 +99,35 @@ pub struct DevOpt {
9099
default_value = "https://api.thegraph.com/ipfs"
91100
)]
92101
pub ipfs: Vec<String>,
102+
#[clap(
103+
long,
104+
default_value = "8000",
105+
value_name = "PORT",
106+
help = "Port for the GraphQL HTTP server",
107+
env = "GRAPH_GRAPHQL_HTTP_PORT"
108+
)]
109+
pub http_port: u16,
110+
#[clap(
111+
long,
112+
default_value = "8030",
113+
value_name = "PORT",
114+
help = "Port for the index node server"
115+
)]
116+
pub index_node_port: u16,
117+
#[clap(
118+
long,
119+
default_value = "8020",
120+
value_name = "PORT",
121+
help = "Port for the JSON-RPC admin server"
122+
)]
123+
pub admin_port: u16,
124+
#[clap(
125+
long,
126+
default_value = "8040",
127+
value_name = "PORT",
128+
help = "Port for the Prometheus metrics server"
129+
)]
130+
pub metrics_port: u16,
93131
}
94132

95133
/// Builds the Graph Node options from DevOpt
@@ -109,7 +147,12 @@ fn build_args(dev_opt: &DevOpt, db_url: &str) -> Result<Opt> {
109147
args.push("--postgres-url".to_string());
110148
args.push(db_url.to_string());
111149

112-
let opt = Opt::parse_from(args);
150+
let mut opt = Opt::parse_from(args);
151+
152+
opt.http_port = dev_opt.http_port;
153+
opt.admin_port = dev_opt.admin_port;
154+
opt.metrics_port = dev_opt.metrics_port;
155+
opt.index_node_port = dev_opt.index_node_port;
113156

114157
Ok(opt)
115158
}
@@ -118,7 +161,7 @@ async fn run_graph_node(
118161
logger: &Logger,
119162
opt: Opt,
120163
link_resolver: Arc<dyn LinkResolver>,
121-
subgraph_updates_channel: Option<mpsc::Receiver<(DeploymentHash, SubgraphName)>>,
164+
subgraph_updates_channel: mpsc::Receiver<(DeploymentHash, SubgraphName)>,
122165
) -> Result<()> {
123166
let env_vars = Arc::new(EnvVars::from_env().context("Failed to load environment variables")?);
124167

@@ -139,16 +182,19 @@ async fn run_graph_node(
139182
env_vars,
140183
ipfs_service,
141184
link_resolver,
142-
subgraph_updates_channel,
185+
Some(subgraph_updates_channel),
143186
)
144187
.await;
145188
Ok(())
146189
}
147190

148191
/// Get the database URL, either from the provided option or by creating a temporary database
149-
fn get_database_url(postgres_url: Option<&String>, database_dir: &Path) -> Result<String> {
192+
fn get_database_url(
193+
postgres_url: Option<&String>,
194+
database_dir: &Path,
195+
) -> Result<(String, Option<TempPgDB>)> {
150196
if let Some(url) = postgres_url {
151-
Ok(url.clone())
197+
Ok((url.clone(), None))
152198
} else {
153199
#[cfg(unix)]
154200
{
@@ -162,13 +208,14 @@ fn get_database_url(postgres_url: Option<&String>, database_dir: &Path) -> Resul
162208

163209
let db = PgTempDBBuilder::new()
164210
.with_data_dir_prefix(database_dir)
165-
.with_initdb_param("-E", "UTF8")
166-
.with_initdb_param("--locale", "C")
211+
.persist_data(false)
212+
.with_initdb_arg("-E", "UTF8")
213+
.with_initdb_arg("--locale", "C")
167214
.start();
168215
let url = db.connection_uri().to_string();
169-
// Prevent the database from being dropped by forgetting it
170-
mem::forget(db);
171-
Ok(url)
216+
// Return the handle so it lives for the lifetime of the program; dropping it will
217+
// shut down Postgres and remove the temporary directory automatically.
218+
Ok((url, Some(db)))
172219
}
173220

174221
#[cfg(not(unix))]
@@ -182,49 +229,76 @@ fn get_database_url(postgres_url: Option<&String>, database_dir: &Path) -> Resul
182229

183230
#[tokio::main]
184231
async fn main() -> Result<()> {
232+
std::env::set_var("ETHEREUM_REORG_THRESHOLD", "10");
233+
std::env::set_var("GRAPH_NODE_DISABLE_DEPLOYMENT_HASH_VALIDATION", "true");
185234
env_logger::init();
186235
let dev_opt = DevOpt::parse();
187236

188237
let database_dir = Path::new(&dev_opt.database_dir);
189238

190239
let logger = logger(true);
191240

192-
info!(logger, "Starting Graph Node Dev");
241+
info!(logger, "Starting Graph Node Dev 1");
193242
info!(logger, "Database directory: {}", database_dir.display());
194243

195-
// Get the database URL
196-
let db_url = get_database_url(dev_opt.postgres_url.as_ref(), database_dir)?;
244+
// Get the database URL and keep the temporary database handle alive for the life of the
245+
// program so that it is dropped (and cleaned up) on graceful shutdown.
246+
let (db_url, mut temp_db_opt) = get_database_url(dev_opt.postgres_url.as_ref(), database_dir)?;
197247

198248
let opt = build_args(&dev_opt, &db_url)?;
199249

200250
let (manifests_paths, source_subgraph_aliases) =
201251
parse_manifest_args(dev_opt.manifests, dev_opt.sources, &logger)?;
202252
let file_link_resolver = Arc::new(FileLinkResolver::new(None, source_subgraph_aliases.clone()));
203253

204-
let (tx, rx) = dev_opt.watch.then(|| mpsc::channel(1)).unzip();
254+
let (tx, rx) = mpsc::channel(1);
205255

206256
let logger_clone = logger.clone();
207257
graph::spawn(async move {
208258
let _ = run_graph_node(&logger_clone, opt, file_link_resolver, rx).await;
209259
});
210260

211-
if let Some(tx) = tx {
261+
if let Err(e) =
262+
watcher::deploy_all_subgraphs(&logger, &manifests_paths, &source_subgraph_aliases, &tx)
263+
.await
264+
{
265+
error!(logger, "Error deploying subgraphs"; "error" => e.to_string());
266+
std::process::exit(1);
267+
}
268+
269+
if dev_opt.watch {
270+
let logger_clone_watch = logger.clone();
212271
graph::spawn_blocking(async move {
213272
if let Err(e) = watch_subgraphs(
214-
&logger,
273+
&logger_clone_watch,
215274
manifests_paths,
216275
source_subgraph_aliases,
217276
vec!["pgtemp-*".to_string()],
218277
tx,
219278
)
220279
.await
221280
{
222-
error!(logger, "Error watching subgraphs"; "error" => e.to_string());
281+
error!(logger_clone_watch, "Error watching subgraphs"; "error" => e.to_string());
223282
std::process::exit(1);
224283
}
225284
});
226285
}
227286

228-
graph::futures03::future::pending::<()>().await;
287+
// Wait for Ctrl+C so we can shut down cleanly and drop the temporary database, which removes
288+
// the data directory.
289+
tokio::signal::ctrl_c()
290+
.await
291+
.expect("Failed to listen for Ctrl+C signal");
292+
info!(logger, "Received Ctrl+C, shutting down.");
293+
294+
// Explicitly shut down and clean up the temporary database directory if we started one.
295+
#[cfg(unix)]
296+
if let Some(db) = temp_db_opt.take() {
297+
db.shutdown();
298+
}
299+
300+
std::process::exit(0);
301+
302+
#[allow(unreachable_code)]
229303
Ok(())
230304
}

node/src/dev/watcher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ fn is_relevant_event(event: &Event, watched_dirs: Vec<PathBuf>, exclusion_set: &
255255
}
256256

257257
/// Redeploys all subgraphs in the order it appears in the manifests_paths
258-
async fn deploy_all_subgraphs(
258+
pub async fn deploy_all_subgraphs(
259259
logger: &Logger,
260260
manifests_paths: &Vec<PathBuf>,
261261
source_subgraph_aliases: &HashMap<String, PathBuf>,

store/postgres/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ blake3 = "1.8"
99
chrono = { workspace = true }
1010
derive_more = { version = "2.0.1", features = ["full"] }
1111
diesel = { workspace = true }
12+
pq-sys = { workspace = true}
1213
diesel-dynamic-schema = { workspace = true }
1314
diesel-derive-enum = { workspace = true }
1415
diesel_derives = { workspace = true }

0 commit comments

Comments
 (0)