diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml new file mode 100755 index 000000000000..09eb82bdaf3d --- /dev/null +++ b/.github/workflows/test-deploy.yml @@ -0,0 +1,93 @@ +name: test-deploy + +on: + push: + branches: + [project-hooks] +jobs: + secrets-gate-run: + runs-on: ubuntu-latest + outputs: + ok: ${{ steps.check-secrets-run.outputs.ok }} + steps: + - name: check for secrets needed to run workflows + id: check-secrets-run + run: | + if [ ${{ secrets.DEPLOYMENTS_ENABLED }} == 'true' ]; then + echo "ok=enabled" >> $GITHUB_OUTPUT + fi + secrets-gate-webhook: + runs-on: ubuntu-latest + outputs: + ok: ${{ steps.check-secrets-webhook.outputs.ok }} + steps: + - name: check for secrets needed to run workflows + id: check-secrets-webhook + run: | + if [ ${{ secrets.SEND_FINISHED_WEBHOOK }} == 'true' ]; then + echo "ok=enabled" >> $GITHUB_OUTPUT + fi + test-deploy: + needs: + - secrets-gate-run + if: ${{ needs.secrets-gate-run.outputs.ok == 'enabled' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + - name: Setup Helm + run: scripts/setup_helm_builder.sh + - name: Setup AWS + run: scripts/setup_aws_builder.sh $EKS_AWS_ACCESS_KEY_ID $EKS_AWS_ACCESS_KEY_SECRET $AWS_REGION $CLUSTER_NAME + env: + EKS_AWS_ACCESS_KEY_ID: ${{ secrets.EKS_AWS_ACCESS_KEY_ID }} + EKS_AWS_ACCESS_KEY_SECRET: ${{ secrets.EKS_AWS_ACCESS_KEY_SECRET }} + AWS_REGION: ${{ secrets.AWS_REGION }} + CLUSTER_NAME: ${{ secrets.CLUSTER_NAME }} + - name: Space debug + run: | + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf "/usr/local/share/boost" + sudo rm -rf "$AGENT_TOOLSDIRECTORY" + - name: move package.json + run: mv package.json package.jsonmoved + - name: npm-install 'cli', @aws-sdk/client-ecr(-public), and @kubernetes/client-node + run: npm install cli @aws-sdk/client-ecr @aws-sdk/client-ecr-public @kubernetes/client-node + - name: restore package.json + run: mv package.jsonmoved package.json + - name: Expose GitHub Runtime + uses: crazy-max/ghaction-github-runtime@v2 + - name: Build and Push Docker Image + run: bash scripts/build_docker_builder.sh dev $GITHUB_SHA $DOCKER_LABEL $AWS_REGION $PRIVATE_ECR + env: + STORAGE_AWS_ACCESS_KEY_ID: ${{ secrets.STORAGE_AWS_ACCESS_KEY_ID }} + STORAGE_AWS_ACCESS_KEY_SECRET: ${{ secrets.STORAGE_AWS_ACCESS_KEY_SECRET }} + DOCKER_LABEL: ${{ secrets.DOCKER_LABEL }} + REPO_NAME: ${{ secrets.DEV_REPO_NAME }} + AWS_REGION: ${{ secrets.AWS_REGION }} + ECR_URL: ${{ secrets.ECR_URL }} + PRIVATE_ECR: ${{ secrets.PRIVATE_ECR }} + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }} + PUBLISH_DOCKERHUB: ${{ secrets.PUBLISH_DOCKERHUB }} + - name: Deploy to EKS + run: bash scripts/deploy_builder.sh dev $GITHUB_SHA + - name: Job succeeded + if: ${{ needs.secrets-gate-webhook.outputs.ok == 'enabled' }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 # Not needed with a .ruby-version file + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + env: + JOB_STATUS: ${{ job.status }} + WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }} + HOOK_OS_NAME: ${{ runner.os }} + WORKFLOW_NAME: ${{ github.workflow }} + run: | + git clone https://github.com/DiscordHooks/github-actions-discord-webhook.git webhook + bash webhook/send.sh $JOB_STATUS $WEBHOOK_URL + shell: bash diff --git a/packages/editor/src/components/projects/EditPermissionsDialog.tsx b/packages/editor/src/components/projects/EditPermissionsDialog.tsx index dcc89efe7351..39e1c2244ea0 100644 --- a/packages/editor/src/components/projects/EditPermissionsDialog.tsx +++ b/packages/editor/src/components/projects/EditPermissionsDialog.tsx @@ -62,6 +62,7 @@ export const EditPermissionsDialog = ({ patchPermission, removePermission }: Props): any => { + console.log('EditPermissionsDialog') const { t } = useTranslation() const [error, setError] = useState('') diff --git a/packages/editor/src/components/projects/ProjectsPage.tsx b/packages/editor/src/components/projects/ProjectsPage.tsx index 1d81544fce2e..d940847b463f 100644 --- a/packages/editor/src/components/projects/ProjectsPage.tsx +++ b/packages/editor/src/components/projects/ProjectsPage.tsx @@ -31,7 +31,7 @@ import { ProjectService, ProjectState } from '@etherealengine/client-core/src/co import { RouterState } from '@etherealengine/client-core/src/common/services/RouterService' import { AuthState } from '@etherealengine/client-core/src/user/services/AuthService' import multiLogger from '@etherealengine/engine/src/common/functions/logger' -import { getMutableState, useHookstate } from '@etherealengine/hyperflux' +import {getMutableState, NO_PROXY, useHookstate} from '@etherealengine/hyperflux' import { ArrowRightRounded, @@ -299,6 +299,7 @@ const ProjectsPage = () => { const openEditPermissionsDialog = () => editPermissionsDialogOpen.set(true) const closeEditPermissionsDialog = () => editPermissionsDialogOpen.set(false) + console.log('activeProject', activeProject.value, activeProject.get(NO_PROXY), activeProject.get(NO_PROXY)?.projectPermissions) const deleteProject = async () => { closeDeleteConfirm() diff --git a/packages/server-core/src/hooks/project-permission-authenticate.ts b/packages/server-core/src/hooks/project-permission-authenticate.ts index 1dff2b8d3393..72663f9fcd30 100755 --- a/packages/server-core/src/hooks/project-permission-authenticate.ts +++ b/packages/server-core/src/hooks/project-permission-authenticate.ts @@ -25,6 +25,7 @@ Ethereal Engine. All Rights Reserved. import { BadRequest, Forbidden } from '@feathersjs/errors' import { HookContext, Paginated } from '@feathersjs/feathers' +import { Application } from '../../declarations' import { GITHUB_URL_REGEX } from '@etherealengine/common/src/constants/GitHubConstants' @@ -41,7 +42,7 @@ import { UserType } from '@etherealengine/engine/src/schemas/user/user.schema' import { checkUserRepoWriteStatus } from '../projects/project/github-helper' export default (writeAccess) => { - return async (context: HookContext): Promise => { + return async (context: HookContext) => { const { params, app } = context if (context.params.isInternal) return context const loggedInUser = params.user as UserType diff --git a/packages/server-core/src/projects/project-permission/project-permission.hooks.ts b/packages/server-core/src/projects/project-permission/project-permission.hooks.ts index 47f4fedcb4f3..7d07cc711d32 100644 --- a/packages/server-core/src/projects/project-permission/project-permission.hooks.ts +++ b/packages/server-core/src/projects/project-permission/project-permission.hooks.ts @@ -66,13 +66,14 @@ const ensureInviteCode = async (context: HookContext) const data: ProjectPermissionData[] = Array.isArray(context.data) ? context.data : [context.data] if (data[0].inviteCode && USER_ID_REGEX.test(data[0].inviteCode)) { - context.data[0].userId = data[0].inviteCode as UserID - delete context.data[0].inviteCode + data[0].userId = data[0].inviteCode as UserID + delete data[0].inviteCode } if (data[0].userId && INVITE_CODE_REGEX.test(data[0].userId)) { - context.data[0].inviteCode = data[0].userId - delete context.data[0].userId + data[0].inviteCode = data[0].userId + delete data[0].userId } + context.data = data[0] } /** diff --git a/packages/server-core/src/projects/project/github-helper.ts b/packages/server-core/src/projects/project/github-helper.ts index 4a2d420b7c5a..698e3c9fcd28 100755 --- a/packages/server-core/src/projects/project/github-helper.ts +++ b/packages/server-core/src/projects/project/github-helper.ts @@ -114,10 +114,12 @@ export const checkUserOrgWriteStatus = async (org, token) => { } export const checkAppOrgStatus = async (organization, token) => { + console.log('checkAppOrgStatus', organization, token) const octo = new Octokit({ auth: token }) const authUser = await octo.rest.users.getAuthenticated() if (organization === authUser.data.login) return 200 const orgs = await getUserOrgs(token) + console.log('user orgs', orgs) return orgs.find((org) => org.login.toLowerCase() === organization.toLowerCase()) } @@ -386,7 +388,7 @@ const uploadToRepo = async ( //Create the new commit with all of the file changes const newCommit = await createNewCommit(octo, org, repo, commitMessage, newTree.sha, currentCommit.commitSha) - await app.service(projectPath)._patch(project.id, { commitSHA: newCommit.sha, commitDate: toDateTimeSql(new Date()) }) + await app.service(projectPath).patch(project.id, { commitSHA: newCommit.sha, commitDate: toDateTimeSql(new Date()) }) try { //This pushes the commit to the main branch in GitHub diff --git a/packages/server-core/src/projects/project/project-helper.ts b/packages/server-core/src/projects/project/project-helper.ts index 756f82a8e5cc..f5f62400975b 100644 --- a/packages/server-core/src/projects/project/project-helper.ts +++ b/packages/server-core/src/projects/project/project-helper.ts @@ -1509,7 +1509,7 @@ export const updateProject = async ( const returned = !existingProject ? // Add to DB - await app.service(projectPath)._create( + await app.service(projectPath).create( { id: v4(), name: projectName, @@ -1535,17 +1535,10 @@ export const updateProject = async ( updateType: data.updateType, updateSchedule: data.updateSchedule, updateUserId: userId - }) + }, params) returned.needsRebuild = typeof data.needsRebuild === 'boolean' ? data.needsRebuild : true - if (!existingProject) { - await app.service(projectPermissionPath).create({ - projectId: returned.id, - userId - }) - } - if (returned.name !== projectName) await app.service(projectPath).patch(existingProject!.id, { name: projectName @@ -1561,7 +1554,7 @@ export const updateProject = async ( await app.service(projectPath).patch(returned.id, { commitSHA, commitDate: toDateTimeSql(commitDate) - }) + }, params) } // run project install script if (projectConfig.onEvent) { @@ -1570,9 +1563,9 @@ export const updateProject = async ( const k8BatchClient = getState(ServerState).k8BatchClient - if (k8BatchClient && (data.updateType === 'tag' || data.updateType === 'commit')) { + if (k8BatchClient && (data.updateType === 'tag' || data.updateType === 'commit')) await createOrUpdateProjectUpdateJob(app, projectName) - } else if (k8BatchClient && (data.updateType === 'none' || data.updateType == null)) + else if (k8BatchClient && (data.updateType === 'none' || data.updateType == null)) await removeProjectUpdateJob(app, projectName) if (params?.jobId) { diff --git a/packages/server-core/src/projects/project/project.hooks.ts b/packages/server-core/src/projects/project/project.hooks.ts index 14ff374bd609..509fd53881c0 100644 --- a/packages/server-core/src/projects/project/project.hooks.ts +++ b/packages/server-core/src/projects/project/project.hooks.ts @@ -266,24 +266,26 @@ const checkIfNameIsValid = async (context: HookContext) => { */ const uploadLocalProject = async (context: HookContext) => { const projectLocalDirectory = path.resolve(projectsRootFolder, context.projectName) - copyFolderRecursiveSync(templateFolderDirectory, projectsRootFolder) - fs.renameSync(path.resolve(projectsRootFolder, 'template-project'), projectLocalDirectory) + if (!fs.existsSync(projectLocalDirectory)) { + copyFolderRecursiveSync(templateFolderDirectory, projectsRootFolder) + fs.renameSync(path.resolve(projectsRootFolder, 'template-project'), projectLocalDirectory) - fs.mkdirSync(path.resolve(projectLocalDirectory, '.git'), { recursive: true }) + fs.mkdirSync(path.resolve(projectLocalDirectory, '.git'), {recursive: true}) - const git = useGit(path.resolve(projectLocalDirectory, '.git')) - try { - await git.init(true) - } catch (e) { - logger.warn(e) - } + const git = useGit(path.resolve(projectLocalDirectory, '.git')) + try { + await git.init(true) + } catch (e) { + logger.warn(e) + } - const packageData = Object.assign({}, templateProjectJson) as any - packageData.name = context.projectName - packageData.etherealEngine.version = getEnginePackageJson().version - fs.writeFileSync(path.resolve(projectLocalDirectory, 'package.json'), JSON.stringify(packageData, null, 2)) + const packageData = Object.assign({}, templateProjectJson) as any + packageData.name = context.projectName + packageData.etherealEngine.version = getEnginePackageJson().version + fs.writeFileSync(path.resolve(projectLocalDirectory, 'package.json'), JSON.stringify(packageData, null, 2)) - await uploadLocalProjectToProvider(context.app, context.projectName, false) + await uploadLocalProjectToProvider(context.app, context.projectName, false) + } } /** @@ -328,7 +330,7 @@ const linkGithubToProject = async (context: HookContext) => { if (githubIdentityProvider.data.length === 0) throw new Error('Must be logged in with GitHub to link a project to a GitHub repo') const split = githubPathRegexExec[2].split('/') - const org = split + const org = split[0] const repo = split[1].replace('.git', '') const appOrgAccess = await checkAppOrgStatus(org, githubIdentityProvider.data[0].oauthToken) if (!appOrgAccess) @@ -485,20 +487,21 @@ const removeProjectUpdate = async (context: HookContext) => { * 1. Clones the repo to the local FS * 2. If in production mode, uploads it to the storage provider * 3. Creates a database entry - * @param data - * @param placeholder This is where data normally goes, but we've put data as the first parameter - * @param params + * @param context Hook context * @returns */ const updateProjectJob = async (context: HookContext) => { + console.log('updateProjectJob') if (!context.data || context.method !== 'update') { throw new BadRequest(`${context.path} service only works for data in ${context.method}`) } const data: ProjectBuildUpdateItemType = context.data as ProjectBuildUpdateItemType + console.log('project data', data) if (!config.kubernetes.enabled || context.params?.isJob) - context.result = updateProject(context.app, context.data, context.params) + context.result = await updateProject(context.app, context.data, context.params) else { + console.log('Updating project through job') const urlParts = data.sourceURL.split('/') let projectName = data.name || urlParts.pop() if (!projectName) throw new Error('Git repo must be plain URL') @@ -538,6 +541,7 @@ const updateProjectJob = async (context: HookContext) => { throw err } } + console.log('Finished updateProjectJob') } export default { @@ -559,21 +563,18 @@ export default { updateCreateData ], update: [ - iff(isProvider('external'), verifyScope('editor', 'write')), - projectPermissionAuthenticate(false), + iff(isProvider('external'), verifyScope('editor', 'write'), projectPermissionAuthenticate(false)), () => schemaHooks.validateData(projectPatchValidator), updateProjectJob ], patch: [ - iff(isProvider('external'), verifyScope('editor', 'write')), - projectPermissionAuthenticate(false), + iff(isProvider('external'), verifyScope('editor', 'write'), projectPermissionAuthenticate(false)), () => schemaHooks.validateData(projectPatchValidator), schemaHooks.resolveData(projectPatchResolver), iff(isProvider('external'), linkGithubToProject) ], remove: [ - iff(isProvider('external'), verifyScope('editor', 'write')), - projectPermissionAuthenticate(false), + iff(isProvider('external'), verifyScope('editor', 'write'), projectPermissionAuthenticate(false)), getProjectName, runProjectUninstallScript, removeProjectFiles, diff --git a/packages/server-core/src/projects/project/project.resolvers.ts b/packages/server-core/src/projects/project/project.resolvers.ts index 83202ebcbf9c..105529390666 100644 --- a/packages/server-core/src/projects/project/project.resolvers.ts +++ b/packages/server-core/src/projects/project/project.resolvers.ts @@ -63,13 +63,12 @@ export const projectDbToSchema = (rawData: ProjectDatabaseType): ProjectType => export const projectResolver = resolve( { projectPermissions: virtual(async (project, context) => { - if (context.params?.query?.allowed) - return (await context.app.service(projectPermissionPath).find({ - query: { - projectId: project.id - }, - paginate: false - })) as any as ProjectPermissionType[] + return (await context.app.service(projectPermissionPath).find({ + query: { + projectId: project.id + }, + paginate: false + })) as any as ProjectPermissionType[] }), commitDate: virtual(async (project) => { diff --git a/packages/server-core/src/projects/project/project.test.ts b/packages/server-core/src/projects/project/project.test.ts index 2a489495c627..0eb57aac22cf 100644 --- a/packages/server-core/src/projects/project/project.test.ts +++ b/packages/server-core/src/projects/project/project.test.ts @@ -43,7 +43,7 @@ const cleanup = async (app: Application) => { const projectDir = path.resolve(appRootPath.path, `packages/projects/projects/${newProjectName}/`) deleteFolderRecursive(projectDir) try { - await app.service(projectPath)._remove(null, { query: { name: newProjectName } }) + await app.service(projectPath).remove(null, { query: { name: newProjectName } }) } catch (e) { // }