Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy to Production – 2023-12-18 #2488

Merged
merged 47 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c427fcf
Add `aws-sdk/client-s3` package to access Cloudflare R2 bucket
pdcp1 Oct 25, 2023
e37c17e
Remove `gatsby-source-s3` plugin
pdcp1 Oct 25, 2023
799088b
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Oct 25, 2023
0672516
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Oct 30, 2023
bb7cf31
Connect to Cloudflare R2 to get the snapshot files
pdcp1 Oct 30, 2023
f216846
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Oct 31, 2023
67534dd
Sort backup files by name descendent
pdcp1 Oct 31, 2023
8e71e7c
Add tests to snapshots download page
pdcp1 Oct 31, 2023
c040f66
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Nov 3, 2023
8ddee62
Hide unowned checklists, sort index
lmcnulty Nov 4, 2023
2aea2ab
wip
lmcnulty Nov 7, 2023
2fdee6b
Add sort selection, preview automatic risks
lmcnulty Nov 8, 2023
e008e63
wip
lmcnulty Nov 9, 2023
aeff58c
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Nov 9, 2023
ed463c5
Improve flakiness on discover test
pdcp1 Nov 9, 2023
5d71605
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Nov 13, 2023
a9030f1
wip
lmcnulty Nov 13, 2023
2b25f35
Make index and form generated risks consistent
lmcnulty Nov 14, 2023
37cc9eb
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Nov 14, 2023
c1b99b5
Replace JSON API usage with GraphQL
lmcnulty Nov 14, 2023
23d7261
Merge pull request #28 from responsible-ai-collaborative/staging
pdcp1 Nov 15, 2023
8f8f6cf
Deactivate inapplicable test, prevent invalid query
lmcnulty Nov 15, 2023
ad0b8ad
Merge pull request #29 from pdcp1/staging
pdcp1 Nov 15, 2023
5ac8fbb
Remove debuggage
lmcnulty Nov 16, 2023
9c986a2
Add message for no risks, neaten code
lmcnulty Nov 16, 2023
d62827b
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Nov 16, 2023
86598f1
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Nov 29, 2023
dec8511
Revise per reviews
lmcnulty Nov 16, 2023
02c132c
merge
lmcnulty Nov 29, 2023
3ab7d86
Increase Select right-padding
lmcnulty Nov 29, 2023
1deef8f
Factor common checklist test logic
lmcnulty Dec 5, 2023
a202ef9
Merge branch 'staging' of https://github.com/responsible-ai-collabora…
lmcnulty Dec 7, 2023
3667800
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Dec 8, 2023
87c785f
Fix text
pdcp1 Dec 8, 2023
86d06eb
Fix = vs == in find user
lmcnulty Dec 11, 2023
9571d34
Fix `metatitle` for Blog posts
pdcp1 Dec 11, 2023
ac37344
Fix Twitter share tests
pdcp1 Dec 11, 2023
e2d3e3f
Merge pull request #2483 from pdcp1/fix/twitter-share
kepae Dec 11, 2023
036cca1
Merge branch 'staging' into feature/cloudflare-r2-backups
pdcp1 Dec 11, 2023
b9390a5
Merge pull request #2375 from pdcp1/feature/cloudflare-r2-backups
kepae Dec 11, 2023
ecd0c14
Merge pull request #2394 from lmcnulty/checklist-index-visibility-sor…
kepae Dec 12, 2023
42caba1
Update LICENSE.txt year
kepae Dec 13, 2023
7ff2182
Merge pull request #2491 from responsible-ai-collaborative/kepae-license
kepae Dec 13, 2023
ddfd3ec
Merge pull request #2469 from lmcnulty/checklists-tests-factor-common…
kepae Dec 14, 2023
efe3957
Merge pull request #2486 from lmcnulty/checklists-fix-find-user-equal…
kepae Dec 15, 2023
fb32a52
Add null check to className in string templates
lmcnulty Dec 18, 2023
c96aa47
Merge pull request #2499 from lmcnulty/fix-class-undefined
kepae Dec 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
AI Incident Database: A program for the archiving of artificial intelligence incidents.

Copyright (C) 2022 Responsible AI Collaborative, Inc.
Copyright (C) 2023 Responsible AI Collaborative, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,12 @@ GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE=1 # specific to Netlify, for large sites
GATSBY_CPU_COUNT=2 # limits the number of Gatsby threads, helping with deployment stability
NODE_VERSION=18 # this is required by Gatsby v5
NODE_OPTIONS=--max-old-space-size=4096 # increase default heap size to prevent crashes during build
# The following "CLOUDFLARE_R2" variables are required to create the /research/snapshots/ page
CLOUDFLARE_R2_ACCOUNT_ID=[The Cloudflare R2 account ID (e.g.: 8f4144a9d995a9921d0200db59f6a00e)]
CLOUDFLARE_R2_ACCESS_KEY_ID=[The Cloudflare R2 access key ID (e.g.: 7aa73208bc89cee3195879e578b291ee)]
CLOUDFLARE_R2_SECRET_ACCESS_KEY=[The Cloudflare R2 secret access key]
CLOUDFLARE_R2_BUCKET_NAME=[The Cloudflare R2 bucket name (e.g.: 'aiid-public')]
GATSBY_CLOUDFLARE_R2_PUBLIC_BUCKET_URL=[The Cloudflare R2 public bucket URL (e.g.: https://pub-daddb16dc28841779b83690f75eb5c58.r2.dev)]
```
### Github Actions
Two workflows take care of deploying the Realm app to both `production` and `staging` environments, defined in `realm-production.yml` and `realm-staging.yml`. Each workflow looks for environment variables defined in a GitHub Environment named `production` and `staging`.
Expand Down
7 changes: 7 additions & 0 deletions site/gatsby-site/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ const config = {
rollbar: {
token: process.env.GATSBY_ROLLBAR_TOKEN,
},
cloudflareR2: {
accountId: process.env.CLOUDFLARE_R2_ACCOUNT_ID,
accessKeyId: process.env.CLOUDFLARE_R2_ACCESS_KEY_ID,
secretAccessKey: process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY,
bucketName: process.env.CLOUDFLARE_R2_BUCKET_NAME,
publicBucketUrl: process.env.GATSBY_CLOUDFLARE_R2_PUBLIC_BUCKET_URL,
},
};

module.exports = config;
126 changes: 45 additions & 81 deletions site/gatsby-site/cypress/e2e/integration/apps/checklistsForm.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ const { gql } = require('@apollo/client');
describe('Checklists App Form', () => {
const url = '/apps/checklists?id=testChecklist';

const defaultChecklist = {
__typename: 'Checklist',
about: '',
id: 'testChecklist',
name: 'Test Checklist',
owner_id: 'a-fake-user-id-that-does-not-exist',
risks: [],
tags_goals: [],
tags_methods: [],
tags_other: [],
};

const usersQuery = {
query: gql`
{
Expand All @@ -19,27 +31,36 @@ describe('Checklists App Form', () => {
timeout: 120000, // mongodb admin api is extremely slow
};

it('Should have read-only access for non-logged-in users', () => {
const withLogin = (callback) => {
cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword'));

cy.query(usersQuery).then(({ data: { users } }) => {
const user = users.find((user) => user.adminData.email == Cypress.env('e2eUsername'));

callback({ user });
});
};

const interceptFindChecklist = (checklist) => {
cy.conditionalIntercept(
'**/graphql',
(req) => req.body.operationName == 'findChecklist',
'findChecklist',
{
data: {
checklist: {
__typename: 'Checklist',
about: '',
id: 'testChecklist',
name: 'Test Checklist',
owner_id: 'a-fake-user-id-that-does-not-exist',
risks: [],
tags_goals: [],
tags_methods: [],
tags_other: [],
},
},
}
{ data: { checklist } }
);
};

const interceptUpsertChecklist = (checklist) => {
cy.conditionalIntercept(
'**/graphql',
(req) => req.body.operationName == 'upsertChecklist',
'upsertChecklist',
{ data: { checklist } }
);
};

it('Should have read-only access for non-logged-in users', () => {
interceptFindChecklist(defaultChecklist);

cy.visit(url);

Expand All @@ -55,26 +76,7 @@ describe('Checklists App Form', () => {
maybeIt('Should have read-only access for logged-in non-owners', () => {
cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword'));

cy.conditionalIntercept(
'**/graphql',
(req) => req.body.operationName == 'findChecklist',
'findChecklist',
{
data: {
checklist: {
__typename: 'Checklist',
about: '',
id: 'testChecklist',
name: 'Test Checklist',
owner_id: 'a-fake-user-id-that-does-not-exist',
risks: [],
tags_goals: [],
tags_methods: [],
tags_other: [],
},
},
}
);
interceptFindChecklist(defaultChecklist);

cy.visit(url);

Expand All @@ -88,51 +90,13 @@ describe('Checklists App Form', () => {
});

maybeIt('Should allow editing for owner', () => {
cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword'));

cy.query(usersQuery).then(({ data: { users } }) => {
const user = users.find((user) => user.adminData.email == Cypress.env('e2eUsername'));

cy.conditionalIntercept(
'**/graphql',
(req) => req.body.operationName == 'findChecklist',
'findChecklist',
{
data: {
checklist: {
__typename: 'Checklist',
about: '',
id: 'testChecklist',
name: 'Test Checklist',
owner_id: user.userId,
risks: [],
tags_goals: [],
tags_methods: [],
tags_other: [],
},
},
}
);
cy.conditionalIntercept(
'**/graphql',
(req) => req.body.operationName == 'upsertChecklist',
'upsertChecklist',
{
data: {
checklist: {
__typename: 'Checklist',
about: "It's a system that does something probably.",
id: 'testChecklist',
name: 'Test Checklist',
owner_id: user.userId,
risks: [],
tags_goals: [],
tags_methods: [],
tags_other: [],
},
},
}
);
withLogin(({ user }) => {
interceptFindChecklist({ ...defaultChecklist, owner_id: user.userId });
interceptUpsertChecklist({
...defaultChecklist,
owner_id: user.userId,
about: "It's a system that does something probably.",
});

cy.visit(url);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ describe('Checklists App Index', () => {
cy.get(newChecklistButtonQuery).should('exist');
});

maybeIt('Should show delete buttons only for owned checklists', () => {
/* We're now showing only the user's owned checklists,
* so we can't test that the delete button doesn't show up on unowned ones.
* Eventually, we'll probably have public checklists show up here too,
* so this can be skipped with a TODO to activate it
* once there are unowned checklists displayed.
*/
it.skip('Should show delete buttons only for owned checklists', () => {
cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword'));

cy.query(usersQuery).then(({ data: { users } }) => {
Expand Down
30 changes: 30 additions & 0 deletions site/gatsby-site/cypress/e2e/integration/snapshots.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { conditionalIt } from '../../support/utils';

describe('The Database Snapshots Page', () => {
const url = '/research/snapshots';

it('Successfully loads', () => {
cy.visit(url);
});

conditionalIt(
!Cypress.env('isEmptyEnvironment'),
'Should display a list of snapshots to download',
() => {
cy.visit(url);

cy.get('[data-cy="snapshots-list"] li')
.should('exist')
.and('be.visible')
.and('have.length.gt', 0);

cy.get('[data-cy="snapshots-list"] li').each((item) => {
expect(item[0].innerText).to.match(
/^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2} (AM|PM) · \d+(\.\d{2})? MB · backup-\d{14}\.tar\.bz2$/
);

expect(item.find('a').attr('href')).to.match(/^https:\/\/.*\/backup-\d{14}\.tar\.bz2$/);
});
}
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('Social Share buttons on pages', { retries: { runMode: 4 } }, () => {
});
}

urlsToTest.forEach(({ page, url, shareButtonSections }) => {
urlsToTest.forEach(({ page, url, title, shareButtonSections }) => {
it(`${page} page should have ${shareButtonSections} Social Share button sections`, () => {
cy.visit(url);

Expand All @@ -38,8 +38,7 @@ describe('Social Share buttons on pages', { retries: { runMode: 4 } }, () => {
const canonicalUrl = `https://incidentdatabase.ai${url}`;

// Twitter share
// TODO: https://github.com/responsible-ai-collaborative/aiid/issues/2481
it.skip(`${page} page should have a Twitter share button`, () => {
it(`${page} page should have a Twitter share button`, () => {
cy.visit(url);

cy.get('[data-cy=btn-share-twitter]').should('exist');
Expand All @@ -57,9 +56,8 @@ describe('Social Share buttons on pages', { retries: { runMode: 4 } }, () => {
cy.get('@popup_twitter', { timeout: 8000 }).should('be.called');
cy.url().should(
'contain',
`https://twitter.com/i/flow/login?redirect_after_login=%2Fintent%2Ftweet%3Ftext%3D`
`https://twitter.com/intent/tweet?text=${encodeURI(title)}&url=${canonicalUrl}`
);
cy.url().should('contain', `url%3D${encodeURIComponent(canonicalUrl)}`);
});

// LinkedIn share
Expand Down
14 changes: 0 additions & 14 deletions site/gatsby-site/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,20 +220,6 @@ const plugins = [
],
},
},
{
resolve: `gatsby-source-s3`,
options: {
aws: {
// This AWS IAM user has been provisioned no permissions, but the plugin requires a user to
// get a listing of the public S3 bucket. User: backupindexpublic
accessKeyId: 'AKIA25BP4AERUFDGAJUJ',
secretAccessKeyId: 'backupindexpublic',
secretAccessKey: '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',
},
buckets: ['aiid-backups-public'],
// expiration: 120,
},
},
{
resolve: `gatsby-theme-i18n`,
options: {
Expand Down
Loading
Loading