Skip to content

Commit c67c538

Browse files
authored
Merge pull request #66 from jdno/fastly
Invalidate release distribution on Fastly
2 parents a226029 + 3a663de commit c67c538

File tree

3 files changed

+94
-3
lines changed

3 files changed

+94
-3
lines changed

src/config.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::discourse::Discourse;
2+
use crate::fastly::Fastly;
23
use crate::github::Github;
34
use crate::Context;
45
use anyhow::{Context as _, Error};
@@ -192,6 +193,14 @@ pub(crate) struct Config {
192193

193194
/// The app ID associated with the private key being passed.
194195
pub(crate) github_app_id: Option<u32>,
196+
197+
/// An API token for Fastly with the `purge_select` scope.
198+
pub(crate) fastly_api_token: Option<String>,
199+
/// The static domain name that is used with Fastly, e.g. `static.rust-lang.org`.
200+
pub(crate) fastly_static_domain: Option<String>,
201+
202+
/// Temporary variable to test Fastly in the dev environment only.
203+
pub(crate) invalidate_fastly: bool,
195204
}
196205

197206
impl Config {
@@ -226,6 +235,9 @@ impl Config {
226235
discourse_api_key: maybe_env("DISCOURSE_API_KEY")?,
227236
github_app_key: maybe_env("GITHUB_APP_KEY")?,
228237
github_app_id: maybe_env("GITHUB_APP_ID")?,
238+
fastly_api_token: maybe_env("FASTLY_API_TOKEN")?,
239+
fastly_static_domain: maybe_env("FASTLY_STATIC_DOMAIN")?,
240+
invalidate_fastly: bool_env("INVALIDATE_FASTLY")?,
229241
})
230242
}
231243

@@ -248,6 +260,14 @@ impl Config {
248260
}
249261
}
250262

263+
pub(crate) fn fastly(&self) -> Option<Fastly> {
264+
if let (Some(token), Some(domain)) = (&self.fastly_api_token, &self.fastly_static_domain) {
265+
Some(Fastly::new(token.clone(), domain.clone()))
266+
} else {
267+
None
268+
}
269+
}
270+
251271
pub(crate) fn stable_dev_static_blog_contents(
252272
&self,
253273
release: &str,

src/fastly.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use anyhow::Error;
2+
use curl::easy::Easy;
3+
4+
pub struct Fastly {
5+
api_token: String,
6+
domain: String,
7+
client: Easy,
8+
}
9+
10+
impl Fastly {
11+
pub fn new(api_token: String, domain: String) -> Self {
12+
Self {
13+
api_token,
14+
domain,
15+
client: Easy::new(),
16+
}
17+
}
18+
19+
pub fn purge(&mut self, path: &str) -> Result<(), Error> {
20+
self.start_new_request()?;
21+
22+
self.client.post(true)?;
23+
self.client.url(&format!(
24+
"https://api.fastly.com/purge/{}/{}",
25+
self.domain, path
26+
))?;
27+
28+
self.client.perform().map_err(|error| error.into())
29+
}
30+
31+
fn start_new_request(&mut self) -> anyhow::Result<()> {
32+
self.client.reset();
33+
self.client.useragent("rust-lang/promote-release")?;
34+
let mut headers = curl::easy::List::new();
35+
headers.append(&format!("Fastly-Key: {}", self.api_token))?;
36+
headers.append("Content-Type: application/json")?;
37+
self.client.http_headers(headers)?;
38+
Ok(())
39+
}
40+
}

src/main.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod build_manifest;
55
mod config;
66
mod curl_helper;
77
mod discourse;
8+
mod fastly;
89
mod github;
910
mod recompress;
1011
mod sign;
@@ -18,6 +19,7 @@ use std::time::Duration;
1819
use std::{collections::HashSet, env};
1920

2021
use crate::build_manifest::BuildManifest;
22+
use crate::config::{Channel, Config};
2123
use crate::sign::Signer;
2224
use crate::smoke_test::SmokeTester;
2325
use anyhow::Error;
@@ -26,8 +28,6 @@ use curl::easy::Easy;
2628
use fs2::FileExt;
2729
use github::{CreateTag, Github};
2830

29-
use crate::config::{Channel, Config};
30-
3131
const TARGET: &str = env!("TARGET");
3232

3333
const BLOG_PRIMARY_BRANCH: &str = "master";
@@ -565,7 +565,12 @@ impl Context {
565565
}
566566

567567
fn invalidate_releases(&self) -> Result<(), Error> {
568-
self.invalidate_cloudfront(&self.config.cloudfront_static_id, &["/dist/*".into()])
568+
let paths = ["/dist/*".into()];
569+
570+
self.invalidate_cloudfront(&self.config.cloudfront_static_id, &paths)?;
571+
self.invalidate_fastly(&paths)?;
572+
573+
Ok(())
569574
}
570575

571576
fn invalidate_cloudfront(&self, distribution_id: &str, paths: &[String]) -> Result<(), Error> {
@@ -600,6 +605,32 @@ impl Context {
600605
Ok(())
601606
}
602607

608+
fn invalidate_fastly(&self, paths: &[String]) -> Result<(), Error> {
609+
// Fastly invalidations are opt-in while we test the integration
610+
// Set PROMOTE_RELEASE_INVALIDATE_FASTLY=1 to enable them
611+
if !self.config.invalidate_fastly {
612+
return Ok(());
613+
}
614+
615+
let mut fastly = match self.config.fastly() {
616+
Some(fastly) => fastly,
617+
None => {
618+
println!();
619+
println!("WARNING! Skipped Fastly invalidation of: {:?}", paths);
620+
println!("Set PROMOTE_RELEASE_FASTLY_API_TOKEN and PROMOTE_RELEASE_FASTLY_STATIC_DOMAIN if you want to invalidate Fastly");
621+
println!();
622+
return Ok(());
623+
}
624+
};
625+
626+
for path in paths {
627+
let path = path.replace('*', "");
628+
fastly.purge(&path)?;
629+
}
630+
631+
Ok(())
632+
}
633+
603634
fn tag_release(&mut self, rustc_commit: &str, signer: &mut Signer) -> Result<(), Error> {
604635
if self.config.channel != Channel::Stable {
605636
// We don't tag non-stable releases

0 commit comments

Comments
 (0)