Graphcool / graphcool-framework

Apache License 2.0
1.78k stars 130 forks source link

None.get issue #388

Open marktani opened 6 years ago

marktani commented 6 years ago

Issue by vincenzo Thursday Nov 09, 2017 at 18:08 GMT Originally opened as https://github.com/graphcool/prisma/issues/1231


Background

I used to have a functional version of my service, which code I had checked into my local repo. This service had Role as a type, with an N:M relationship with the User type. A permission query exploiting this relationship was also in place.

Once I had all that working, I wanted to try to turn Role into an enum, after reading some docs. After removing all references to the old Role type, I managed to deploy the new version successfully (local). However, I had missed that currently there is a limitation that affects my use case, so I resolved to revert back to my original functional service, which used to deploy just fine.

The issue

It's at this point that the bug appeared. Deploying (even with --dry-run) that same version of the service gives now this error:

There are issues with the new service definition:

  Global
    ✖ None.get

Debug output

$ DEBUG="*" gc deploy -t local --force
  config CWD /vagrant/data/IELTSRO +0ms
  config HOME /home/vagrant +2ms
  config definitionDir /vagrant/data/IELTSRO +2ms
  config definitionPath /vagrant/data/IELTSRO/graphcool.yml +0ms
  config homepath /home/vagrant/.graphcoolrc +0ms
  config localRCPath /vagrant/data/IELTSRO/.graphcoolrc +0ms
  config globalRCPath /home/vagrant/.graphcoolrc +0ms
  cli command id deploy +0ms
  cli:plugincache Got plugin from cache +0ms
  cli:plugincache /home/vagrant/.cache/graphcool/plugins.json +0ms
  cli:plugincache Got plugin from cache +1ms
  cli:plugincache /home/vagrant/.cache/graphcool/plugins.json +0ms
  plugins findCommand graphcool-cli-core +0ms
  plugin requiring command +0ms
  cli-engine:plugins:manager requiring /home/vagrant/.nvm/versions/node/v8.2.0/lib/node_modules/graphcool/node_modules/graphcool-cli-core +0ms
  cli-engine:plugins:manager required +270ms
  plugin required command +272ms
  deploy run +0ms
  client choosing clusterEndpoint http://localhost:60000/system +0ms
  client Sending query +1ms
  client 
  client       query ($projectId: ID!){
  client         viewer {
  client           project(id: $projectId) {
  client             ...RemoteProject
  client           }
  client         }
  client       }
  client       
  client   fragment RemoteProject on Project {
  client     id
  client     name
  client     schema
  client     alias
  client     region
  client     isEjected
  client     projectDefinitionWithFileContent
  client   }
  client 
  client        +1ms
  client { projectId: 'cj9r952d8000j014991vnmbew' } +0ms
  deploy bundling +123ms
  bundler /vagrant/data/IELTSRO/.build/build.zip +0ms
