Skip to content

Commit 8d76c62

Browse files
committed
Update documentation
1 parent 2c026c8 commit 8d76c62

File tree

4 files changed

+135
-60
lines changed

4 files changed

+135
-60
lines changed

README.md

Lines changed: 94 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -36,50 +36,113 @@ serve new files to users, or update redirects, etc.
3636
NOTE: Fileset uses the default App Engine Google Cloud Storage bucket
3737
(`gs://appid.appspot.com`) to upload files.
3838

39-
1. Install the Fileset CLI.
40-
41-
```bash
42-
npm install --save-dev @blinkk/fileset
39+
1. Within your project, create a directory to house the server files, e.g.
40+
`./backend/fileset`. Avoid mixing the server configuration with any tools to
41+
build your website. The `package.json`, etc. should be kept separate in order
42+
to keep the deployment slim.
43+
44+
2. Create a `package.json` like the below. App Engine will use `npm start` to
45+
run the server.
46+
47+
```json
48+
{
49+
"scripts": {
50+
"start": "fileset serve"
51+
},
52+
"dependencies": {
53+
"@blinkk/fileset": "^0.1.0"
54+
}
55+
}
4356
```
4457

45-
2. Create an `app.yaml` for Google App Engine deployment.
58+
3. Create an `app.yaml` for Google App Engine deployment.
4659

4760
```yaml
4861
service: fileset
4962
runtime: nodejs10
50-
entrypoint: fileset serve
5163
```
5264
53-
3. Deploy the app.
65+
4. Deploy the app and enable the Cloud Datastore API.
66+
67+
```bash
68+
gcloud app deploy --project=<AppID> app.yaml
69+
gcloud services enable datastore.googleapis.com --project=<AppID>
70+
```
71+
72+
### Deployment setup
73+
74+
NOTE: Before you can deploy, you'll need to authenticate. Refer to the
75+
[authentication documentation](#uploader-authentication) if you have not used
76+
Google Cloud Platform services before and need information on authentication.
77+
78+
1. Create a `fileset.yaml` configuration file.
79+
80+
```yaml
81+
site: siteId # Specify a site ID. If blank, `default` will be used.
82+
schedule:
83+
default: master # Specify a branch for the prod deployment.
84+
```
85+
86+
2. Generate your files.
87+
88+
Use a static site generator or just manually create a directory containing files
89+
to upload. In the below example, the files in the directory `build` are
90+
uploaded.
91+
92+
4. Upload your files.
5493

5594
```bash
56-
gcloud app deploy app.yaml
95+
fileset upload ./build
5796
```
5897

59-
### Authentication for deployment
98+
NOTE: The uploader will look for `fileset.yaml` within the `./build` directory
99+
first. If it's not found, it will look up in the parent folder for a
100+
`fileset.yaml` file. If the config file doesn't exist in the `./build` or parent
101+
folder, the uploader will abort.
60102

61-
Before you are able to deploy your files, you'll need to set up authentication
62-
to deploy.
103+
5. That's it! Files have been uploaded to Google Cloud Storage and the uploaded
104+
directory is now being served by the application server.
63105

64-
1. Identify the service account to use.
106+
TODO: Document Identity-Aware Proxy setup and CLI authentication.
107+
108+
## Uploader authentication
109+
110+
You'll need to be authenticated to deploy files and upload the serving manifests.
111+
112+
### Local testing / user account authentication
113+
114+
If you are testing locally, your user account can be used to authenticate to
115+
Cloud Datastore and Cloud Storage. Simply run the below command to create
116+
credentials used for authentication:
117+
118+
```bash
119+
gcloud auth application-default login
120+
```
121+
122+
### Continuous deployment / service account authentication
123+
124+
If you are using a service account for deployment, you'll need to ensure it has
125+
the right permissions.
126+
127+
#### 1. Identify the service account to use.
65128

66129
Authentication to upload your files is done using a service account. You'll
67130
generally want to use one of two service accounts:
68131

69-
a. When the command is invoked from Google Cloud Build, your project's Cloud
70-
Build service account (`<ProjectNumber>@cloudbuild.gserviceaccount.com`) is
71-
used.
132+
__Cloud Build service account__: When the command is invoked from Google Cloud
133+
Build, your project's Cloud Build service account
134+
(`<ProjectNumber>@cloudbuild.gserviceaccount.com`) is used.
72135

73136
To determine your project's project number:
74137

75138
```bash
76139
gcloud projects describe <AppID>
77140
```
78141

79-
b. When the command is invoked locally (i.e. for testing or for manual uploads),
80-
you'll likely want to use your App Engine app's default service account
81-
(`<AppID>@appspot.gserviceaccount.com`). You can download a service account key
82-
by running:
142+
__Application default service account__: When the command is invoked locally
143+
(i.e. for testing or for manual uploads), you'll likely want to use your App
144+
Engine app's default service account (`<AppID>@appspot.gserviceaccount.com`).
145+
You can download a service account key by running:
83146

84147
```bash
85148
gcloud iam service-accounts keys create \
@@ -91,7 +154,7 @@ NOTE: This will download a `key.json` to your current directory. Avoid
91154
committing this to your Git repository. You'll want to add `key.json` to
92155
`.gitignore`.
93156

