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

Expand to codecov somehow #482

Closed
43 tasks done
Tracked by #79
chadwhitacre opened this issue Jun 14, 2023 · 29 comments
Closed
43 tasks done
Tracked by #79

Expand to codecov somehow #482

chadwhitacre opened this issue Jun 14, 2023 · 29 comments
Assignees

Comments

@chadwhitacre
Copy link
Member

chadwhitacre commented Jun 14, 2023

For getsentry/team-ospo#79 I need to roll out Sentry's routing and triage process in the codecov org. I've set up a second GitHub App for this purpose (yay CoveCod! :), and I need to send the GH event stream from that app somewhere for processing. If we can, it seems best to send both event streams (getsentry and codecov) to our existing eng-pipes deployment, so that we don't have to maintain two separate deployments. We could maintain two deployments, but we already have a third viable org (syntaxfm; no immediate plans to roll out automations there) and should only expect more in the future as Sentry grows. I want a consistent GH engagement management process across all orgs. I would like to send everything through our single eng-pipes.

The primary change here will be in getClient (I'm expecting some changes in the GitHub brainlets as well), and the biggest thing to talk through up front (assuming we're good with running everything through a single deployment) is configuration. We currently assume a single GitHub App, and we use these envvar keys to configure it:

eng-pipes/.env.example

Lines 5 to 12 in af1f4ca

# GitHub App ID
GH_APP_IDENTIFIER=""
# Github App Webhook Secret to verify requests come from GitHub
GH_WEBHOOK_SECRET=""
# GitHub App Secret Key
# NOTE: this *must* be on a single line, otherwise it will break
# reading the secret key.
GH_APP_SECRET_KEY='-----BEGIN RSA PRIVATE KEY----------END RSA PRIVATE KEY-----'

Supporting an arbitrary number of GitHub Apps (one per org) is a little futzy using envvars, but I think something like this might work?

# Keep this global for all orgs/apps. Easier to rotate.
GH_WEBHOOK_SECRET=""

# App for getsentry
GH_APP_1_NAME="getsentry"
GH_APP_1_IDENTIFIER="deadbeef"
GH_APP_1_SECRET_KEY='-----BEGIN RSA PRIVATE KEY-----feedbeef-----END RSA PRIVATE KEY-----'

# App for getsentry
GH_APP_2_NAME="codecov"
GH_APP_2_IDENTIFIER="ba5eba11"
GH_APP_2_SECRET_KEY='-----BEGIN RSA PRIVATE KEY-----b01dface-----END RSA PRIVATE KEY-----'

I would parse this out at startup-time (somewhere in/under buildServer.ts), but only fail at runtime (as we do today) when there is no app configured for the requested org.

Update

I ended up going with a github-orgs.yml for configuration, because a) I need to scope the repo allow-lists to orgs and those are too cumbersome for environment variables, and b) we want to move towards a YAML config file anyway to bring in some config from security-as-code.

PRs

@chadwhitacre
Copy link
Member Author

Went around the horn in Slack about whether to have multiple apps or a single app that we would keep unlisted and filter out any unwanted org traffic from (if anyone were to bother to get it installed outside of our orgs). We decided to proceed with two apps for now to avoid having to come up with a brand that works for the general case vs. getsantry and CoveCod.

@chadwhitacre
Copy link
Member Author