Bundling functions...  bundler added files [ '.envrc',
  '.git/',
  '.graphcoolrc',
  'graphcool.yml',
  'node_modules/',
  'package-lock.json',
  'README.md',
  'package.json',
  'src/',
  'types.graphql',
  '.build/build.zip',
  '.build/dist/',
  '.git/HEAD',
  '.git/FETCH_HEAD',
  '.git/COMMIT_EDITMSG',
  '.git/config',
  '.git/ORIG_HEAD',
  '.git/branches/',
  '.git/description',
  '.git/index',
  '.git/hooks/',
  '.git/info/',
  '.git/logs/',
  '.git/objects/',
  '.git/refs/',
  'node_modules/.bin/',
  'node_modules/@types/',
  'node_modules/apollo-fetch/',
  'node_modules/apollo-link/',
  'node_modules/apollo-link-http/',
  'node_modules/bcryptjs/',
  'node_modules/cross-fetch/',
  'node_modules/apollo-utilities/',
  'node_modules/deprecated-decorator/',
  'node_modules/encoding/',
  'node_modules/graphcool-lib/',
  'node_modules/graphql/',
  'node_modules/graphql-request/',
  'node_modules/graphql-tools/',
  'node_modules/is-stream/',
  'node_modules/iconv-lite/',
  'node_modules/isomorphic-fetch/',
  'node_modules/iterall/',
  'node_modules/node-fetch/',
  'node_modules/package-lock.json',
  'node_modules/source-map/',
  'node_modules/source-map-support/',
  'node_modules/uuid/',
  'node_modules/validator/',
  'node_modules/whatwg-fetch/',
  'node_modules/zen-observable-ts/',
  'src/email-password/',
  'src/permissions/',
  '.git/info/exclude',
  '.git/hooks/commit-msg.sample',
  '.git/hooks/pre-applypatch.sample',
  '.git/hooks/applypatch-msg.sample',
  '.git/hooks/post-update.sample',
  '.git/hooks/pre-commit.sample',
  '.git/hooks/pre-push.sample',
  '.git/hooks/pre-rebase.sample',
  '.git/hooks/update.sample',
  '.git/hooks/prepare-commit-msg.sample',
  '.git/logs/HEAD',
  '.git/logs/refs/',
  '.git/refs/heads/',
  '.git/refs/remotes/',
  '.git/refs/tags/',
  '.git/objects/00/',
  '.git/objects/01/',
  '.git/objects/02/',
  '.git/objects/03/',
  '.git/objects/04/',
  '.git/objects/05/',
  '.git/objects/07/',
  '.git/objects/06/',
  '.git/objects/08/',
  '.git/objects/09/',
  '.git/objects/0b/',
  '.git/objects/0c/',
  '.git/objects/0e/',
  '.git/objects/0a/',
  '.git/objects/0f/',
  '.git/objects/0d/',
  '.git/objects/11/',
  '.git/objects/12/',
  '.git/objects/10/',
  '.git/objects/13/',
  '.git/objects/14/',
  '.git/objects/16/',
  '.git/objects/15/',
  '.git/objects/17/',
  '.git/objects/19/',
  '.git/objects/1c/',
  '.git/objects/1d/',
  '.git/objects/1b/',
  '.git/objects/1e/',
  '.git/objects/1a/',
  '.git/objects/1f/',
  '.git/objects/23/',
  ... 1932 more items ] +2s
  ts-builder starting compile [ '/vagrant/data/IELTSRO/src/email-password/signup.ts',
  '/vagrant/data/IELTSRO/src/email-password/authenticate.ts',
  '/vagrant/data/IELTSRO/src/email-password/loggedInUser.ts' ] +3ms
  ts-builder created program +396ms
  ts-builder emitted +382ms
  bundler converted files [ '/vagrant/data/IELTSRO/src/email-password/signup.ts',
  '/vagrant/data/IELTSRO/src/email-password/authenticate.ts',
  '/vagrant/data/IELTSRO/src/email-password/loggedInUser.ts' ] +1ms
  bundler createdFiles [ '/vagrant/data/IELTSRO/.build/dist/src/email-password/signup.js',
  '/vagrant/data/IELTSRO/.build/dist/src/email-password/authenticate.js',
  '/vagrant/data/IELTSRO/.build/dist/src/email-password/loggedInUser.js' ] +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/ src/ +68ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/ src/email-password/ +1ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/byline.js src/email-password/byline.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/authenticate-dev.js src/email-password/authenticate-dev.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/authenticate.js src/email-password/authenticate.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/authenticate-lambda.js src/email-password/authenticate-lambda.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/loggedInUser-dev.js src/email-password/loggedInUser-dev.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/loggedInUser.js src/email-password/loggedInUser.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/loggedInUser-lambda.js src/email-password/loggedInUser-lambda.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/signup-lambda.js src/email-password/signup-lambda.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/signup-dev.js src/email-password/signup-dev.js +0ms
  bundler adding /vagrant/data/IELTSRO/.build/dist/src/email-password/signup.js src/email-password/signup.js +0ms
  bundler added build files [ 'src/',
  'src/email-password/',
  'src/email-password/byline.js',
  'src/email-password/authenticate-dev.js',
  'src/email-password/authenticate.js',
  'src/email-password/authenticate-lambda.js',
  'src/email-password/loggedInUser-dev.js',
  'src/email-password/loggedInUser.js',
  'src/email-password/loggedInUser-lambda.js',
  'src/email-password/signup-lambda.js',
  'src/email-password/signup-dev.js',
  'src/email-password/signup.js' ] +0ms
  client choosing clusterEndpoint http://localhost:60000/system +7s
  client Sending query +0ms
  client 
  client       mutation getUrl($projectId: String!) {
  client         getTemporaryDeployUrl(
  client           input: {
  client           projectId: $projectId
  client         }
  client       ) {
  client           url
  client         }
  client       }
  client      +0ms
  client { projectId: 'cj9r952d8000j014991vnmbew' } +1ms
  bundler uploading to http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m +4s
  bundler {
  bundler   "success" : true
  bundler } +554ms
  bundler bundled 7807 +0ms
 7.8s
  deploy bundled +2ms
Deploying to local with target local locally...  client 
  client 
  client Sending service definition: +671ms
  client {
  client   "modules": [
  client     {
  client       "name": "",
  client       "content": "types: ./types.graphql\nfunctions:\n  signup:\n    type: resolver\n    schema: src/email-password/signup.graphql\n    handler:\n      code: src/email-password/signup.ts\n  authenticate:\n    type: resolver\n    schema: src/email-password/authenticate.graphql\n    handler:\n      code: src/email-password/authenticate.ts\n  loggedInUser:\n    type: resolver\n    schema: src/email-password/loggedInUser.graphql\n    handler:\n      code: src/email-password/loggedInUser.ts\npermissions:\n  - operation: File.read\n  - operation: File.create\n  - operation: File.update\n  - operation: File.delete\n  - operation: Ielts.create\n    authenticated: true\n    query: './src/permissions/Ielts.graphql:create'\n  - operation: Ielts.update\n  - operation: Ielts.delete\n  - operation: Ielts.read\n  - operation: Role.read\n  - operation: Role.create\n  - operation: Role.update\n  - operation: Role.delete\n  - operation: User.read\n  - operation: User.create\n  - operation: User.update\n  - operation: User.delete\n  - operation: UserOnRole.*\nrootTokens: []\n",
  client       "files": {
  client         "./types.graphql": "type File @model {\n  contentType: String!\n  createdAt: DateTime!\n  dsadsa: Float!\n  id: ID! @isUnique # read-only (managed by Graphcool)\n  name: String!\n  secret: String! @isUnique\n  size: Int!\n  updatedAt: DateTime!\n  url: String! @isUnique\n}\n\ntype Ielts @model {\n  city: String!\n  country: String!\n  id: ID! @isUnique # read-only (managed by Graphcool)\n  minAcademic: Float\n  minBandScore: Float!\n  minGeneral: Float\n  organisation: String!\n  state: String!\n  website: String!\n}\n\ntype Role @model {\n  id: ID! @isUnique # read-only (managed by Graphcool)\n  name: String! @isUnique\n  users: [User!]! @relation(name: \"UserOnRole\")\n}\n\ntype User @model {\n  createdAt: DateTime! # read-only (managed by Graphcool)\n  email: String @isUnique\n  id: ID! @isUnique # read-only (managed by Graphcool)\n  name: String! @isUnique\n  password: String\n  roles: [Role!]! @relation(name: \"UserOnRole\")\n  updatedAt: DateTime! # read-only (managed by Graphcool)\n}",
  client         "./src/permissions/Ielts.graphql": "query create {\n  SomeRoleExists(filter: {users_some: {id: $user_id}, name: \"Editor\"})\n}",
  client         "src/email-password/signup.graphql": "type SignupUserPayload {\n  id: ID!\n  token: String!\n}\n\nextend type Mutation {\n  signupUser(email: String!, password: String!, name: String!): SignupUserPayload\n}",
  client         "src/email-password/authenticate.graphql": "type AuthenticateUserPayload {\n  id: ID!\n  token: String!\n}\n\nextend type Mutation {\n  authenticateUser(email: String!, password: String!): AuthenticateUserPayload\n}\n",
  client         "src/email-password/loggedInUser.graphql": "type LoggedInUserPayload {\n  id: ID!\n}\n\nextend type Query {\n  # return user data if request contains valid authentication token\n  loggedInUser: LoggedInUserPayload\n}\n"
  client       },
  client       "externalFiles": {
  client         "src/email-password/signup.ts": {
  client           "url": "http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m",
  client           "lambdaHandler": "src/email-password/signup-lambda.handle",
  client           "devHandler": "src/email-password/signup-dev.js"
  client         },
  client         "src/email-password/authenticate.ts": {
  client           "url": "http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m",
  client           "lambdaHandler": "src/email-password/authenticate-lambda.handle",
  client           "devHandler": "src/email-password/authenticate-dev.js"
  client         },
  client         "src/email-password/loggedInUser.ts": {
  client           "url": "http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m",
  client           "lambdaHandler": "src/email-password/loggedInUser-lambda.handle",
  client           "devHandler": "src/email-password/loggedInUser-dev.js"
  client         }
  client       }
  client     }
  client   ]
  client } +14ms
  client choosing clusterEndpoint http://localhost:60000/system +4ms
  client Sending query +2ms
  client       mutation($projectId: String!, $force: Boolean, $isDryRun: Boolean!, $config: String!) {
  client         push(input: {
  client           projectId: $projectId
  client           force: $force
  client           isDryRun: $isDryRun
  client           config: $config
  client           version: 1
  client         }) {
  client           migrationMessages {
  client             type
  client             action
  client             name
  client             description
  client             subDescriptions {
  client               type
  client               action
  client               name
  client               description
  client             }
  client           }
  client           errors {
  client             description
  client             type
  client             field
  client           }
  client           project {
  client             id
  client             name
  client             alias
  client             projectDefinitionWithFileContent
  client           }
  client         }
  client       }
  client      +0ms
  client { projectId: 'cj9r952d8000j014991vnmbew',
  client   force: true,
  client   isDryRun: false,
  client   config: '{"modules":[{"name":"","content":"types: ./types.graphql\\nfunctions:\\n  signup:\\n    type: resolver\\n    schema: src/email-password/signup.graphql\\n    handler:\\n      code: src/email-password/signup.ts\\n  authenticate:\\n    type: resolver\\n    schema: src/email-password/authenticate.graphql\\n    handler:\\n      code: src/email-password/authenticate.ts\\n  loggedInUser:\\n    type: resolver\\n    schema: src/email-password/loggedInUser.graphql\\n    handler:\\n      code: src/email-password/loggedInUser.ts\\npermissions:\\n  - operation: File.read\\n  - operation: File.create\\n  - operation: File.update\\n  - operation: File.delete\\n  - operation: Ielts.create\\n    authenticated: true\\n    query: \'./src/permissions/Ielts.graphql:create\'\\n  - operation: Ielts.update\\n  - operation: Ielts.delete\\n  - operation: Ielts.read\\n  - operation: Role.read\\n  - operation: Role.create\\n  - operation: Role.update\\n  - operation: Role.delete\\n  - operation: User.read\\n  - operation: User.create\\n  - operation: User.update\\n  - operation: User.delete\\n  - operation: UserOnRole.*\\nrootTokens: []\\n","files":{"./types.graphql":"type File @model {\\n  contentType: String!\\n  createdAt: DateTime!\\n  dsadsa: Float!\\n  id: ID! @isUnique # read-only (managed by Graphcool)\\n  name: String!\\n  secret: String! @isUnique\\n  size: Int!\\n  updatedAt: DateTime!\\n  url: String! @isUnique\\n}\\n\\ntype Ielts @model {\\n  city: String!\\n  country: String!\\n  id: ID! @isUnique # read-only (managed by Graphcool)\\n  minAcademic: Float\\n  minBandScore: Float!\\n  minGeneral: Float\\n  organisation: String!\\n  state: String!\\n  website: String!\\n}\\n\\ntype Role @model {\\n  id: ID! @isUnique # read-only (managed by Graphcool)\\n  name: String! @isUnique\\n  users: [User!]! @relation(name: \\"UserOnRole\\")\\n}\\n\\ntype User @model {\\n  createdAt: DateTime! # read-only (managed by Graphcool)\\n  email: String @isUnique\\n  id: ID! @isUnique # read-only (managed by Graphcool)\\n  name: String! @isUnique\\n  password: String\\n  roles: [Role!]! @relation(name: \\"UserOnRole\\")\\n  updatedAt: DateTime! # read-only (managed by Graphcool)\\n}","./src/permissions/Ielts.graphql":"query create {\\n  SomeRoleExists(filter: {users_some: {id: $user_id}, name: \\"Editor\\"})\\n}","src/email-password/signup.graphql":"type SignupUserPayload {\\n  id: ID!\\n  token: String!\\n}\\n\\nextend type Mutation {\\n  signupUser(email: String!, password: String!, name: String!): SignupUserPayload\\n}","src/email-password/authenticate.graphql":"type AuthenticateUserPayload {\\n  id: ID!\\n  token: String!\\n}\\n\\nextend type Mutation {\\n  authenticateUser(email: String!, password: String!): AuthenticateUserPayload\\n}\\n","src/email-password/loggedInUser.graphql":"type LoggedInUserPayload {\\n  id: ID!\\n}\\n\\nextend type Query {\\n  # return user data if request contains valid authentication token\\n  loggedInUser: LoggedInUserPayload\\n}\\n"},"externalFiles":{"src/email-password/signup.ts":{"url":"http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m","lambdaHandler":"src/email-password/signup-lambda.handle","devHandler":"src/email-password/signup-dev.js"},"src/email-password/authenticate.ts":{"url":"http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m","lambdaHandler":"src/email-password/authenticate-lambda.handle","devHandler":"src/email-password/authenticate-dev.js"},"src/email-password/loggedInUser.ts":{"url":"http://localhost:60050/functions/files/cj9r952d8000j014991vnmbew/cj9ss1hkm000z0187uwhgd44m","lambdaHandler":"src/email-password/loggedInUser-lambda.handle","devHandler":"src/email-password/loggedInUser-dev.js"}}}]}' } +22ms
  client undefined +201ms
 247ms
There are issues with the new service definition:

  Global
    ✖ None.get

Types, before and after

Original working types.graphql:

type File @model {
  contentType: String!
  createdAt: DateTime!
  dsadsa: Float!
  id: ID! @isUnique # read-only (managed by Graphcool)
  name: String!
  secret: String! @isUnique
  size: Int!
  updatedAt: DateTime!
  url: String! @isUnique
}

type Role @model {
  id: ID! @isUnique # read-only (managed by Graphcool)
  name: String! @isUnique
  users: [User!]! @relation(name: "UserOnRole")
}

type User @model {
  createdAt: DateTime! # read-only (managed by Graphcool)
  email: String @isUnique
  id: ID! @isUnique # read-only (managed by Graphcool)
  name: String! @isUnique
  password: String
  roles: [Role!]! @relation(name: "UserOnRole")
  updatedAt: DateTime! # read-only (managed by Graphcool)
}

Types modified with Role as enum:

type File @model {
  contentType: String!
  createdAt: DateTime!
  dsadsa: Float!
  id: ID! @isUnique # read-only (managed by Graphcool)
  name: String!
  secret: String! @isUnique
  size: Int!
  updatedAt: DateTime!
  url: String! @isUnique
}

type Ielts @model {
  city: String!
  country: String!
  id: ID! @isUnique # read-only (managed by Graphcool)
  minAcademic: Float
  minBandScore: Float!
  minGeneral: Float
  organisation: String!
  state: String!
  website: String!
}

enum Role {
  EDITOR,
  CONTRIBUTOR
}

type User @model {
  createdAt: DateTime! # read-only (managed by Graphcool)
  email: String @isUnique
  id: ID! @isUnique # read-only (managed by Graphcool)
  name: String! @isUnique
  password: String
  roles: [Role!]
  updatedAt: DateTime! # read-only (managed by Graphcool)
}

Diff between the two

diff --git a/types.graphql b/types.graphql
index a0faa06..830cb7d 100644
--- a/types.graphql
+++ b/types.graphql
@@ -22,10 +22,9 @@ type Ielts @model {
   website: String!
 }

-type Role @model {
-  id: ID! @isUnique # read-only (managed by Graphcool)
-  name: String! @isUnique
-  users: [User!]! @relation(name: "UserOnRole")
+enum Role {
+  EDITOR,
+  CONTRIBUTOR
 }

 type User @model {
@@ -34,6 +33,6 @@ type User @model {
   id: ID! @isUnique # read-only (managed by Graphcool)
   name: String! @isUnique
   password: String
-  roles: [Role!]! @relation(name: "UserOnRole")
+  roles: [Role!]
   updatedAt: DateTime! # read-only (managed by Graphcool)
 }
\ No newline at end of file
marktani commented 6 years ago

Comment by marktani Thursday Nov 09, 2017 at 19:12 GMT


When I do these steps (locally):

I get this error message:

There are issues with the new service definition:

Global ✖ No field with id 'cj9sudcag05hu0109g78ixtoy'

But not the error you are reporting. Anyway, that's a reproducible problem 🙂

marktani commented 6 years ago

Comment by vincenzo Thursday Nov 09, 2017 at 23:32 GMT


@marktani

I got that too, initially. Let me explain further.

First, the PR describes a bug that occurs after this sequence:

In your case, you stopped at the second step, and your deployment was never successful. This is because when you pass from the initial to the later types, dangling references for the type Role are left scattered around; at the very least you should have the following left in your graphcool.yml:

- operation: Role.create
- operation: Role.update
- operation: Role.delete
- operation: UserOnRole.*

In my original case I also had a permission query still referencing the type Role. Either way, when you get rid of the dangling references, your force-deploy as per the second step of my sequence above will succeed.

Once you have that, then you must restore the original types, and try to deploy them again. It was then that I got the issue I describe in this PR, and to work around it I had to destroy the docker containers and redeploy, which worked.

marktani commented 6 years ago

Comment by marktani Friday Nov 10, 2017 at 08:38 GMT


dangling references for the type Role are left scattered around; at the very least you should have the following left in your graphcool.yml

No, my graphcool.yml looks like this:

permissions:
  - operation: "*"

So, there are no dangling references to Role as far as I can see.

marktani commented 6 years ago

Comment by vincenzo Friday Nov 10, 2017 at 08:41 GMT


@marktani LOL, ok, so that makes it even more interesting, because when I got the error you got, I solved it by removing dangling references. It was @kbrandwijk that suggested to me to look into that (starting from the permission query). :D Anyway, it should be possible to make the latter types deploy correctly after the former were deployed already. Until you get to that point, you won't be able to then go to third step of restoring the former types. :)

marktani commented 6 years ago

Comment by Timopheym Wednesday Dec 27, 2017 at 15:33 GMT


@vincenzo @marktani Sorry, i've got the same error, how can i make it work!?((

marktani commented 6 years ago

Comment by Timopheym Wednesday Dec 27, 2017 at 15:41 GMT


I was in need to remove @rename derectives after changing schema

henryson commented 6 years ago

I got the same error when changing a property from type String to a custom type with a relation. Before: education: String After: education: Education @relation(...) Then I stepped back and first deleted education and deployed, then add the same property with the new type, then it was successful. So it seems like the issue is changing the type in one deploy.

phonghho commented 6 years ago

I'm receiving this error as well. Changing anything in my models and then deploying results in this error. I must first remove the model, deploy, then add the model back in with the changes and deploy again.

Update: I tried not making any changes and deploying the same exact definition and I get the same error. Not sure if I'm not just understanding how to deploy changes are add any migration directives.