94-
2. Ensure service account has permissions.
157+
#### 2. Ensure service account has permissions.
95158

96159
The following permissions are needed:
97160

@@ -117,34 +180,6 @@ for role in datastore.owner storage.objectAdmin g; do \
117180
--role=roles/$role \
118181
; done
119182
```
120-
121-
### Deployment setup
122-
123-
1. Create a `fileset.yaml` configuration file.
124-
125-
```yaml
126-
site: siteId # Specify a site ID. If blank, `default` will be used.
127-
schedule:
128-
default: master # Specify a branch for the prod deployment.
129-
```
130-
131-
2. Generate your files.
132-
133-
Use a static site generator or just manually create a directory containing files
134-
to upload. In the below example, the files in the directory `build` are
135-
uploaded.
136-
137-
4. Upload your files.
138-
139-
```bash
140-
fileset upload -s siteId build
141-
```
142-
143-
5. That's it! Files have been uploaded to Google Cloud Storage and the uploaded
144-
directory is now being served by the application server.
145-
146-
TODO: Document Identity-Aware Proxy setup and CLI authentication.
147-
148183
## Environments
149184

150185
Fileset uses Git branches to determine whether files should be in production
@@ -175,3 +210,14 @@ Staging URL: https://default-f3a9abb-dot-fileset-dot-appid.appspot.com
175210
...
176211
Staging URL: https://default-4fb48ce-dot-fileset-dot-appid.appspot.com
177212
```
213+
214+
## Testing
215+
216+
You can verify Fileset server is working as you expect by looking for the following headers:
217+
218+
| Header | Description |
219+
|-|-|
220+
| `x-fileset-site` | The site being served. Usually this will be `default` but for multi-site installations, this will be useful for determining which site is serving. |
221+
| `x-fileset-ref` | The Git commit sha that corresponds to the serving manifest that is handling your request. |
222+
| `x-fileset-blob` | The blob directory key corresponding to the file being served. This is the SHA-1 hash of the file's content. |
223+
| `x-fileset-ttl` | For scheduled deployments, the value of this header will correspond to the timestamp for the timed deployment being served. |

app.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
service: fileset2
22
runtime: nodejs10
33
instance_class: F4
4-
entrypoint: node ./dist/src/index.js serve
4+
entrypoint: fileset serve

src/commands/upload.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export class UploadCommand {
4343
const gitData = await getGitData(path);
4444
const config = findConfig(path);
4545
const ttl = this.options.ttl ? new Date(this.options.ttl) : undefined;
46+
const site = this.options.site || config.site;
47+
4648
let bucket = this.options.bucket;
4749
if (!bucket && config.google_cloud_project) {
4850
bucket = `${config.google_cloud_project}.appspot.com`;
@@ -54,7 +56,13 @@ export class UploadCommand {
5456
'Unable to determine which Google Cloud Storage bucket to use. You must specify a `google_cloud_project` in `fileset.yaml` or specify a `GOOGLE_CLOUD_PROJECT` environment variable.'
5557
);
5658
}
57-
const site = this.options.site || config.site;
59+
60+
const googleCloudProject =
61+
config.google_cloud_project || process.env.GOOGLE_CLOUD_PROJECT;
62+
if (!googleCloudProject) {
63+
throw new Error('Unable to determine the Google Cloud project.');
64+
}
65+
5866
const manifest = new Manifest(
5967
site,
6068
this.options.ref || gitData.ref,
@@ -65,6 +73,12 @@ export class UploadCommand {
6573
console.log(`No files found in -> ${path}`);
6674
return;
6775
}
68-
upload.uploadManifest(bucket, manifest, this.options.force, ttl);
76+
upload.uploadManifest(
77+
googleCloudProject,
78+
bucket,
79+
manifest,
80+
this.options.force,
81+
ttl
82+
);
6983
}
7084
}