Below is an audit of getClient in 94396e5 (current HEAD of main). I guess the main take-away is that we seem to sometimes pass a dynamic value for the second arg, and sometimes we use OWNER from config. I think we probably want to always pass a dynamic value, and we probably want to be able to turn off certain brainlets (we don't want all of the GoCD integrations in codecov).

export const OWNER = process.env.OWNER || 'getsentry';

def
---
src/api/github/getClient.ts:37:                                   export async function getClient(type: ClientType, org: string | null) {
src/api/github/getClient.ts:57:                                   'Must pass org to `getClient` if getting an app scoped client.'

use
---
src/utils/getOssUserType.ts:32:                                   const octokit = await getClient(ClientType.User, org);

src/brain/ghaCancel/index.ts:27:                                  const octokit = await getClient(ClientType.App, owner);
src/brain/issueLabelHandler/followups.ts:143:                     const octokit = await getClient(ClientType.App, owner);
src/brain/issueLabelHandler/followups.ts:82:                      const octokit = await getClient(ClientType.App, owner);
src/brain/issueLabelHandler/route.ts:141:                         const octokit = await getClient(ClientType.App, owner);
src/brain/issueLabelHandler/route.ts:86:                          const octokit = await getClient(ClientType.App, owner);
src/brain/issueLabelHandler/triage.ts:111:                        const octokit = await getClient(ClientType.App, owner);
src/brain/issueLabelHandler/triage.ts:61:                         const octokit = await getClient(ClientType.App, owner);
src/brain/projectsHandler/project.ts:65:                          const octokit = await getClient(ClientType.App, owner);

src/api/github/getSentryPullRequestsForGetsentryRange.ts:40:      const octokit = await getClient(ClientType.App, OWNER);
src/brain/gocdSlackFeeds/deployFeed.ts:76:                        const octokit = await getClient(ClientType.App, OWNER);
src/brain/notifyOnGoCDStageEvent/index.ts:276:                    const octokit = await getClient(ClientType.App, OWNER);
src/brain/pleaseDeployNotifier/actionViewUndeployedCommits.ts:71: const octokit = await getClient(ClientType.App, OWNER);
src/brain/requiredChecks/getAnnotations.ts:85:                    const octokit = await getClient(ClientType.App, OWNER);
src/brain/typescript/getProgress.ts:21:                           const octokit = await getClient(ClientType.App, OWNER);
src/utils/db/getFailureMessages.ts:43:                            const octokit = await getClient(ClientType.App, OWNER);
src/webhooks/pubsub/index.ts:53:                                  const octokit = await getClient(ClientType.App, OWNER);

src/api/github/getChangedStack.ts:22:                             const octokit = client || (await getClient(ClientType.App, OWNER));
src/api/github/getRelevantCommit.ts:18:                           const octokit = client || (await getClient(ClientType.App, OWNER));


test def
--------
test/jest.setup.ts:3:                                             jest.mock('@api/github/getClient');
src/api/github/__mocks__/getClient.ts:163:                        export async function getClient(type: ClientType, org?: string) {
src/api/github/__mocks__/getClient.ts:172:                        throw Error('Org required for mock getClient()');

test use
--------
src/utils/getOssUserType.test.ts:16:                              octokit = await getClient(ClientType.User);

src/brain/ghaCancel/index.test.ts:23:                             octokit = await getClient(ClientType.App, 'getsentry');
src/brain/githubMetrics/index.test.ts:64:                         octokit = await getClient(ClientType.App, 'getsentry');
src/brain/notifyOnGoCDStageEvent/index.test.ts:101:               octokit = await getClient(ClientType.App, 'getsentry');
src/brain/pleaseDeployNotifier/index.test.ts:40:                  octokit = await getClient(ClientType.App, 'getsentry');
src/brain/requiredChecks/getAnnotations.test.ts:10:               octokit = await getClient(ClientType.App, 'getsentry');
src/brain/requiredChecks/index.test.ts:69:                        octokit = await getClient(ClientType.App, 'getsentry');
src/utils/db/getFailureMessages.test.ts:16:                       octokit = await getClient(ClientType.App, 'getsentry');
src/api/github/getSentryPullRequestsForGetsentryRange.test.ts:15: getsentry = await getClient(ClientType.App, 'getsentry');

src/brain/issueLabelHandler/index.test.ts:77:                     octokit = await getClient(ClientType.App, 'Enterprise');
src/webhooks/pubsub/stalebot.test.ts:18:                          ...(await getClient(ClientType.App, 'Enterprise')),

src/brain/projectsHandler/index.test.ts:44:                       octokit = await getClient(ClientType.App, 'test-org');

src/brain/gocdSlackFeeds/deployFeed.test.ts:519:                  const octokit = await getClient(ClientType.App, OWNER);
src/brain/gocdSlackFeeds/deployFeed.test.ts:650:                  const octokit = await getClient(ClientType.App, OWNER);

@chadwhitacre
Copy link
Member Author

Thinking next about OWNER, but that leads right into SENTRY_REPO and GETSENTRY_REPO.

def
---
src/config/index.ts:12:                                           export const SENTRY_REPO = process.env.SENTRY_REPO || 'sentry';
src/config/index.ts:13:                                           export const GETSENTRY_REPO = process.env.GETSENTRY_REPO || 'getsentry';


use
---
src/api/github/getRelevantCommit.ts:22:                           repo: GETSENTRY_REPO,
src/api/github/getRelevantCommit.ts:44:                           repo: SENTRY_REPO,
src/api/github/getSentryPullRequestsForGetsentryRange.ts:103:     repo: GETSENTRY_REPO,
src/api/github/getSentryPullRequestsForGetsentryRange.ts:46:      repo: GETSENTRY_REPO,
src/api/github/getSentryPullRequestsForGetsentryRange.ts:63:      repo: isBumpCommit ? SENTRY_REPO : GETSENTRY_REPO,
src/api/github/getSentryPullRequestsForGetsentryRange.ts:72:      repo: GETSENTRY_REPO,
src/api/github/getSentryPullRequestsForGetsentryRange.ts:94:      repo: SENTRY_REPO,
src/api/github/isGetsentryRequiredCheck/index.ts:15:              if (payload.repository?.full_name !== `${OWNER}/${GETSENTRY_REPO}`) {
src/brain/gocdSlackFeeds/deployFeed.ts:135:                       if (repo !== GETSENTRY_REPO) {
src/brain/gocdSlackFeeds/deployFeed.ts:152:                       SENTRY_REPO,
src/brain/notifyOnGoCDStageEvent/index.ts:18:                     GETSENTRY_REPO,
src/brain/notifyOnGoCDStageEvent/index.ts:190:                    relevantCommit.sha === sha ? GETSENTRY_REPO : SENTRY_REPO;
src/brain/notifyOnGoCDStageEvent/index.ts:216:                    repo: GETSENTRY_REPO,
src/brain/notifyOnGoCDStageEvent/index.ts:224:                    repo: GETSENTRY_REPO,
src/brain/notifyOnGoCDStageEvent/index.ts:22:                     SENTRY_REPO,
src/brain/notifyOnGoCDStageEvent/index.ts:236:                    if (url.indexOf(`${OWNER}/${GETSENTRY_REPO}`) != -1) {
src/brain/pleaseDeployNotifier/actionViewUndeployedCommits.ts:5:  GETSENTRY_REPO,
src/brain/pleaseDeployNotifier/actionViewUndeployedCommits.ts:82: repo: GETSENTRY_REPO,
src/brain/pleaseDeployNotifier/index.ts:133:                      const commitLink = `https://github.com/${OWNER}/${GETSENTRY_REPO}/commits/${commit}`;
src/brain/pleaseDeployNotifier/index.ts:139:                      relevantCommit.sha === checkRun.head_sha ? GETSENTRY_REPO : SENTRY_REPO;
src/brain/pleaseDeployNotifier/index.ts:13:                       GETSENTRY_REPO,
src/brain/pleaseDeployNotifier/index.ts:17:                       SENTRY_REPO,
src/brain/requiredChecks/getAnnotations.ts:96:                    repo: GETSENTRY_REPO,
src/brain/requiredChecks/getTextParts.ts:10:                      const commitLink = `https://github.com/${OWNER}/${GETSENTRY_REPO}/commits/${checkRun.head_sha}`;
src/brain/requiredChecks/getTextParts.ts:15:                      `${GETSENTRY_REPO}@master`,
src/brain/typescript/getProgress.ts:11:                           repo = SENTRY_REPO,
src/brain/typescript/index.ts:40:                                 repo: GETSENTRY_REPO,
src/brain/typescript/index.ts:45:                                 repo: GETSENTRY_REPO,
src/utils/db/getFailureMessages.ts:52:                            repo: GETSENTRY_REPO,
src/webhooks/pubsub/index.ts:12:                                  const DEFAULT_REPOS = [SENTRY_REPO];


test def
--------
test/jest.setup.ts:13:                                            GETSENTRY_REPO: 'getsentry',
test/jest.setup.ts:14:                                            SENTRY_REPO: 'sentry',

@chadwhitacre
Copy link
Member Author

I guess what we need is to adopt a strategy for ignoring codepaths that aren't relevant in codecov. Is it possible that we can avoid those by not subscribing CoveCod to certain GitHub events? Or are there events that we subscribe to for both CI/CD and engagement tracking purposes? I guess that would be the next thing to audit.

@chadwhitacre
Copy link
Member Author

chadwhitacre commented Jun 30, 2023

Looking good! 👍

General
=======
src/api/github/index.ts:16:                       githubEvents.onError(defaultErrorHandler);
src/brain/githubMetrics/index.ts:25:              githubEvents.onAny(ossHandler);

Engagement Tracking
===================
src/brain/issueLabelHandler/index.ts:14:          githubEvents.on('issues.opened', markUntriaged);
src/brain/issueLabelHandler/index.ts:18:          githubEvents.on('issues.opened', markUnrouted);
src/brain/issueLabelHandler/index.ts:16:          githubEvents.on('issues.labeled', markTriaged);
src/brain/issueLabelHandler/index.ts:20:          githubEvents.on('issues.labeled', markRouted);
src/brain/issueLabelHandler/index.ts:27:          githubEvents.on('issues.labeled', ensureOneWaitingForLabel);
src/brain/issueNotifier/index.ts:248:             githubEvents.on('issues.labeled', wrapHandler('issueNotifier', githubLabelHandler));
src/brain/issueLabelHandler/index.ts:25:          githubEvents.on('issue_comment.created', updateCommunityFollowups);
src/brain/projectsHandler/index.ts:10:            githubEvents.on('projects_v2_item.edited', syncLabelsWithProjectField);

test
----
src/brain/issueLabelHandler/index.test.ts:37:     githubEvents.onError(errors);
src/brain/issueLabelHandler/index.test.ts:69:     githubEvents.onError(defaultErrorHandler);
src/brain/projectsHandler/index.test.ts:26:       githubEvents.onError(errors);
src/brain/projectsHandler/index.test.ts:36:       githubEvents.onError(defaultErrorHandler);

CI/CD
=====
src/brain/githubMetrics/index.ts:18:              githubEvents.on('check_run', sentryHandler);
src/brain/pleaseDeployNotifier/index.ts:209:      githubEvents.on('check_run', handler);
src/brain/requiredChecks/index.ts:82:             githubEvents.on('check_run', handler);

@chadwhitacre
Copy link
Member Author

I guess as long as we don't subscribe CoveCod to check_run we should be fine. 👍

@chadwhitacre
Copy link
Member Author

And honestly it's really only the getClient calls downstream of the event handlers we care about that need to be made to work with dynamic owner vs. static global OWNER. That said, it'll probably be more hygienic to standardize on dynamic across the codebase.

@chadwhitacre
Copy link
Member Author

I guess the risk is that we receive an event from the codecov org and try to take an action in the getsentry (hard-coded OWNER) org. It's possible we could end up with some garbage that way.

@chadwhitacre
Copy link
Member Author

OWNER in 9bf0d35 (#505):

def
---
src/config/index.ts:11:                                             export const OWNER = process.env.OWNER || 'getsentry';
src/config/index.ts:179:                                             * getClient calls to use a dynamic owner/org instead of OWNER as defined above.

use
---
src/api/github/getChangedStack.ts:17:                               const octokit = await getClient(ClientType.App, OWNER);
src/api/github/getChangedStack.ts:20:                               owner: OWNER,
src/api/github/getChangedStack.ts:40:                               Commit: `https://github.com/${OWNER}/${repo}/commit/${ref}`,

src/api/github/getRelevantCommit.ts:17:                             const octokit = await getClient(ClientType.App, OWNER);
src/api/github/getRelevantCommit.ts:21:                             owner: OWNER,
src/api/github/getRelevantCommit.ts:43:                             owner: OWNER,

src/api/github/isGetsentryRequiredCheck/index.ts:15:                if (payload.repository?.full_name !== `${OWNER}/${GETSENTRY_REPO}`) {

src/brain/gocdSlackFeeds/deployFeed.ts:76:                          const octokit = await getClient(ClientType.App, OWNER);

src/brain/notifyOnGoCDStageEvent/index.ts:215:                      owner: OWNER,
src/brain/notifyOnGoCDStageEvent/index.ts:21:                       OWNER,
src/brain/notifyOnGoCDStageEvent/index.ts:223:                      owner: OWNER,
src/brain/notifyOnGoCDStageEvent/index.ts:236:                      if (url.indexOf(`${OWNER}/${GETSENTRY_REPO}`) != -1) {
src/brain/notifyOnGoCDStageEvent/index.ts:276:                      const octokit = await getClient(ClientType.App, OWNER);

src/brain/pleaseDeployNotifier/actionViewUndeployedCommits.ts:71:   const octokit = await getClient(ClientType.App, OWNER);
src/brain/pleaseDeployNotifier/actionViewUndeployedCommits.ts:81:   owner: OWNER,
src/brain/pleaseDeployNotifier/actionViewUndeployedCommits.ts:8:    OWNER,
src/brain/pleaseDeployNotifier/index.ts:133:                        const commitLink = `https://github.com/${OWNER}/${GETSENTRY_REPO}/commits/${commit}`;
src/brain/pleaseDeployNotifier/index.ts:16:                         OWNER,

src/brain/requiredChecks/getAnnotations.ts:85:                      const octokit = await getClient(ClientType.App, OWNER);
src/brain/requiredChecks/getAnnotations.ts:95:                      owner: OWNER,
src/brain/requiredChecks/getTextParts.ts:10:                        const commitLink = `https://github.com/${OWNER}/${GETSENTRY_REPO}/commits/${checkRun.head_sha}`;

src/brain/typescript/getProgress.ts:21:                             const octokit = await getClient(ClientType.App, OWNER);
src/brain/typescript/getProgress.ts:29:                             owner: OWNER,
src/brain/typescript/getProgress.ts:36:                             owner: OWNER,
src/brain/typescript/getProgress.ts:60:                             owner: OWNER,

src/utils/db/getFailureMessages.ts:43:                              const octokit = await getClient(ClientType.App, OWNER);
src/utils/db/getFailureMessages.ts:51:                              owner: OWNER,

src/webhooks/pubsub/index.ts:53:                                    const octokit = await getClient(ClientType.App, OWNER);
src/webhooks/pubsub/slackNotifications.ts:146:                      owner: OWNER,
src/webhooks/pubsub/slackNotifications.ts:427:                      owner: OWNER,
src/webhooks/pubsub/slackNotifications.ts:8:                        OWNER,
src/webhooks/pubsub/stalebot.ts:26:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:33:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:44:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:50:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:79:                                 owner: OWNER,


test def
--------
test/jest.setup.ts:12:                                              OWNER: 'getsentry',

test use
--------
test/payloads/github/issue_comment.ts:62:                           author_association: 'OWNER',
test/payloads/github/pull_request.ts:408:                           author_association: 'OWNER',
test/payloads/github/issues.ts:62:                                  author_association: 'OWNER',
src/brain/gocdSlackFeeds/deployFeed.test.ts:519:                    const octokit = await getClient(ClientType.App, OWNER);
src/brain/gocdSlackFeeds/deployFeed.test.ts:650:                    const octokit = await getClient(ClientType.App, OWNER);

@chadwhitacre
Copy link
Member Author

Need to tackle these ones:

src/webhooks/pubsub/index.ts:53:                                    const octokit = await getClient(ClientType.App, OWNER);
src/webhooks/pubsub/slackNotifications.ts:146:                      owner: OWNER,
src/webhooks/pubsub/slackNotifications.ts:427:                      owner: OWNER,
src/webhooks/pubsub/slackNotifications.ts:8:                        OWNER,
src/webhooks/pubsub/stalebot.ts:26:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:33:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:44:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:50:                                 owner: OWNER,
src/webhooks/pubsub/stalebot.ts:79:                                 owner: OWNER,

@chadwhitacre
Copy link
Member Author

Yeah okay upgrading pubsub is going to be the main piece of work before we can start testing out sending CoveCod events to eng-pipes.

@chadwhitacre
Copy link
Member Author

And it won't impact Codecov to install CoveCod without updating pubsub, that should just continue to poke getsentry org without impacting codecov. I think that means I'm ready to install CoveCod on codecov and test it out!

@chadwhitacre
Copy link
Member Author

I put up a slew of incremental PRs.

I need to understand pubsub better, here's the jobs in GCP. Since repos are coming in the payload I guess we should look at sending org in the payload as well, that means we have to set up one pubsub in GCP for each org vs. wiring org knowledge into eng-pipes. Tradeoffs. Wiring into org I guess would block on multi-org config changes.

@chadwhitacre
Copy link
Member Author

Where is the payload with repos? 🤔

Screenshot 2023-07-10 at 10 42 44 AM

@chadwhitacre
Copy link
Member Author

Looking into eng-pipes-cron topic ...

Screenshot 2023-07-10 at 10 44 01 AM

@chadwhitacre
Copy link
Member Author

P.S. It shouldn't matter that we have logic for Status labels in eng-pipes, since those labels won't exist in codecov/feedback and we won't be sending any events with those.

We should set up a GTM team in the codecov org.

if (status === 204) {
// https://docs.github.com/en/rest/teams/members?apiVersion=2022-11-28#get-team-membership-for-a-user
// "will include the members of child teams"
check = 'Team';
status = await getResponseStatus(octokit.request, [
'GET /orgs/{org}/teams/GTM/memberships/{username}',
{ org, username },
]);
if (status === 200) {
// I'd rather express this inversely, so that the failure case is
// slightly safer, but our GitHub teams are not clean enough for that.
type = 'gtm';
} else if (status === 404) {
type = 'internal'; // ~= EPD
}
} else if (status === 404) {
type = 'external';
}

@chadwhitacre
Copy link
Member Author

chadwhitacre commented Jul 10, 2023

Any additional bots we want to exclude?

const KNOWN_BOTS = [
// https://www.notion.so/sentry/Bot-Accounts-beea0fc35473453ab50e05e6e4d1d02d
'getsentry-bot',
'getsentry-release',
'sentry-test-fixture-nonmember',
'codecov-commenter',
];

@chadwhitacre
Copy link
Member Author

Alright I still don't know how pubsub works. Where do we define the payload?

@chadwhitacre
Copy link
Member Author

Also how are Slack notifications going to work? What else do we need to configure for that?

@chadwhitacre
Copy link
Member Author

chadwhitacre commented Jul 10, 2023

@hubertdeng123
Copy link
Member

Since repos are coming in the payload I guess we should look at sending org in the payload as well, that means we have to set up one pubsub in GCP for each org

Agreed here.

@chadwhitacre
Copy link
Member Author

I think I found it! Pretty sure this is where we define prod secrets:

https://github.com/getsentry/eng-pipes/settings/environments/164955041/edit

@chadwhitacre
Copy link
Member Author

Where are "Waiting for: Support" notifications going?

There shouldn't be any coming from the bot since the feedback repo won't have routing. If someone manually adds the label it'll show up in the #discuss-support-open-source channel with a somewhat confusing message:

bolt.client.chat.postMessage({
text: `⏲ Issue ready to route: <${issue.html_url}|#${issue.number} ${issue.title}>`,
channel: SUPPORT_CHANNEL_ID,
unfurl_links: false,
unfurl_media: false,
});

This isn't the end of the world since it requires manually sending to support. I'm pretty sure Support and Product Owner notifications should get folded together in Q3 under getsentry/team-ospo#157.

Teach notify-for-triage about org? special office for them? or use sfo/yyz? Try to use sfo/yyz.

We're in the same boat here as with SDK repos where we don't provide Slack notifications currently. Let's solve this under getsentry/team-ospo#157 as well.

@chadwhitacre
Copy link
Member Author

If I'm reading this right we essentially skip notifications for repos without routing, which is what codecov/feedback is.

const issuesToNotifyAbout = (
await Promise.all([...org.repos.withRouting].map(getIssueSLOInfoForRepo))
).flat();

I think we're fine.

@chadwhitacre
Copy link
Member Author

If I'm wrong I expect an error to show up in Sentry. I'm going to set SENTRY_DSN locally and see if anything shows up.

@chadwhitacre
Copy link
Member Author

I see this in the console:

    error: select "offices" from "label_to_channel" where "label_name" = $1 - relation "label_to_channel" does not exist

but nothing in Sentry.

@chadwhitacre
Copy link
Member Author

Hrm, possible this is broken in prod, too. 🤔

$ yarn migrate migrate:latest                                                                                      
Requiring external module ts-node/register
Working directory changed to ~/workbench/getsentry/eng-pipes/src
ENOENT: no such file or directory, open 'github-orgs.local.yml'
Error: ENOENT: no such file or directory, open 'github-orgs.local.yml'
    at Object.openSync (fs.js:476:3)
    at NodeFS.openSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:16719:24)
    at makeCallSync.subPath.subPath (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:19405:26)
    at ZipOpenFS.makeCallSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:20161:26)
    at ZipOpenFS.openSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:19404:17)
    at VirtualFS.openSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:17157:24)
    at PosixFS.openSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:17157:24)
    at URLFS.openSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:17157:24)
    at Object.readFileSync (fs.js:377:35)
    at NodeFS.readFileSync (/Users/chadwhitacre/workbench/getsentry/eng-pipes/.pnp.cjs:17065:24)
$ ag 'Working directory changed'
$ 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants