-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Attempted to set up a fake dependabot-api server using json-server. The integration test now boots up a localhost server running json-server that looks similar to dependabot-api allowing the updater to complete the update. I haven't fully grocked how it works but should be possible to get it to persist the pr create from the updater and assert it from the test.
- Loading branch information
Philip Harrison
committed
Jul 27, 2021
1 parent
a47bd57
commit e60f3c5
Showing
11 changed files
with
3,230 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| name: 'build-test' | ||
| on: pull_request | ||
|
|
||
| jobs: | ||
| integration-ci: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha }} | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: GPR login | ||
| run: docker login docker.pkg.github.com -u x -p ${{ secrets.GPR_TOKEN }} | ||
| - name: GRP pull | ||
| run: docker pull docker.pkg.github.com/dependabot/dependabot-updater:latest | ||
| - run: | | ||
| npm ci | ||
| - name: Run integration test files | ||
| env: | ||
| DEPENDABOT_API_URL: 'http://host.docker.internal:9000' | ||
| run: npm test "integration" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import Docker from 'dockerode' | ||
| import {UPDATER_IMAGE_NAME} from '../src/main' | ||
|
|
||
| export const removeDanglingUpdaterContainers = async (): Promise<void> => { | ||
| const docker = new Docker() | ||
| const containers = (await docker.listContainers()) || [] | ||
|
|
||
| for (const container of containers) { | ||
| if (container.Image.includes(UPDATER_IMAGE_NAME)) { | ||
| try { | ||
| await docker.getContainer(container.Id).remove({v: true, force: true}) | ||
| } catch (e) { | ||
| // ignore | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| { | ||
| "update_jobs": [ | ||
| { | ||
| "id": 1, | ||
| "allowed-updates": [ | ||
| { | ||
| "dependency-type": "direct", | ||
| "update-type": "all" | ||
| } | ||
| ], | ||
| "credentials-metadata": [ | ||
| { | ||
| "type": "git_source", | ||
| "host": "github.com" | ||
| } | ||
| ], | ||
| "dependencies": null, | ||
| "existing-pull-requests": [], | ||
| "ignore-conditions": [], | ||
| "lockfile-only": false, | ||
| "max-updater-run-time": 2700, | ||
| "package-manager": "npm_and_yarn", | ||
| "source": { | ||
| "provider": "github", | ||
| "repo": "dsp-testing/dependabot-all-updates-test", | ||
| "directory": "/", | ||
| "branch": null, | ||
| "api-endpoint": "https://api.github.com/", | ||
| "hostname": "github.com" | ||
| }, | ||
| "updating-a-pull-request": false, | ||
| "update-subdependencies": false, | ||
| "requirements-update-strategy": null, | ||
| "security-advisories": [], | ||
| "security-updates-only": false, | ||
| "vendor-dependencies": false, | ||
| "reject-external-code": false, | ||
| "experiments": { | ||
| "build-pull-request-message": true | ||
| }, | ||
| "commit-message-options": { | ||
| "include-scope": null, | ||
| "prefix": null, | ||
| "prefix-development": null | ||
| }, | ||
| "data": { | ||
| "base-commit-sha": "a8d9c08ff29358f80f6194b5909de9879741780d" | ||
| } | ||
| } | ||
| ], | ||
| "credentials": [{"id": 1}], | ||
| "dependencies": [], | ||
| "update_job_errors": [], | ||
| "pull_requests": [] | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| const jsonServer = require('json-server') | ||
| const path = require('path') | ||
| const fs = require('fs') | ||
| const server = jsonServer.create() | ||
| const db = JSON.parse(fs.readFileSync(path.join(__dirname, 'db.json'))) | ||
| const router = jsonServer.router(db) | ||
| const middlewares = jsonServer.defaults() | ||
|
|
||
| const SERVER_PORT = 9000 | ||
|
|
||
| // NOTE: Serialise the response like dependabot-api | ||
| router.render = (_, res) => { | ||
| const id = res.locals.data.id | ||
| const data = { | ||
| attributes: res.locals.data | ||
| } | ||
| if (id) { | ||
| data.id = id | ||
| } | ||
| res.jsonp({ | ||
| data | ||
| }) | ||
| } | ||
|
|
||
| server.get('/update_jobs/:id/credentials', (_, res) => { | ||
| res.jsonp({ | ||
| data: { | ||
| attributes: { | ||
| credentials: { | ||
| type: 'git_source', | ||
| host: 'github.com', | ||
| username: 'x-access-token', | ||
| password: process.env.GITHUB_TOKEN | ||
| } | ||
| } | ||
| } | ||
| }) | ||
| }) | ||
|
|
||
| server.use( | ||
| jsonServer.rewriter({ | ||
| '/update_jobs/:id/details': '/update_jobs/:id', | ||
| '/update_jobs/:id/credentials': '/credentials/:id', | ||
| '/update_jobs/:id/create_pull_request': '/pull_requests', | ||
| '/update_jobs/:id/update_pull_request': '/pull_requests', | ||
| '/update_jobs/:id/close_pull_request': '/pull_requests', | ||
| '/update_jobs/:id/record_update_job_error': '/update_job_errors/:id', | ||
| '/update_jobs/:id/mark_as_processed': '/update_jobs/:id', | ||
| '/update_jobs/:id/update_dependency_list': '/dependencies/:id', | ||
| '/update_jobs/:id/record_package_manager_version': '/update_jobs/:id' | ||
| }) | ||
| ) | ||
|
|
||
| server.use(jsonServer.bodyParser) | ||
| // TEMP HACK: Always return 204 on post so the updater doesn't buil out | ||
| server.use((req, res, next) => { | ||
| if (req.method === 'POST' && req.body.data) { | ||
| req.body = req.body.data | ||
| res.sendStatus(204) | ||
| } | ||
| next() | ||
| }) | ||
|
|
||
| server.use(middlewares) | ||
| server.use(router) | ||
| server.listen(SERVER_PORT, () => { | ||
| console.log(`JSON Server is running on http://localhost:${SERVER_PORT}`) | ||
| }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,87 +1,79 @@ | ||
| import Docker from 'dockerode' | ||
| import fs from 'fs' | ||
| import path from 'path' | ||
| import axios from 'axios' | ||
| import waitPort from 'wait-port' | ||
| import {spawn} from 'child_process' | ||
|
|
||
| import {Updater} from '../src/updater' | ||
| import {UPDATER_IMAGE_NAME} from '../src/main' | ||
| import {APIClient, JobParameters} from '../src/api-client' | ||
| import {ImageService} from '../src/image-service' | ||
|
|
||
| import {removeDanglingUpdaterContainers} from './helpers' | ||
| const FAKE_SERVER_PORT = 9000 | ||
|
|
||
| describe('Updater', () => { | ||
| let server: any | ||
|
|
||
| // To run the js-code itself against API: | ||
| // const params = { | ||
| // jobID: 1, | ||
| // jobToken: 'xxx', | ||
| // credentialsToken: 'xxx', | ||
| // dependabotAPI: 'http://host.docker.internal:3001' | ||
| // } | ||
| // const client = axios.create({baseURL: params.dependabotAPI}) | ||
| // const api = new DependabotAPI(client, params) | ||
| // const updater = new Updater(UPDATER_IMAGE_NAME, api) | ||
|
|
||
| // This stubs out API calls from JS, but will run the updater against an API | ||
| // running on the specified API endpoint. | ||
| const mockAPIClient: any = { | ||
| getJobDetails: jest.fn(), | ||
| getCredentials: jest.fn(), | ||
| params: { | ||
| jobID: 1, | ||
| jobToken: process.env.JOB_TOKEN, | ||
| credentialsToken: process.env.CREDENTIALS_TOKEN, | ||
| dependabotAPIURL: 'http://host.docker.internal:3001' | ||
| } | ||
| } | ||
| const updater = new Updater(UPDATER_IMAGE_NAME, mockAPIClient) | ||
| // This runs the tests against a fake dependabot-api server using json-server | ||
| const fakeDependabotApiUrl = `http://host.docker.internal:${FAKE_SERVER_PORT}` | ||
| const dependabotApiUrl = | ||
| process.env.DEPENDABOT_API_URL || fakeDependabotApiUrl | ||
| const params = new JobParameters( | ||
| 1, | ||
| process.env.JOB_TOKEN || 'job-token', | ||
| process.env.CREDENTIALS_TOKEN || 'cred-token', | ||
| process.env.DEPENDABOT_API_URL || | ||
| `http://host.docker.internal:${FAKE_SERVER_PORT}` | ||
| ) | ||
|
|
||
| const client = axios.create({baseURL: params.dependabotAPIURL}) | ||
| const apiClient = new APIClient(client, params) | ||
| const updater = new Updater(UPDATER_IMAGE_NAME, apiClient) | ||
|
|
||
| beforeAll(async () => { | ||
| if (process.env.CI) { | ||
| if (process.env.SKIP_INTEGRATION_TESTS) { | ||
| // Skip this test on CI, as it takes too long to download the image | ||
| return | ||
| } | ||
|
|
||
| await ImageService.pull(UPDATER_IMAGE_NAME) | ||
|
|
||
| if (dependabotApiUrl === fakeDependabotApiUrl) { | ||
| server = spawn(`${path.join(__dirname, 'server/server.js')}`) | ||
| server.stdout.on('data', (data: any) => { | ||
| console.log(`json-server log: ${data}`) // eslint-disable-line no-console | ||
| }) | ||
| server.stderr.on('data', (data: any) => { | ||
| console.error(`json-server error: ${data}`) // eslint-disable-line no-console | ||
| }) | ||
| await waitPort({port: FAKE_SERVER_PORT}) | ||
| } | ||
| }) | ||
|
|
||
| afterEach(async () => { | ||
| const docker = new Docker() | ||
| const containers = (await docker.listContainers()) || [] | ||
|
|
||
| for (const container of containers) { | ||
| if ( | ||
| container.Image.includes( | ||
| 'docker.pkg.github.com/dependabot/dependabot-updater' | ||
| ) | ||
| ) { | ||
| try { | ||
| await docker.getContainer(container.Id).remove({v: true, force: true}) | ||
| } catch (e) { | ||
| // ignore | ||
| } | ||
| } | ||
| } | ||
| server && server.kill() | ||
| await removeDanglingUpdaterContainers() | ||
| }) | ||
|
|
||
| jest.setTimeout(20000) | ||
| jest.setTimeout(30000) | ||
| it('should fetch manifests', async () => { | ||
| if (process.env.CI) { | ||
| if (process.env.SKIP_INTEGRATION_TESTS) { | ||
| // Skip this test on CI, as it takes too long to download the image | ||
| return | ||
| } | ||
|
|
||
| mockAPIClient.getJobDetails.mockImplementation(() => { | ||
| return JSON.parse( | ||
| fs | ||
| .readFileSync(path.join(__dirname, 'fixtures/job-details/npm.json')) | ||
| .toString() | ||
| ).data.attributes | ||
| }) | ||
| mockAPIClient.getCredentials.mockImplementation(() => { | ||
| return [ | ||
| { | ||
| type: 'git_source', | ||
| host: 'github.com', | ||
| username: 'x-access-token', | ||
| password: process.env.GITHUB_TOKEN | ||
| } | ||
| ] | ||
| }) | ||
| await updater.runUpdater() | ||
|
|
||
| // TODO: Check if the pr was persisted in json-server | ||
| // const res = await client.get('/pull_requests/1') | ||
| // expect(res.status).toEqual(200) | ||
| }) | ||
| }) |
Oops, something went wrong.