src/upload.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {asyncify, mapLimit} from 'async';
88
import {Datastore} from '@google-cloud/datastore';
99
import {Storage} from '@google-cloud/storage';
1010
import {entity} from '@google-cloud/datastore/build/src/entity';
11+
import {google} from '@google-cloud/datastore/build/protos/protos';
1112

12-
const datastore = new Datastore();
1313
const NUM_CONCURRENT_UPLOADS = 64;
1414

1515
function getBlobPath(siteId: string, hash: string) {
@@ -51,13 +51,16 @@ function createProgressBar() {
5151
}
5252

5353
export async function uploadManifest(
54+
googleCloudProject: string,
5455
bucket: string,
5556
manifest: Manifest,
5657
force?: boolean,
5758
ttl?: Date
5859
) {
5960
console.log(`Using storage: ${bucket}/${getBlobPath(manifest.site, '')}`);
60-
const storageBucket = new Storage().bucket(bucket);
61+
const storageBucket = new Storage({
62+
projectId: googleCloudProject,
63+
}).bucket(bucket);
6164
const bar = createProgressBar();
6265

6366
// Check for files that have already been uploaded. Files already uploaded do
@@ -72,7 +75,7 @@ export async function uploadManifest(
7275
);
7376

7477
if (numTotalFiles <= 0) {
75-
finalize(manifest, ttl);
78+
finalize(googleCloudProject, manifest, ttl);
7679
} else {
7780
let bytesTransferred = 0;
7881
let numProcessedFiles = 0;
@@ -82,7 +85,7 @@ export async function uploadManifest(
8285
});
8386
// @ts-ignore
8487
bar.on('stop', () => {
85-
finalize(manifest, ttl);
88+
finalize(googleCloudProject, manifest, ttl);
8689
});
8790

8891
mapLimit(
@@ -130,7 +133,11 @@ export async function uploadManifest(
130133
}
131134
}
132135

133-
async function saveManifestEntity(key: entity.Key, data: any) {
136+
async function saveManifestEntity(
137+
datastore: Datastore,
138+
key: entity.Key,
139+
data: any
140+
) {
134141
const ent = {
135142
key: key,
136143
excludeFromIndexes: ['paths'],
@@ -139,7 +146,15 @@ async function saveManifestEntity(key: entity.Key, data: any) {
139146
await datastore.save(ent);
140147
}
141148

142-
async function finalize(manifest: Manifest, ttl?: Date) {
149+
async function finalize(
150+
googleCloudProject: string,
151+
manifest: Manifest,
152+
ttl?: Date
153+
) {
154+
const datastore = new Datastore({
155+
projectId: googleCloudProject,
156+
// keyFilename: '/path/to/keyfile.json',
157+
});
143158
const manifestPaths = manifest.toJSON();
144159
const now = new Date();
145160

@@ -148,7 +163,7 @@ async function finalize(manifest: Manifest, ttl?: Date) {
148163
'Fileset2Manifest',
149164
`${manifest.site}:ref:${manifest.shortSha}`,
150165
]);
151-
await saveManifestEntity(key, {
166+
await saveManifestEntity(datastore, key, {
152167
site: manifest.site,
153168
ref: manifest.ref,
154169
branch: manifest.branch,
@@ -162,7 +177,7 @@ async function finalize(manifest: Manifest, ttl?: Date) {
162177
'Fileset2Manifest',
163178
`${manifest.site}:branch:${manifest.branch}`,
164179
]);
165-
await saveManifestEntity(branchKey, {
180+
await saveManifestEntity(datastore, branchKey, {
166181
site: manifest.site,
167182
ref: manifest.ref,
168183
branch: manifest.branch,
@@ -181,6 +196,6 @@ async function finalize(manifest: Manifest, ttl?: Date) {
181196
);
182197
// TODO: Allow customizing the staging URL using `fileset.yaml` configuration.
183198
console.log(
184-
`Staged: https://${manifest.site}-${manifest.shortSha}-dot-fileset2-dot-${process.env.GOOGLE_CLOUD_PROJECT}.appspot.com`
199+
`Staged: https://${manifest.site}-${manifest.shortSha}-dot-fileset2-dot-${googleCloudProject}.appspot.com`
185200
);
186201
}

0 commit comments

Comments
 (0)