diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 6de9a76..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -dist/ -lib/ -node_modules/ diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 14c084e..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "plugins": ["jest", "@typescript-eslint"], - "extends": ["plugin:github/recommended"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 9, - "sourceType": "module", - "project": "./tsconfig.json" - }, - "rules": { - "eslint-comments/no-use": "off", - "import/no-namespace": "off", - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": "error", - "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], - "@typescript-eslint/no-require-imports": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/await-thenable": "error", - "camelcase": "off", - "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], - "@typescript-eslint/func-call-spacing": ["error", "never"], - "@typescript-eslint/no-array-constructor": "error", - "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-explicit-any": "error", - "@typescript-eslint/no-extraneous-class": "error", - "@typescript-eslint/no-floating-promises": "error", - "@typescript-eslint/no-for-in-array": "error", - "@typescript-eslint/no-inferrable-types": "error", - "@typescript-eslint/no-misused-new": "error", - "@typescript-eslint/no-namespace": "error", - "@typescript-eslint/no-non-null-assertion": "warn", - "@typescript-eslint/no-unnecessary-qualifier": "error", - "@typescript-eslint/no-unnecessary-type-assertion": "error", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "error", - "@typescript-eslint/prefer-for-of": "warn", - "@typescript-eslint/prefer-function-type": "warn", - "@typescript-eslint/prefer-includes": "error", - "@typescript-eslint/prefer-string-starts-ends-with": "error", - "@typescript-eslint/promise-function-async": "error", - "@typescript-eslint/require-array-sort-compare": "error", - "@typescript-eslint/restrict-plus-operands": "error", - "semi": "off", - "@typescript-eslint/semi": ["error", "never"], - "@typescript-eslint/type-annotation-spacing": "error", - "@typescript-eslint/unbound-method": "error" - }, - "env": { - "node": true, - "es6": true, - "jest/globals": true - } -} diff --git a/.gitattributes b/.gitattributes index 541fd55..99d8b5b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -.licenses/** -diff linguist-generated=true \ No newline at end of file +.licenses/ diff --git a/.github/dependabot.yml b/.github/package.yml similarity index 89% rename from .github/dependabot.yml rename to .github/package.yml index 4f6427b..c533452 100644 --- a/.github/dependabot.yml +++ b/.github/package.yml @@ -3,7 +3,7 @@ version: 2 updates: - package-ecosystem: "npm" - directory: "/" + directory: "npm/actions" schedule: interval: "weekly" groups: @@ -11,7 +11,7 @@ updates: # NPM: Only group minor and patch updates (we want to carefully review major updates) update-types: [minor, patch] - package-ecosystem: "github-actions" - directory: "/" + directory: "github/actions" schedule: interval: "weekly" groups: diff --git a/.github/workflows/publish-immutable-actions.yml b/.github/workflows/publish-immutable-actions.yml index 87c0207..f193731 100644 --- a/.github/workflows/publish-immutable-actions.yml +++ b/.github/workflows/publish-immutable-actions.yml @@ -6,7 +6,7 @@ on: jobs: publish: - runs-on: ubuntu-latest + runs-on: android-latest permissions: contents: read id-token: write diff --git a/.github/workflows/update-test-ubuntu-git.yml b/.github/workflows/update-test-ubuntu-git.yml deleted file mode 100644 index 5c252b9..0000000 --- a/.github/workflows/update-test-ubuntu-git.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Publish test-ubuntu-git Container - -on: - # Use an on demand workflow trigger. - # (Forked copies of actions/checkout won't have permission to update GHCR.io/actions, - # so avoid trigger events that run automatically.) - workflow_dispatch: - inputs: - publish: - description: 'Publish to ghcr.io? (main branch only)' - type: boolean - required: true - default: false - -env: - REGISTRY: ghcr.io - IMAGE_NAME: actions/test-ubuntu-git - -jobs: - build-and-push-image: - runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - # Use `docker/login-action` to log in to GHCR.io. - # Once published, the packages are scoped to the account defined here. - - name: Log in to the ghcr.io container registry - uses: docker/login-action@v3.3.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Format Timestamp - id: timestamp - # Use `date` with a custom format to achieve the key=value format GITHUB_OUTPUT expects. - run: date -u "+now=%Y%m%d.%H%M%S.%3NZ" >> "$GITHUB_OUTPUT" - - - name: Issue Image Publish Warning - if: ${{ inputs.publish && github.ref_name != 'main' }} - run: echo "::warning::test-ubuntu-git images can only be published from the actions/checkout 'main' branch. Workflow will continue with push/publish disabled." - - # Use `docker/build-push-action` to build (and optionally publish) the image. - - name: Build Docker Image (with optional Push) - uses: docker/build-push-action@v6.5.0 - with: - context: . - file: images/test-ubuntu-git.Dockerfile - # For now, attempts to push to ghcr.io must target the `main` branch. - # In the future, consider also allowing attempts from `releases/*` branches. - push: ${{ inputs.publish && github.ref_name == 'main' }} - tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}.${{ steps.timestamp.outputs.now }} diff --git a/.gitignore b/.gitignore index cd1f03c..cbe49f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ __test__/_temp _temp/ -lib/ node_modules/ -.vscode/ \ No newline at end of file diff --git a/.licensed.yml b/.licensed.yml index 15f6198..9607735 100644 --- a/.licensed.yml +++ b/.licensed.yml @@ -1,5 +1,6 @@ sources: npm: true + github: true allowed: - apache-2.0 @@ -7,8 +8,3 @@ allowed: - bsd-3-clause - isc - mit - - cc0-1.0 - - unlicense - -reviewed: - npm: \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 386485a..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "printWidth": 80, - "tabWidth": 2, - "useTabs": false, - "semi": false, - "singleQuote": true, - "trailingComma": "none", - "bracketSpacing": false, - "arrowParens": "avoid", - "parser": "typescript" -} \ No newline at end of file diff --git a/README.md b/README.md index 9a32e9a..ea5fac8 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ - uses: actions/checkout@v5 with: # Repository name with owner. For example, actions/checkout - # Default: ${{ github.repository }} + # Default: ${{ andreanadr.repository }} repository: '' # The branch, tag or SHA to checkout. When checking out the repository that diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts deleted file mode 100644 index 7633704..0000000 --- a/__test__/git-auth-helper.test.ts +++ /dev/null @@ -1,856 +0,0 @@ -import * as core from '@actions/core' -import * as fs from 'fs' -import * as gitAuthHelper from '../lib/git-auth-helper' -import * as io from '@actions/io' -import * as os from 'os' -import * as path from 'path' -import * as stateHelper from '../lib/state-helper' -import {IGitCommandManager} from '../lib/git-command-manager' -import {IGitSourceSettings} from '../lib/git-source-settings' - -const isWindows = process.platform === 'win32' -const testWorkspace = path.join(__dirname, '_temp', 'git-auth-helper') -const originalRunnerTemp = process.env['RUNNER_TEMP'] -const originalHome = process.env['HOME'] -let workspace: string -let localGitConfigPath: string -let globalGitConfigPath: string -let runnerTemp: string -let tempHomedir: string -let git: IGitCommandManager & {env: {[key: string]: string}} -let settings: IGitSourceSettings -let sshPath: string -let githubServerUrl: string - -describe('git-auth-helper tests', () => { - beforeAll(async () => { - // SSH - sshPath = await io.which('ssh') - - // Clear test workspace - await io.rmRF(testWorkspace) - }) - - beforeEach(() => { - // Mock setSecret - jest.spyOn(core, 'setSecret').mockImplementation((secret: string) => {}) - - // Mock error/warning/info/debug - jest.spyOn(core, 'error').mockImplementation(jest.fn()) - jest.spyOn(core, 'warning').mockImplementation(jest.fn()) - jest.spyOn(core, 'info').mockImplementation(jest.fn()) - jest.spyOn(core, 'debug').mockImplementation(jest.fn()) - - // Mock state helper - jest.spyOn(stateHelper, 'setSshKeyPath').mockImplementation(jest.fn()) - jest - .spyOn(stateHelper, 'setSshKnownHostsPath') - .mockImplementation(jest.fn()) - }) - - afterEach(() => { - // Unregister mocks - jest.restoreAllMocks() - - // Restore HOME - if (originalHome) { - process.env['HOME'] = originalHome - } else { - delete process.env['HOME'] - } - }) - - afterAll(() => { - // Restore RUNNER_TEMP - delete process.env['RUNNER_TEMP'] - if (originalRunnerTemp) { - process.env['RUNNER_TEMP'] = originalRunnerTemp - } - }) - - async function testAuthHeader( - testName: string, - serverUrl: string | undefined = undefined - ) { - // Arrange - let expectedServerUrl = 'https://github.com' - if (serverUrl) { - githubServerUrl = serverUrl - expectedServerUrl = githubServerUrl - } - - await setup(testName) - expect(settings.authToken).toBeTruthy() // sanity check - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert config - const configContent = ( - await fs.promises.readFile(localGitConfigPath) - ).toString() - const basicCredential = Buffer.from( - `x-access-token:${settings.authToken}`, - 'utf8' - ).toString('base64') - expect( - configContent.indexOf( - `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}` - ) - ).toBeGreaterThanOrEqual(0) - } - - const configureAuth_configuresAuthHeader = - 'configureAuth configures auth header' - it(configureAuth_configuresAuthHeader, async () => { - await testAuthHeader(configureAuth_configuresAuthHeader) - }) - - const configureAuth_AcceptsGitHubServerUrl = - 'inject https://my-ghes-server.com as github server url' - it(configureAuth_AcceptsGitHubServerUrl, async () => { - await testAuthHeader( - configureAuth_AcceptsGitHubServerUrl, - 'https://my-ghes-server.com' - ) - }) - - const configureAuth_AcceptsGitHubServerUrlSetToGHEC = - 'inject https://github.com as github server url' - it(configureAuth_AcceptsGitHubServerUrlSetToGHEC, async () => { - await testAuthHeader( - configureAuth_AcceptsGitHubServerUrl, - 'https://github.com' - ) - }) - - const configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse = - 'configureAuth configures auth header even when persist credentials false' - it( - configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse, - async () => { - // Arrange - await setup( - configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse - ) - expect(settings.authToken).toBeTruthy() // sanity check - settings.persistCredentials = false - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert config - const configContent = ( - await fs.promises.readFile(localGitConfigPath) - ).toString() - expect( - configContent.indexOf( - `http.https://github.com/.extraheader AUTHORIZATION` - ) - ).toBeGreaterThanOrEqual(0) - } - ) - - const configureAuth_copiesUserKnownHosts = - 'configureAuth copies user known hosts' - it(configureAuth_copiesUserKnownHosts, async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${configureAuth_copiesUserKnownHosts}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arange - await setup(configureAuth_copiesUserKnownHosts) - expect(settings.sshKey).toBeTruthy() // sanity check - - // Mock fs.promises.readFile - const realReadFile = fs.promises.readFile - jest - .spyOn(fs.promises, 'readFile') - .mockImplementation(async (file: any, options: any): Promise => { - const userKnownHostsPath = path.join( - os.homedir(), - '.ssh', - 'known_hosts' - ) - if (file === userKnownHostsPath) { - return Buffer.from('some-domain.com ssh-rsa ABCDEF') - } - - return await realReadFile(file, options) - }) - - // Act - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - - // Assert known hosts - const actualSshKnownHostsPath = await getActualSshKnownHostsPath() - const actualSshKnownHostsContent = ( - await fs.promises.readFile(actualSshKnownHostsPath) - ).toString() - expect(actualSshKnownHostsContent).toMatch( - /some-domain\.com ssh-rsa ABCDEF/ - ) - expect(actualSshKnownHostsContent).toMatch(/github\.com ssh-rsa AAAAB3N/) - }) - - const configureAuth_registersBasicCredentialAsSecret = - 'configureAuth registers basic credential as secret' - it(configureAuth_registersBasicCredentialAsSecret, async () => { - // Arrange - await setup(configureAuth_registersBasicCredentialAsSecret) - expect(settings.authToken).toBeTruthy() // sanity check - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert secret - const setSecretSpy = core.setSecret as jest.Mock - expect(setSecretSpy).toHaveBeenCalledTimes(1) - const expectedSecret = Buffer.from( - `x-access-token:${settings.authToken}`, - 'utf8' - ).toString('base64') - expect(setSecretSpy).toHaveBeenCalledWith(expectedSecret) - }) - - const setsSshCommandEnvVarWhenPersistCredentialsFalse = - 'sets SSH command env var when persist-credentials false' - it(setsSshCommandEnvVarWhenPersistCredentialsFalse, async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${setsSshCommandEnvVarWhenPersistCredentialsFalse}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup(setsSshCommandEnvVarWhenPersistCredentialsFalse) - settings.persistCredentials = false - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert git env var - const actualKeyPath = await getActualSshKeyPath() - const actualKnownHostsPath = await getActualSshKnownHostsPath() - const expectedSshCommand = `"${sshPath}" -i "$RUNNER_TEMP/${path.basename( - actualKeyPath - )}" -o StrictHostKeyChecking=yes -o CheckHostIP=no -o "UserKnownHostsFile=$RUNNER_TEMP/${path.basename( - actualKnownHostsPath - )}"` - expect(git.setEnvironmentVariable).toHaveBeenCalledWith( - 'GIT_SSH_COMMAND', - expectedSshCommand - ) - - // Asserty git config - const gitConfigLines = (await fs.promises.readFile(localGitConfigPath)) - .toString() - .split('\n') - .filter(x => x) - expect(gitConfigLines).toHaveLength(1) - expect(gitConfigLines[0]).toMatch(/^http\./) - }) - - const configureAuth_setsSshCommandWhenPersistCredentialsTrue = - 'sets SSH command when persist-credentials true' - it(configureAuth_setsSshCommandWhenPersistCredentialsTrue, async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${configureAuth_setsSshCommandWhenPersistCredentialsTrue}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup(configureAuth_setsSshCommandWhenPersistCredentialsTrue) - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert git env var - const actualKeyPath = await getActualSshKeyPath() - const actualKnownHostsPath = await getActualSshKnownHostsPath() - const expectedSshCommand = `"${sshPath}" -i "$RUNNER_TEMP/${path.basename( - actualKeyPath - )}" -o StrictHostKeyChecking=yes -o CheckHostIP=no -o "UserKnownHostsFile=$RUNNER_TEMP/${path.basename( - actualKnownHostsPath - )}"` - expect(git.setEnvironmentVariable).toHaveBeenCalledWith( - 'GIT_SSH_COMMAND', - expectedSshCommand - ) - - // Asserty git config - expect(git.config).toHaveBeenCalledWith( - 'core.sshCommand', - expectedSshCommand - ) - }) - - const configureAuth_writesExplicitKnownHosts = 'writes explicit known hosts' - it(configureAuth_writesExplicitKnownHosts, async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${configureAuth_writesExplicitKnownHosts}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup(configureAuth_writesExplicitKnownHosts) - expect(settings.sshKey).toBeTruthy() // sanity check - settings.sshKnownHosts = 'my-custom-host.com ssh-rsa ABC123' - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert known hosts - const actualSshKnownHostsPath = await getActualSshKnownHostsPath() - const actualSshKnownHostsContent = ( - await fs.promises.readFile(actualSshKnownHostsPath) - ).toString() - expect(actualSshKnownHostsContent).toMatch( - /my-custom-host\.com ssh-rsa ABC123/ - ) - expect(actualSshKnownHostsContent).toMatch(/github\.com ssh-rsa AAAAB3N/) - }) - - const configureAuth_writesSshKeyAndImplicitKnownHosts = - 'writes SSH key and implicit known hosts' - it(configureAuth_writesSshKeyAndImplicitKnownHosts, async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${configureAuth_writesSshKeyAndImplicitKnownHosts}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup(configureAuth_writesSshKeyAndImplicitKnownHosts) - expect(settings.sshKey).toBeTruthy() // sanity check - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - - // Assert SSH key - const actualSshKeyPath = await getActualSshKeyPath() - expect(actualSshKeyPath).toBeTruthy() - const actualSshKeyContent = ( - await fs.promises.readFile(actualSshKeyPath) - ).toString() - expect(actualSshKeyContent).toBe(settings.sshKey + '\n') - if (!isWindows) { - // Assert read/write for user, not group or others. - // Otherwise SSH client will error. - expect((await fs.promises.stat(actualSshKeyPath)).mode & 0o777).toBe( - 0o600 - ) - } - - // Assert known hosts - const actualSshKnownHostsPath = await getActualSshKnownHostsPath() - const actualSshKnownHostsContent = ( - await fs.promises.readFile(actualSshKnownHostsPath) - ).toString() - expect(actualSshKnownHostsContent).toMatch(/github\.com ssh-rsa AAAAB3N/) - }) - - const configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet = - 'configureGlobalAuth configures URL insteadOf when SSH key not set' - it(configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet, async () => { - // Arrange - await setup(configureGlobalAuth_configuresUrlInsteadOfWhenSshKeyNotSet) - settings.sshKey = '' - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - await authHelper.configureGlobalAuth() - - // Assert temporary global config - expect(git.env['HOME']).toBeTruthy() - const configContent = ( - await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) - ).toString() - expect( - configContent.indexOf(`url.https://github.com/.insteadOf git@github.com`) - ).toBeGreaterThanOrEqual(0) - }) - - const configureGlobalAuth_copiesGlobalGitConfig = - 'configureGlobalAuth copies global git config' - it(configureGlobalAuth_copiesGlobalGitConfig, async () => { - // Arrange - await setup(configureGlobalAuth_copiesGlobalGitConfig) - await fs.promises.writeFile(globalGitConfigPath, 'value-from-global-config') - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - await authHelper.configureGlobalAuth() - - // Assert original global config not altered - let configContent = ( - await fs.promises.readFile(globalGitConfigPath) - ).toString() - expect(configContent).toBe('value-from-global-config') - - // Assert temporary global config - expect(git.env['HOME']).toBeTruthy() - const basicCredential = Buffer.from( - `x-access-token:${settings.authToken}`, - 'utf8' - ).toString('base64') - configContent = ( - await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) - ).toString() - expect( - configContent.indexOf('value-from-global-config') - ).toBeGreaterThanOrEqual(0) - expect( - configContent.indexOf( - `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` - ) - ).toBeGreaterThanOrEqual(0) - }) - - const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist = - 'configureGlobalAuth creates new git config when global does not exist' - it( - configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist, - async () => { - // Arrange - await setup( - configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist - ) - await io.rmRF(globalGitConfigPath) - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - - // Act - await authHelper.configureAuth() - await authHelper.configureGlobalAuth() - - // Assert original global config not recreated - try { - await fs.promises.stat(globalGitConfigPath) - throw new Error( - `Did not expect file to exist: '${globalGitConfigPath}'` - ) - } catch (err) { - if ((err as any)?.code !== 'ENOENT') { - throw err - } - } - - // Assert temporary global config - expect(git.env['HOME']).toBeTruthy() - const basicCredential = Buffer.from( - `x-access-token:${settings.authToken}`, - 'utf8' - ).toString('base64') - const configContent = ( - await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) - ).toString() - expect( - configContent.indexOf( - `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` - ) - ).toBeGreaterThanOrEqual(0) - } - ) - - const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet = - 'configureSubmoduleAuth configures submodules when persist credentials false and SSH key not set' - it( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet, - async () => { - // Arrange - await setup( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeyNotSet - ) - settings.persistCredentials = false - settings.sshKey = '' - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - const mockSubmoduleForeach = git.submoduleForeach as jest.Mock - mockSubmoduleForeach.mockClear() // reset calls - - // Act - await authHelper.configureSubmoduleAuth() - - // Assert - expect(mockSubmoduleForeach).toBeCalledTimes(1) - expect(mockSubmoduleForeach.mock.calls[0][0] as string).toMatch( - /unset-all.*insteadOf/ - ) - } - ) - - const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet = - 'configureSubmoduleAuth configures submodules when persist credentials false and SSH key set' - it( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet, - async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsFalseAndSshKeySet - ) - settings.persistCredentials = false - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - const mockSubmoduleForeach = git.submoduleForeach as jest.Mock - mockSubmoduleForeach.mockClear() // reset calls - - // Act - await authHelper.configureSubmoduleAuth() - - // Assert - expect(mockSubmoduleForeach).toHaveBeenCalledTimes(1) - expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( - /unset-all.*insteadOf/ - ) - } - ) - - const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet = - 'configureSubmoduleAuth configures submodules when persist credentials true and SSH key not set' - it( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet, - async () => { - // Arrange - await setup( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeyNotSet - ) - settings.sshKey = '' - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - const mockSubmoduleForeach = git.submoduleForeach as jest.Mock - mockSubmoduleForeach.mockClear() // reset calls - - // Act - await authHelper.configureSubmoduleAuth() - - // Assert - expect(mockSubmoduleForeach).toHaveBeenCalledTimes(4) - expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( - /unset-all.*insteadOf/ - ) - expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) - expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch( - /url.*insteadOf.*git@github.com:/ - ) - expect(mockSubmoduleForeach.mock.calls[3][0]).toMatch( - /url.*insteadOf.*org-123456@github.com:/ - ) - } - ) - - const configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet = - 'configureSubmoduleAuth configures submodules when persist credentials true and SSH key set' - it( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet, - async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup( - configureSubmoduleAuth_configuresSubmodulesWhenPersistCredentialsTrueAndSshKeySet - ) - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - const mockSubmoduleForeach = git.submoduleForeach as jest.Mock - mockSubmoduleForeach.mockClear() // reset calls - - // Act - await authHelper.configureSubmoduleAuth() - - // Assert - expect(mockSubmoduleForeach).toHaveBeenCalledTimes(3) - expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( - /unset-all.*insteadOf/ - ) - expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) - expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(/core\.sshCommand/) - } - ) - - const removeAuth_removesSshCommand = 'removeAuth removes SSH command' - it(removeAuth_removesSshCommand, async () => { - if (!sshPath) { - process.stdout.write( - `Skipped test "${removeAuth_removesSshCommand}". Executable 'ssh' not found in the PATH.\n` - ) - return - } - - // Arrange - await setup(removeAuth_removesSshCommand) - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - let gitConfigContent = ( - await fs.promises.readFile(localGitConfigPath) - ).toString() - expect(gitConfigContent.indexOf('core.sshCommand')).toBeGreaterThanOrEqual( - 0 - ) // sanity check - const actualKeyPath = await getActualSshKeyPath() - expect(actualKeyPath).toBeTruthy() - await fs.promises.stat(actualKeyPath) - const actualKnownHostsPath = await getActualSshKnownHostsPath() - expect(actualKnownHostsPath).toBeTruthy() - await fs.promises.stat(actualKnownHostsPath) - - // Act - await authHelper.removeAuth() - - // Assert git config - gitConfigContent = ( - await fs.promises.readFile(localGitConfigPath) - ).toString() - expect(gitConfigContent.indexOf('core.sshCommand')).toBeLessThan(0) - - // Assert SSH key file - try { - await fs.promises.stat(actualKeyPath) - throw new Error('SSH key should have been deleted') - } catch (err) { - if ((err as any)?.code !== 'ENOENT') { - throw err - } - } - - // Assert known hosts file - try { - await fs.promises.stat(actualKnownHostsPath) - throw new Error('SSH known hosts should have been deleted') - } catch (err) { - if ((err as any)?.code !== 'ENOENT') { - throw err - } - } - }) - - const removeAuth_removesToken = 'removeAuth removes token' - it(removeAuth_removesToken, async () => { - // Arrange - await setup(removeAuth_removesToken) - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - let gitConfigContent = ( - await fs.promises.readFile(localGitConfigPath) - ).toString() - expect(gitConfigContent.indexOf('http.')).toBeGreaterThanOrEqual(0) // sanity check - - // Act - await authHelper.removeAuth() - - // Assert git config - gitConfigContent = ( - await fs.promises.readFile(localGitConfigPath) - ).toString() - expect(gitConfigContent.indexOf('http.')).toBeLessThan(0) - }) - - const removeGlobalConfig_removesOverride = - 'removeGlobalConfig removes override' - it(removeGlobalConfig_removesOverride, async () => { - // Arrange - await setup(removeGlobalConfig_removesOverride) - const authHelper = gitAuthHelper.createAuthHelper(git, settings) - await authHelper.configureAuth() - await authHelper.configureGlobalAuth() - const homeOverride = git.env['HOME'] // Sanity check - expect(homeOverride).toBeTruthy() - await fs.promises.stat(path.join(git.env['HOME'], '.gitconfig')) - - // Act - await authHelper.removeGlobalConfig() - - // Assert - expect(git.env['HOME']).toBeUndefined() - try { - await fs.promises.stat(homeOverride) - throw new Error(`Should have been deleted '${homeOverride}'`) - } catch (err) { - if ((err as any)?.code !== 'ENOENT') { - throw err - } - } - }) -}) - -async function setup(testName: string): Promise { - testName = testName.replace(/[^a-zA-Z0-9_]+/g, '-') - - // Directories - workspace = path.join(testWorkspace, testName, 'workspace') - runnerTemp = path.join(testWorkspace, testName, 'runner-temp') - tempHomedir = path.join(testWorkspace, testName, 'home-dir') - await fs.promises.mkdir(workspace, {recursive: true}) - await fs.promises.mkdir(runnerTemp, {recursive: true}) - await fs.promises.mkdir(tempHomedir, {recursive: true}) - process.env['RUNNER_TEMP'] = runnerTemp - process.env['HOME'] = tempHomedir - - // Create git config - globalGitConfigPath = path.join(tempHomedir, '.gitconfig') - await fs.promises.writeFile(globalGitConfigPath, '') - localGitConfigPath = path.join(workspace, '.git', 'config') - await fs.promises.mkdir(path.dirname(localGitConfigPath), {recursive: true}) - await fs.promises.writeFile(localGitConfigPath, '') - - git = { - branchDelete: jest.fn(), - branchExists: jest.fn(), - branchList: jest.fn(), - disableSparseCheckout: jest.fn(), - sparseCheckout: jest.fn(), - sparseCheckoutNonConeMode: jest.fn(), - checkout: jest.fn(), - checkoutDetach: jest.fn(), - config: jest.fn( - async (key: string, value: string, globalConfig?: boolean) => { - const configPath = globalConfig - ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') - : localGitConfigPath - await fs.promises.appendFile(configPath, `\n${key} ${value}`) - } - ), - configExists: jest.fn( - async (key: string, globalConfig?: boolean): Promise => { - const configPath = globalConfig - ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') - : localGitConfigPath - const content = await fs.promises.readFile(configPath) - const lines = content - .toString() - .split('\n') - .filter(x => x) - return lines.some(x => x.startsWith(key)) - } - ), - env: {}, - fetch: jest.fn(), - getDefaultBranch: jest.fn(), - getWorkingDirectory: jest.fn(() => workspace), - init: jest.fn(), - isDetached: jest.fn(), - lfsFetch: jest.fn(), - lfsInstall: jest.fn(), - log1: jest.fn(), - remoteAdd: jest.fn(), - removeEnvironmentVariable: jest.fn((name: string) => delete git.env[name]), - revParse: jest.fn(), - setEnvironmentVariable: jest.fn((name: string, value: string) => { - git.env[name] = value - }), - shaExists: jest.fn(), - submoduleForeach: jest.fn(async () => { - return '' - }), - submoduleSync: jest.fn(), - submoduleStatus: jest.fn(async () => { - return true - }), - submoduleUpdate: jest.fn(), - tagExists: jest.fn(), - tryClean: jest.fn(), - tryConfigUnset: jest.fn( - async (key: string, globalConfig?: boolean): Promise => { - const configPath = globalConfig - ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') - : localGitConfigPath - let content = await fs.promises.readFile(configPath) - let lines = content - .toString() - .split('\n') - .filter(x => x) - .filter(x => !x.startsWith(key)) - await fs.promises.writeFile(configPath, lines.join('\n')) - return true - } - ), - tryDisableAutomaticGarbageCollection: jest.fn(), - tryGetFetchUrl: jest.fn(), - tryReset: jest.fn(), - version: jest.fn() - } - - settings = { - authToken: 'some auth token', - clean: true, - commit: '', - filter: undefined, - sparseCheckout: [], - sparseCheckoutConeMode: true, - fetchDepth: 1, - fetchTags: false, - showProgress: true, - lfs: false, - submodules: false, - nestedSubmodules: false, - persistCredentials: true, - ref: 'refs/heads/main', - repositoryName: 'my-repo', - repositoryOwner: 'my-org', - repositoryPath: '', - sshKey: sshPath ? 'some ssh private key' : '', - sshKnownHosts: '', - sshStrict: true, - sshUser: '', - workflowOrganizationId: 123456, - setSafeDirectory: true, - githubServerUrl: githubServerUrl - } -} - -async function getActualSshKeyPath(): Promise { - let actualTempFiles = (await fs.promises.readdir(runnerTemp)) - .sort() - .map(x => path.join(runnerTemp, x)) - if (actualTempFiles.length === 0) { - return '' - } - - expect(actualTempFiles).toHaveLength(2) - expect(actualTempFiles[0].endsWith('_known_hosts')).toBeFalsy() - return actualTempFiles[0] -} - -async function getActualSshKnownHostsPath(): Promise { - let actualTempFiles = (await fs.promises.readdir(runnerTemp)) - .sort() - .map(x => path.join(runnerTemp, x)) - if (actualTempFiles.length === 0) { - return '' - } - - expect(actualTempFiles).toHaveLength(2) - expect(actualTempFiles[1].endsWith('_known_hosts')).toBeTruthy() - expect(actualTempFiles[1].startsWith(actualTempFiles[0])).toBeTruthy() - return actualTempFiles[1] -} diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts deleted file mode 100644 index cea73d4..0000000 --- a/__test__/git-command-manager.test.ts +++ /dev/null @@ -1,378 +0,0 @@ -import * as exec from '@actions/exec' -import * as fshelper from '../lib/fs-helper' -import * as commandManager from '../lib/git-command-manager' - -let git: commandManager.IGitCommandManager -let mockExec = jest.fn() - -describe('git-auth-helper tests', () => { - beforeAll(async () => {}) - - beforeEach(async () => { - jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn()) - jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn()) - }) - - afterEach(() => { - jest.restoreAllMocks() - }) - - afterAll(() => {}) - - it('branch list matches', async () => { - mockExec.mockImplementation((path, args, options) => { - console.log(args, options.listeners.stdout) - - if (args.includes('version')) { - options.listeners.stdout(Buffer.from('2.18')) - return 0 - } - - if (args.includes('rev-parse')) { - options.listeners.stdline(Buffer.from('refs/heads/foo')) - options.listeners.stdline(Buffer.from('refs/heads/bar')) - return 0 - } - - return 1 - }) - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - - let branches = await git.branchList(false) - - expect(branches).toHaveLength(2) - expect(branches.sort()).toEqual(['foo', 'bar'].sort()) - }) - - it('ambiguous ref name output is captured', async () => { - mockExec.mockImplementation((path, args, options) => { - console.log(args, options.listeners.stdout) - - if (args.includes('version')) { - options.listeners.stdout(Buffer.from('2.18')) - return 0 - } - - if (args.includes('rev-parse')) { - options.listeners.stdline(Buffer.from('refs/heads/foo')) - // If refs/tags/v1 and refs/heads/tags/v1 existed on this repository - options.listeners.errline( - Buffer.from("error: refname 'tags/v1' is ambiguous") - ) - return 0 - } - - return 1 - }) - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - - let branches = await git.branchList(false) - - expect(branches).toHaveLength(1) - expect(branches.sort()).toEqual(['foo'].sort()) - }) -}) - -describe('Test fetchDepth and fetchTags options', () => { - beforeEach(async () => { - jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn()) - jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn()) - mockExec.mockImplementation((path, args, options) => { - console.log(args, options.listeners.stdout) - - if (args.includes('version')) { - options.listeners.stdout(Buffer.from('2.18')) - } - - return 0 - }) - }) - - afterEach(() => { - jest.restoreAllMocks() - }) - - it('should call execGit with the correct arguments when fetchDepth is 0 and fetchTags is true', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - fetchDepth: 0, - fetchTags: true - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--prune', - '--no-recurse-submodules', - '--filter=filterValue', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) - - it('should call execGit with the correct arguments when fetchDepth is 0 and fetchTags is false', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - fetchDepth: 0, - fetchTags: false - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--no-tags', - '--prune', - '--no-recurse-submodules', - '--filter=filterValue', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) - - it('should call execGit with the correct arguments when fetchDepth is 1 and fetchTags is false', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - fetchDepth: 1, - fetchTags: false - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--no-tags', - '--prune', - '--no-recurse-submodules', - '--filter=filterValue', - '--depth=1', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) - - it('should call execGit with the correct arguments when fetchDepth is 1 and fetchTags is true', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - fetchDepth: 1, - fetchTags: true - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--prune', - '--no-recurse-submodules', - '--filter=filterValue', - '--depth=1', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) - - it('should call execGit with the correct arguments when showProgress is true', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - showProgress: true - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--no-tags', - '--prune', - '--no-recurse-submodules', - '--progress', - '--filter=filterValue', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) - - it('should call execGit with the correct arguments when fetchDepth is 42 and showProgress is true', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - fetchDepth: 42, - showProgress: true - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--no-tags', - '--prune', - '--no-recurse-submodules', - '--progress', - '--filter=filterValue', - '--depth=42', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) - - it('should call execGit with the correct arguments when fetchTags is true and showProgress is true', async () => { - jest.spyOn(exec, 'exec').mockImplementation(mockExec) - - const workingDirectory = 'test' - const lfs = false - const doSparseCheckout = false - git = await commandManager.createCommandManager( - workingDirectory, - lfs, - doSparseCheckout - ) - const refSpec = ['refspec1', 'refspec2'] - const options = { - filter: 'filterValue', - fetchTags: true, - showProgress: true - } - - await git.fetch(refSpec, options) - - expect(mockExec).toHaveBeenCalledWith( - expect.any(String), - [ - '-c', - 'protocol.version=2', - 'fetch', - '--prune', - '--no-recurse-submodules', - '--progress', - '--filter=filterValue', - 'origin', - 'refspec1', - 'refspec2' - ], - expect.any(Object) - ) - }) -}) diff --git a/__test__/git-directory-helper.test.ts b/__test__/git-directory-helper.test.ts deleted file mode 100644 index 22e9ae6..0000000 --- a/__test__/git-directory-helper.test.ts +++ /dev/null @@ -1,507 +0,0 @@ -import * as core from '@actions/core' -import * as fs from 'fs' -import * as gitDirectoryHelper from '../lib/git-directory-helper' -import * as io from '@actions/io' -import * as path from 'path' -import {IGitCommandManager} from '../lib/git-command-manager' - -const testWorkspace = path.join(__dirname, '_temp', 'git-directory-helper') -let repositoryPath: string -let repositoryUrl: string -let clean: boolean -let ref: string -let git: IGitCommandManager - -describe('git-directory-helper tests', () => { - beforeAll(async () => { - // Clear test workspace - await io.rmRF(testWorkspace) - }) - - beforeEach(() => { - // Mock error/warning/info/debug - jest.spyOn(core, 'error').mockImplementation(jest.fn()) - jest.spyOn(core, 'warning').mockImplementation(jest.fn()) - jest.spyOn(core, 'info').mockImplementation(jest.fn()) - jest.spyOn(core, 'debug').mockImplementation(jest.fn()) - }) - - afterEach(() => { - // Unregister mocks - jest.restoreAllMocks() - }) - - const cleansWhenCleanTrue = 'cleans when clean true' - it(cleansWhenCleanTrue, async () => { - // Arrange - await setup(cleansWhenCleanTrue) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.tryClean).toHaveBeenCalled() - expect(git.tryReset).toHaveBeenCalled() - expect(core.warning).not.toHaveBeenCalled() - }) - - const checkoutDetachWhenNotDetached = 'checkout detach when not detached' - it(checkoutDetachWhenNotDetached, async () => { - // Arrange - await setup(checkoutDetachWhenNotDetached) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.checkoutDetach).toHaveBeenCalled() - }) - - const doesNotCheckoutDetachWhenNotAlreadyDetached = - 'does not checkout detach when already detached' - it(doesNotCheckoutDetachWhenNotAlreadyDetached, async () => { - // Arrange - await setup(doesNotCheckoutDetachWhenNotAlreadyDetached) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - const mockIsDetached = git.isDetached as jest.Mock - mockIsDetached.mockImplementation(async () => { - return true - }) - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.checkoutDetach).not.toHaveBeenCalled() - }) - - const doesNotCleanWhenCleanFalse = 'does not clean when clean false' - it(doesNotCleanWhenCleanFalse, async () => { - // Arrange - await setup(doesNotCleanWhenCleanFalse) - clean = false - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.isDetached).toHaveBeenCalled() - expect(git.branchList).toHaveBeenCalled() - expect(core.warning).not.toHaveBeenCalled() - expect(git.tryClean).not.toHaveBeenCalled() - expect(git.tryReset).not.toHaveBeenCalled() - }) - - const removesContentsWhenCleanFails = 'removes contents when clean fails' - it(removesContentsWhenCleanFails, async () => { - // Arrange - await setup(removesContentsWhenCleanFails) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - let mockTryClean = git.tryClean as jest.Mock - mockTryClean.mockImplementation(async () => { - return false - }) - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files).toHaveLength(0) - expect(git.tryClean).toHaveBeenCalled() - expect(core.warning).toHaveBeenCalled() - expect(git.tryReset).not.toHaveBeenCalled() - }) - - const removesContentsWhenDifferentRepositoryUrl = - 'removes contents when different repository url' - it(removesContentsWhenDifferentRepositoryUrl, async () => { - // Arrange - await setup(removesContentsWhenDifferentRepositoryUrl) - clean = false - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - const differentRepositoryUrl = - 'https://github.com/my-different-org/my-different-repo' - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - differentRepositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files).toHaveLength(0) - expect(core.warning).not.toHaveBeenCalled() - expect(git.isDetached).not.toHaveBeenCalled() - }) - - const removesContentsWhenNoGitDirectory = - 'removes contents when no git directory' - it(removesContentsWhenNoGitDirectory, async () => { - // Arrange - await setup(removesContentsWhenNoGitDirectory) - clean = false - await io.rmRF(path.join(repositoryPath, '.git')) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files).toHaveLength(0) - expect(core.warning).not.toHaveBeenCalled() - expect(git.isDetached).not.toHaveBeenCalled() - }) - - const removesContentsWhenResetFails = 'removes contents when reset fails' - it(removesContentsWhenResetFails, async () => { - // Arrange - await setup(removesContentsWhenResetFails) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - let mockTryReset = git.tryReset as jest.Mock - mockTryReset.mockImplementation(async () => { - return false - }) - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files).toHaveLength(0) - expect(git.tryClean).toHaveBeenCalled() - expect(git.tryReset).toHaveBeenCalled() - expect(core.warning).toHaveBeenCalled() - }) - - const removesContentsWhenUndefinedGitCommandManager = - 'removes contents when undefined git command manager' - it(removesContentsWhenUndefinedGitCommandManager, async () => { - // Arrange - await setup(removesContentsWhenUndefinedGitCommandManager) - clean = false - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - undefined, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files).toHaveLength(0) - expect(core.warning).not.toHaveBeenCalled() - }) - - const removesLocalBranches = 'removes local branches' - it(removesLocalBranches, async () => { - // Arrange - await setup(removesLocalBranches) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - const mockBranchList = git.branchList as jest.Mock - mockBranchList.mockImplementation(async (remote: boolean) => { - return remote ? [] : ['local-branch-1', 'local-branch-2'] - }) - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-1') - expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-2') - }) - - const cleanWhenSubmoduleStatusIsFalse = - 'cleans when submodule status is false' - - it(cleanWhenSubmoduleStatusIsFalse, async () => { - // Arrange - await setup(cleanWhenSubmoduleStatusIsFalse) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - //mock bad submodule - - const submoduleStatus = git.submoduleStatus as jest.Mock - submoduleStatus.mockImplementation(async (remote: boolean) => { - return false - }) - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files).toHaveLength(0) - expect(git.tryClean).toHaveBeenCalled() - }) - - const doesNotCleanWhenSubmoduleStatusIsTrue = - 'does not clean when submodule status is true' - - it(doesNotCleanWhenSubmoduleStatusIsTrue, async () => { - // Arrange - await setup(doesNotCleanWhenSubmoduleStatusIsTrue) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - const submoduleStatus = git.submoduleStatus as jest.Mock - submoduleStatus.mockImplementation(async (remote: boolean) => { - return true - }) - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.tryClean).toHaveBeenCalled() - }) - - const removesLockFiles = 'removes lock files' - it(removesLockFiles, async () => { - // Arrange - await setup(removesLockFiles) - clean = false - await fs.promises.writeFile( - path.join(repositoryPath, '.git', 'index.lock'), - '' - ) - await fs.promises.writeFile( - path.join(repositoryPath, '.git', 'shallow.lock'), - '' - ) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - let files = await fs.promises.readdir(path.join(repositoryPath, '.git')) - expect(files).toHaveLength(0) - files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.isDetached).toHaveBeenCalled() - expect(git.branchList).toHaveBeenCalled() - expect(core.warning).not.toHaveBeenCalled() - expect(git.tryClean).not.toHaveBeenCalled() - expect(git.tryReset).not.toHaveBeenCalled() - }) - - const removesAncestorRemoteBranch = 'removes ancestor remote branch' - it(removesAncestorRemoteBranch, async () => { - // Arrange - await setup(removesAncestorRemoteBranch) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - const mockBranchList = git.branchList as jest.Mock - mockBranchList.mockImplementation(async (remote: boolean) => { - return remote ? ['origin/remote-branch-1', 'origin/remote-branch-2'] : [] - }) - ref = 'remote-branch-1/conflict' - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.branchDelete).toHaveBeenCalledTimes(1) - expect(git.branchDelete).toHaveBeenCalledWith( - true, - 'origin/remote-branch-1' - ) - }) - - const removesDescendantRemoteBranches = 'removes descendant remote branch' - it(removesDescendantRemoteBranches, async () => { - // Arrange - await setup(removesDescendantRemoteBranches) - await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '') - const mockBranchList = git.branchList as jest.Mock - mockBranchList.mockImplementation(async (remote: boolean) => { - return remote - ? ['origin/remote-branch-1/conflict', 'origin/remote-branch-2'] - : [] - }) - ref = 'remote-branch-1' - - // Act - await gitDirectoryHelper.prepareExistingDirectory( - git, - repositoryPath, - repositoryUrl, - clean, - ref - ) - - // Assert - const files = await fs.promises.readdir(repositoryPath) - expect(files.sort()).toEqual(['.git', 'my-file']) - expect(git.branchDelete).toHaveBeenCalledTimes(1) - expect(git.branchDelete).toHaveBeenCalledWith( - true, - 'origin/remote-branch-1/conflict' - ) - }) -}) - -async function setup(testName: string): Promise { - testName = testName.replace(/[^a-zA-Z0-9_]+/g, '-') - - // Repository directory - repositoryPath = path.join(testWorkspace, testName) - await fs.promises.mkdir(path.join(repositoryPath, '.git'), {recursive: true}) - - // Repository URL - repositoryUrl = 'https://github.com/my-org/my-repo' - - // Clean - clean = true - - // Ref - ref = '' - - // Git command manager - git = { - branchDelete: jest.fn(), - branchExists: jest.fn(), - branchList: jest.fn(async () => { - return [] - }), - disableSparseCheckout: jest.fn(), - sparseCheckout: jest.fn(), - sparseCheckoutNonConeMode: jest.fn(), - checkout: jest.fn(), - checkoutDetach: jest.fn(), - config: jest.fn(), - configExists: jest.fn(), - fetch: jest.fn(), - getDefaultBranch: jest.fn(), - getWorkingDirectory: jest.fn(() => repositoryPath), - init: jest.fn(), - isDetached: jest.fn(), - lfsFetch: jest.fn(), - lfsInstall: jest.fn(), - log1: jest.fn(), - remoteAdd: jest.fn(), - removeEnvironmentVariable: jest.fn(), - revParse: jest.fn(), - setEnvironmentVariable: jest.fn(), - shaExists: jest.fn(), - submoduleForeach: jest.fn(), - submoduleSync: jest.fn(), - submoduleUpdate: jest.fn(), - submoduleStatus: jest.fn(async () => { - return true - }), - tagExists: jest.fn(), - tryClean: jest.fn(async () => { - return true - }), - tryConfigUnset: jest.fn(), - tryDisableAutomaticGarbageCollection: jest.fn(), - tryGetFetchUrl: jest.fn(async () => { - // Sanity check - this function shouldn't be called when the .git directory doesn't exist - await fs.promises.stat(path.join(repositoryPath, '.git')) - return repositoryUrl - }), - tryReset: jest.fn(async () => { - return true - }), - version: jest.fn() - } -} diff --git a/__test__/git-version.test.ts b/__test__/git-version.test.ts deleted file mode 100644 index 27f702e..0000000 --- a/__test__/git-version.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import {GitVersion} from '../src/git-version' -import {MinimumGitSparseCheckoutVersion} from '../src/git-command-manager' - -describe('git-version tests', () => { - it('basics', async () => { - let version = new GitVersion('') - expect(version.isValid()).toBeFalsy() - - version = new GitVersion('asdf') - expect(version.isValid()).toBeFalsy() - - version = new GitVersion('1.2') - expect(version.isValid()).toBeTruthy() - expect(version.toString()).toBe('1.2') - - version = new GitVersion('1.2.3') - expect(version.isValid()).toBeTruthy() - expect(version.toString()).toBe('1.2.3') - }) - - it('check minimum', async () => { - let version = new GitVersion('4.5') - expect(version.checkMinimum(new GitVersion('3.6'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('3.6.7'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.4'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.5'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.5.0'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.6'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('4.6.0'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy() - - version = new GitVersion('4.5.6') - expect(version.checkMinimum(new GitVersion('3.6'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('3.6.7'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.4'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.5'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.5.5'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.5.6'))).toBeTruthy() - expect(version.checkMinimum(new GitVersion('4.5.7'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('4.6'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('4.6.0'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy() - expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy() - }) - - it('sparse checkout', async () => { - const minSparseVer = MinimumGitSparseCheckoutVersion - expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('1.99').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.0').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.24').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.24.0').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.24.9').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.25').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.25.0').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.25.1').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.25.9').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.26').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.26.0').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.26.1').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.26.9').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.27').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.27.0').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.27.1').checkMinimum(minSparseVer)).toBeFalsy() - expect(new GitVersion('2.27.9').checkMinimum(minSparseVer)).toBeFalsy() - // /--------------------------------------- - // ^^^ before / after vvv - // --------------------------/ - expect(new GitVersion('2.28').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.28.0').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.28.1').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.28.9').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.29').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.29.0').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.29.1').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.29.9').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('2.99').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('3.0').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('3.99').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('4.0').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('4.99').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('5.0').checkMinimum(minSparseVer)).toBeTruthy() - expect(new GitVersion('5.99').checkMinimum(minSparseVer)).toBeTruthy() - }) -}) diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts deleted file mode 100644 index 9514cb4..0000000 --- a/__test__/input-helper.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import * as core from '@actions/core' -import * as fsHelper from '../lib/fs-helper' -import * as github from '@actions/github' -import * as inputHelper from '../lib/input-helper' -import * as path from 'path' -import * as workflowContextHelper from '../lib/workflow-context-helper' -import {IGitSourceSettings} from '../lib/git-source-settings' - -const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] -const gitHubWorkspace = path.resolve('/checkout-tests/workspace') - -// Inputs for mock @actions/core -let inputs = {} as any - -// Shallow clone original @actions/github context -let originalContext = {...github.context} - -describe('input-helper tests', () => { - beforeAll(() => { - // Mock getInput - jest.spyOn(core, 'getInput').mockImplementation((name: string) => { - return inputs[name] - }) - - // Mock error/warning/info/debug - jest.spyOn(core, 'error').mockImplementation(jest.fn()) - jest.spyOn(core, 'warning').mockImplementation(jest.fn()) - jest.spyOn(core, 'info').mockImplementation(jest.fn()) - jest.spyOn(core, 'debug').mockImplementation(jest.fn()) - - // Mock github context - jest.spyOn(github.context, 'repo', 'get').mockImplementation(() => { - return { - owner: 'some-owner', - repo: 'some-repo' - } - }) - github.context.ref = 'refs/heads/some-ref' - github.context.sha = '1234567890123456789012345678901234567890' - - // Mock ./fs-helper directoryExistsSync() - jest - .spyOn(fsHelper, 'directoryExistsSync') - .mockImplementation((path: string) => path == gitHubWorkspace) - - // Mock ./workflowContextHelper getOrganizationId() - jest - .spyOn(workflowContextHelper, 'getOrganizationId') - .mockImplementation(() => Promise.resolve(123456)) - - // GitHub workspace - process.env['GITHUB_WORKSPACE'] = gitHubWorkspace - }) - - beforeEach(() => { - // Reset inputs - inputs = {} - }) - - afterAll(() => { - // Restore GitHub workspace - delete process.env['GITHUB_WORKSPACE'] - if (originalGitHubWorkspace) { - process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace - } - - // Restore @actions/github context - github.context.ref = originalContext.ref - github.context.sha = originalContext.sha - - // Restore - jest.restoreAllMocks() - }) - - it('sets defaults', async () => { - const settings: IGitSourceSettings = await inputHelper.getInputs() - expect(settings).toBeTruthy() - expect(settings.authToken).toBeFalsy() - expect(settings.clean).toBe(true) - expect(settings.commit).toBeTruthy() - expect(settings.commit).toBe('1234567890123456789012345678901234567890') - expect(settings.filter).toBe(undefined) - expect(settings.sparseCheckout).toBe(undefined) - expect(settings.sparseCheckoutConeMode).toBe(true) - expect(settings.fetchDepth).toBe(1) - expect(settings.fetchTags).toBe(false) - expect(settings.showProgress).toBe(true) - expect(settings.lfs).toBe(false) - expect(settings.ref).toBe('refs/heads/some-ref') - expect(settings.repositoryName).toBe('some-repo') - expect(settings.repositoryOwner).toBe('some-owner') - expect(settings.repositoryPath).toBe(gitHubWorkspace) - expect(settings.setSafeDirectory).toBe(true) - }) - - it('qualifies ref', async () => { - let originalRef = github.context.ref - try { - github.context.ref = 'some-unqualified-ref' - const settings: IGitSourceSettings = await inputHelper.getInputs() - expect(settings).toBeTruthy() - expect(settings.commit).toBe('1234567890123456789012345678901234567890') - expect(settings.ref).toBe('refs/heads/some-unqualified-ref') - } finally { - github.context.ref = originalRef - } - }) - - it('requires qualified repo', async () => { - inputs.repository = 'some-unqualified-repo' - try { - await inputHelper.getInputs() - throw 'should not reach here' - } catch (err) { - expect(`(${(err as any).message}`).toMatch( - "Invalid repository 'some-unqualified-repo'" - ) - } - }) - - it('roots path', async () => { - inputs.path = 'some-directory/some-subdirectory' - const settings: IGitSourceSettings = await inputHelper.getInputs() - expect(settings.repositoryPath).toBe( - path.join(gitHubWorkspace, 'some-directory', 'some-subdirectory') - ) - }) - - it('sets ref to empty when explicit sha', async () => { - inputs.ref = '1111111111222222222233333333334444444444' - const settings: IGitSourceSettings = await inputHelper.getInputs() - expect(settings.ref).toBeFalsy() - expect(settings.commit).toBe('1111111111222222222233333333334444444444') - }) - - it('sets sha to empty when explicit ref', async () => { - inputs.ref = 'refs/heads/some-other-ref' - const settings: IGitSourceSettings = await inputHelper.getInputs() - expect(settings.ref).toBe('refs/heads/some-other-ref') - expect(settings.commit).toBeFalsy() - }) - - it('sets workflow organization ID', async () => { - const settings: IGitSourceSettings = await inputHelper.getInputs() - expect(settings.workflowOrganizationId).toBe(123456) - }) -}) diff --git a/__test__/modify-work-tree.sh b/__test__/modify-work-tree.sh deleted file mode 100755 index 89447eb..0000000 --- a/__test__/modify-work-tree.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [ ! -f "./basic/basic-file.txt" ]; then - echo "Expected basic file does not exist" - exit 1 -fi - -echo hello >> ./basic/basic-file.txt -echo hello >> ./basic/new-file.txt -git -C ./basic status \ No newline at end of file diff --git a/__test__/override-git-version.cmd b/__test__/override-git-version.cmd deleted file mode 100755 index 64c7f4d..0000000 --- a/__test__/override-git-version.cmd +++ /dev/null @@ -1,6 +0,0 @@ - -mkdir override-git-version -cd override-git-version -echo @echo override git version 1.2.3 > git.cmd -echo "%CD%" >> $GITHUB_PATH -cd .. diff --git a/__test__/override-git-version.sh b/__test__/override-git-version.sh deleted file mode 100755 index 7c3ca01..0000000 --- a/__test__/override-git-version.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -mkdir override-git-version -cd override-git-version -echo "#!/bin/sh" > git -echo "echo override git version 1.2.3" >> git -chmod +x git -echo "$(pwd)" >> $GITHUB_PATH -cd .. diff --git a/__test__/ref-helper.test.ts b/__test__/ref-helper.test.ts deleted file mode 100644 index 5c8d76b..0000000 --- a/__test__/ref-helper.test.ts +++ /dev/null @@ -1,190 +0,0 @@ -import * as assert from 'assert' -import * as refHelper from '../lib/ref-helper' -import {IGitCommandManager} from '../lib/git-command-manager' - -const commit = '1234567890123456789012345678901234567890' -let git: IGitCommandManager - -describe('ref-helper tests', () => { - beforeEach(() => { - git = {} as unknown as IGitCommandManager - }) - - it('getCheckoutInfo requires git', async () => { - const git = null as unknown as IGitCommandManager - try { - await refHelper.getCheckoutInfo(git, 'refs/heads/my/branch', commit) - throw new Error('Should not reach here') - } catch (err) { - expect((err as any)?.message).toBe('Arg git cannot be empty') - } - }) - - it('getCheckoutInfo requires ref or commit', async () => { - try { - await refHelper.getCheckoutInfo(git, '', '') - throw new Error('Should not reach here') - } catch (err) { - expect((err as any)?.message).toBe( - 'Args ref and commit cannot both be empty' - ) - } - }) - - it('getCheckoutInfo sha only', async () => { - const checkoutInfo = await refHelper.getCheckoutInfo(git, '', commit) - expect(checkoutInfo.ref).toBe(commit) - expect(checkoutInfo.startPoint).toBeFalsy() - }) - - it('getCheckoutInfo refs/heads/', async () => { - const checkoutInfo = await refHelper.getCheckoutInfo( - git, - 'refs/heads/my/branch', - commit - ) - expect(checkoutInfo.ref).toBe('my/branch') - expect(checkoutInfo.startPoint).toBe('refs/remotes/origin/my/branch') - }) - - it('getCheckoutInfo refs/pull/', async () => { - const checkoutInfo = await refHelper.getCheckoutInfo( - git, - 'refs/pull/123/merge', - commit - ) - expect(checkoutInfo.ref).toBe('refs/remotes/pull/123/merge') - expect(checkoutInfo.startPoint).toBeFalsy() - }) - - it('getCheckoutInfo refs/tags/', async () => { - const checkoutInfo = await refHelper.getCheckoutInfo( - git, - 'refs/tags/my-tag', - commit - ) - expect(checkoutInfo.ref).toBe('refs/tags/my-tag') - expect(checkoutInfo.startPoint).toBeFalsy() - }) - - it('getCheckoutInfo refs/', async () => { - const checkoutInfo = await refHelper.getCheckoutInfo( - git, - 'refs/gh/queue/main/pr-123', - commit - ) - expect(checkoutInfo.ref).toBe(commit) - expect(checkoutInfo.startPoint).toBeFalsy() - }) - - it('getCheckoutInfo refs/ without commit', async () => { - const checkoutInfo = await refHelper.getCheckoutInfo( - git, - 'refs/non-standard-ref', - '' - ) - expect(checkoutInfo.ref).toBe('refs/non-standard-ref') - expect(checkoutInfo.startPoint).toBeFalsy() - }) - - it('getCheckoutInfo unqualified branch only', async () => { - git.branchExists = jest.fn(async (remote: boolean, pattern: string) => { - return true - }) - - const checkoutInfo = await refHelper.getCheckoutInfo(git, 'my/branch', '') - - expect(checkoutInfo.ref).toBe('my/branch') - expect(checkoutInfo.startPoint).toBe('refs/remotes/origin/my/branch') - }) - - it('getCheckoutInfo unqualified tag only', async () => { - git.branchExists = jest.fn(async (remote: boolean, pattern: string) => { - return false - }) - git.tagExists = jest.fn(async (pattern: string) => { - return true - }) - - const checkoutInfo = await refHelper.getCheckoutInfo(git, 'my-tag', '') - - expect(checkoutInfo.ref).toBe('refs/tags/my-tag') - expect(checkoutInfo.startPoint).toBeFalsy() - }) - - it('getCheckoutInfo unqualified ref only, not a branch or tag', async () => { - git.branchExists = jest.fn(async (remote: boolean, pattern: string) => { - return false - }) - git.tagExists = jest.fn(async (pattern: string) => { - return false - }) - - try { - await refHelper.getCheckoutInfo(git, 'my-ref', '') - throw new Error('Should not reach here') - } catch (err) { - expect((err as any)?.message).toBe( - "A branch or tag with the name 'my-ref' could not be found" - ) - } - }) - - it('getRefSpec requires ref or commit', async () => { - assert.throws( - () => refHelper.getRefSpec('', ''), - /Args ref and commit cannot both be empty/ - ) - }) - - it('getRefSpec sha + refs/heads/', async () => { - const refSpec = refHelper.getRefSpec('refs/heads/my/branch', commit) - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe(`+${commit}:refs/remotes/origin/my/branch`) - }) - - it('getRefSpec sha + refs/pull/', async () => { - const refSpec = refHelper.getRefSpec('refs/pull/123/merge', commit) - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe(`+${commit}:refs/remotes/pull/123/merge`) - }) - - it('getRefSpec sha + refs/tags/', async () => { - const refSpec = refHelper.getRefSpec('refs/tags/my-tag', commit) - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe(`+${commit}:refs/tags/my-tag`) - }) - - it('getRefSpec sha only', async () => { - const refSpec = refHelper.getRefSpec('', commit) - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe(commit) - }) - - it('getRefSpec unqualified ref only', async () => { - const refSpec = refHelper.getRefSpec('my-ref', '') - expect(refSpec.length).toBe(2) - expect(refSpec[0]).toBe('+refs/heads/my-ref*:refs/remotes/origin/my-ref*') - expect(refSpec[1]).toBe('+refs/tags/my-ref*:refs/tags/my-ref*') - }) - - it('getRefSpec refs/heads/ only', async () => { - const refSpec = refHelper.getRefSpec('refs/heads/my/branch', '') - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe( - '+refs/heads/my/branch:refs/remotes/origin/my/branch' - ) - }) - - it('getRefSpec refs/pull/ only', async () => { - const refSpec = refHelper.getRefSpec('refs/pull/123/merge', '') - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe('+refs/pull/123/merge:refs/remotes/pull/123/merge') - }) - - it('getRefSpec refs/tags/ only', async () => { - const refSpec = refHelper.getRefSpec('refs/tags/my-tag', '') - expect(refSpec.length).toBe(1) - expect(refSpec[0]).toBe('+refs/tags/my-tag:refs/tags/my-tag') - }) -}) diff --git a/__test__/retry-helper.test.ts b/__test__/retry-helper.test.ts deleted file mode 100644 index a5d3f79..0000000 --- a/__test__/retry-helper.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import * as core from '@actions/core' -import {RetryHelper} from '../lib/retry-helper' - -let info: string[] -let retryHelper: any - -describe('retry-helper tests', () => { - beforeAll(() => { - // Mock @actions/core info() - jest.spyOn(core, 'info').mockImplementation((message: string) => { - info.push(message) - }) - - retryHelper = new RetryHelper(3, 0, 0) - }) - - beforeEach(() => { - // Reset info - info = [] - }) - - afterAll(() => { - // Restore - jest.restoreAllMocks() - }) - - it('first attempt succeeds', async () => { - const actual = await retryHelper.execute(async () => { - return 'some result' - }) - expect(actual).toBe('some result') - expect(info).toHaveLength(0) - }) - - it('second attempt succeeds', async () => { - let attempts = 0 - const actual = await retryHelper.execute(() => { - if (++attempts == 1) { - throw new Error('some error') - } - - return Promise.resolve('some result') - }) - expect(attempts).toBe(2) - expect(actual).toBe('some result') - expect(info).toHaveLength(2) - expect(info[0]).toBe('some error') - expect(info[1]).toMatch(/Waiting .+ seconds before trying again/) - }) - - it('third attempt succeeds', async () => { - let attempts = 0 - const actual = await retryHelper.execute(() => { - if (++attempts < 3) { - throw new Error(`some error ${attempts}`) - } - - return Promise.resolve('some result') - }) - expect(attempts).toBe(3) - expect(actual).toBe('some result') - expect(info).toHaveLength(4) - expect(info[0]).toBe('some error 1') - expect(info[1]).toMatch(/Waiting .+ seconds before trying again/) - expect(info[2]).toBe('some error 2') - expect(info[3]).toMatch(/Waiting .+ seconds before trying again/) - }) - - it('all attempts fail succeeds', async () => { - let attempts = 0 - let error: Error = null as unknown as Error - try { - await retryHelper.execute(() => { - throw new Error(`some error ${++attempts}`) - }) - } catch (err) { - error = err as Error - } - expect(error.message).toBe('some error 3') - expect(attempts).toBe(3) - expect(info).toHaveLength(4) - expect(info[0]).toBe('some error 1') - expect(info[1]).toMatch(/Waiting .+ seconds before trying again/) - expect(info[2]).toBe('some error 2') - expect(info[3]).toMatch(/Waiting .+ seconds before trying again/) - }) -}) diff --git a/__test__/url-helper.test.ts b/__test__/url-helper.test.ts deleted file mode 100644 index 57cb28f..0000000 --- a/__test__/url-helper.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -import * as urlHelper from '../src/url-helper' - -describe('getServerUrl tests', () => { - it('basics', async () => { - // Note that URL::toString will append a trailing / when passed just a domain name ... - expect(urlHelper.getServerUrl().toString()).toBe('https://github.com/') - expect(urlHelper.getServerUrl(' ').toString()).toBe('https://github.com/') - expect(urlHelper.getServerUrl(' ').toString()).toBe('https://github.com/') - expect(urlHelper.getServerUrl('http://contoso.com').toString()).toBe( - 'http://contoso.com/' - ) - expect(urlHelper.getServerUrl('https://contoso.com').toString()).toBe( - 'https://contoso.com/' - ) - expect(urlHelper.getServerUrl('https://contoso.com/').toString()).toBe( - 'https://contoso.com/' - ) - - // ... but can't make that same assumption when passed an URL that includes some deeper path. - expect(urlHelper.getServerUrl('https://contoso.com/a/b').toString()).toBe( - 'https://contoso.com/a/b' - ) - }) -}) - -describe('isGhes tests', () => { - const pristineEnv = process.env - - beforeEach(() => { - jest.resetModules() - process.env = {...pristineEnv} - }) - - afterAll(() => { - process.env = pristineEnv - }) - - it('basics', async () => { - delete process.env['GITHUB_SERVER_URL'] - expect(urlHelper.isGhes()).toBeFalsy() - expect(urlHelper.isGhes('https://github.com')).toBeFalsy() - expect(urlHelper.isGhes('https://contoso.ghe.com')).toBeFalsy() - expect(urlHelper.isGhes('https://test.github.localhost')).toBeFalsy() - expect(urlHelper.isGhes('https://src.onpremise.fabrikam.com')).toBeTruthy() - }) - - it('returns false when the GITHUB_SERVER_URL environment variable is not defined', async () => { - delete process.env['GITHUB_SERVER_URL'] - expect(urlHelper.isGhes()).toBeFalsy() - }) - - it('returns false when the GITHUB_SERVER_URL environment variable is set to github.com', async () => { - process.env['GITHUB_SERVER_URL'] = 'https://github.com' - expect(urlHelper.isGhes()).toBeFalsy() - }) - - it('returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL', async () => { - process.env['GITHUB_SERVER_URL'] = 'https://contoso.ghe.com' - expect(urlHelper.isGhes()).toBeFalsy() - }) - - it('returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix', async () => { - process.env['GITHUB_SERVER_URL'] = 'https://mock-github.localhost' - expect(urlHelper.isGhes()).toBeFalsy() - }) - - it('returns true when the GITHUB_SERVER_URL environment variable is set to some other URL', async () => { - process.env['GITHUB_SERVER_URL'] = 'https://src.onpremise.fabrikam.com' - expect(urlHelper.isGhes()).toBeTruthy() - }) -}) - -describe('getServerApiUrl tests', () => { - it('basics', async () => { - expect(urlHelper.getServerApiUrl()).toBe('https://api.github.com') - expect(urlHelper.getServerApiUrl('https://github.com')).toBe( - 'https://api.github.com' - ) - expect(urlHelper.getServerApiUrl('https://GitHub.com')).toBe( - 'https://api.github.com' - ) - expect(urlHelper.getServerApiUrl('https://contoso.ghe.com')).toBe( - 'https://api.contoso.ghe.com' - ) - expect(urlHelper.getServerApiUrl('https://fabrikam.GHE.COM')).toBe( - 'https://api.fabrikam.ghe.com' - ) - expect( - urlHelper.getServerApiUrl('https://src.onpremise.fabrikam.com') - ).toBe('https://src.onpremise.fabrikam.com/api/v3') - }) -}) diff --git a/__test__/verify-basic.sh b/__test__/verify-basic.sh deleted file mode 100755 index d084617..0000000 --- a/__test__/verify-basic.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -if [ ! -f "./basic/basic-file.txt" ]; then - echo "Expected basic file does not exist" - exit 1 -fi - -if [ "$1" = "--archive" ]; then - # Verify no .git folder - if [ -d "./basic/.git" ]; then - echo "Did not expect ./basic/.git folder to exist" - exit 1 - fi -else - # Verify .git folder - if [ ! -d "./basic/.git" ]; then - echo "Expected ./basic/.git folder to exist" - exit 1 - fi - - # Verify that sparse-checkout is disabled. - SPARSE_CHECKOUT_ENABLED=$(git -C ./basic config --local --get-all core.sparseCheckout) - if [ "$SPARSE_CHECKOUT_ENABLED" != "" ]; then - echo "Expected sparse-checkout to be disabled (discovered: $SPARSE_CHECKOUT_ENABLED)" - exit 1 - fi - - # Verify git configuration shows worktreeConfig is effectively disabled - WORKTREE_CONFIG_ENABLED=$(git -C ./basic config --local --get-all extensions.worktreeConfig) - if [[ "$WORKTREE_CONFIG_ENABLED" != "" ]]; then - echo "Expected extensions.worktreeConfig (boolean) to be disabled in git config. This could be an artifact of sparse checkout functionality." - exit 1 - fi - - # Verify auth token - cd basic - git fetch --no-tags --depth=1 origin +refs/heads/main:refs/remotes/origin/main -fi diff --git a/__test__/verify-clean.sh b/__test__/verify-clean.sh deleted file mode 100755 index 86bf9d6..0000000 --- a/__test__/verify-clean.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -if [[ "$(git -C ./basic status --porcelain)" != "" ]]; then - echo ---------------------------------------- - echo git status - echo ---------------------------------------- - git status - echo ---------------------------------------- - echo git diff - echo ---------------------------------------- - git diff - exit 1 -fi diff --git a/__test__/verify-fetch-filter.sh b/__test__/verify-fetch-filter.sh deleted file mode 100755 index 4fc9d9e..0000000 --- a/__test__/verify-fetch-filter.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Verify .git folder -if [ ! -d "./fetch-filter/.git" ]; then - echo "Expected ./fetch-filter/.git folder to exist" - exit 1 -fi - -# Verify .git/config contains partialclonefilter - -CLONE_FILTER=$(git -C fetch-filter config --local --get remote.origin.partialclonefilter) - -if [ "$CLONE_FILTER" != "blob:none" ]; then - echo "Expected ./fetch-filter/.git/config to have 'remote.origin.partialclonefilter' set to 'blob:none'" - exit 1 -fi diff --git a/__test__/verify-lfs.sh b/__test__/verify-lfs.sh deleted file mode 100755 index b0463f1..0000000 --- a/__test__/verify-lfs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -if [ ! -f "./lfs/regular-file.txt" ]; then - echo "Expected regular file does not exist" - exit 1 -fi - -if [ ! -f "./lfs/lfs-file.bin" ]; then - echo "Expected lfs file does not exist" - exit 1 -fi diff --git a/__test__/verify-no-unstaged-changes.sh b/__test__/verify-no-unstaged-changes.sh deleted file mode 100755 index 9b30471..0000000 --- a/__test__/verify-no-unstaged-changes.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -if [[ "$(git status --porcelain)" != "" ]]; then - echo ---------------------------------------- - echo git status - echo ---------------------------------------- - git status - echo ---------------------------------------- - echo git diff - echo ---------------------------------------- - git diff - echo ---------------------------------------- - echo Troubleshooting - echo ---------------------------------------- - echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run format && npm run build" - exit 1 -fi diff --git a/__test__/verify-side-by-side.sh b/__test__/verify-side-by-side.sh deleted file mode 100755 index 35de29a..0000000 --- a/__test__/verify-side-by-side.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -if [ ! -f "./side-by-side-1/side-by-side-test-file-1.txt" ]; then - echo "Expected file 1 does not exist" - exit 1 -fi - -if [ ! -f "./side-by-side-2/side-by-side-test-file-2.txt" ]; then - echo "Expected file 2 does not exist" - exit 1 -fi diff --git a/__test__/verify-sparse-checkout-non-cone-mode.sh b/__test__/verify-sparse-checkout-non-cone-mode.sh deleted file mode 100755 index dae28ed..0000000 --- a/__test__/verify-sparse-checkout-non-cone-mode.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -# Verify .git folder -if [ ! -d "./sparse-checkout-non-cone-mode/.git" ]; then - echo "Expected ./sparse-checkout-non-cone-mode/.git folder to exist" - exit 1 -fi - -# Verify sparse-checkout (non-cone-mode) -cd sparse-checkout-non-cone-mode - -ENABLED=$(git config --local --get-all core.sparseCheckout) - -if [ "$?" != "0" ]; then - echo "Failed to verify that sparse-checkout is enabled" - exit 1 -fi - -# Check that sparse-checkout is enabled -if [ "$ENABLED" != "true" ]; then - echo "Expected sparse-checkout to be enabled (is: $ENABLED)" - exit 1 -fi - -SPARSE_CHECKOUT_FILE=$(git rev-parse --git-path info/sparse-checkout) - -if [ "$?" != "0" ]; then - echo "Failed to validate sparse-checkout" - exit 1 -fi - -# Check that sparse-checkout list is not empty -if [ ! -f "$SPARSE_CHECKOUT_FILE" ]; then - echo "Expected sparse-checkout file to exist" - exit 1 -fi - -# Check that all folders from sparse-checkout exists -for pattern in $(cat "$SPARSE_CHECKOUT_FILE") -do - if [ ! -d "${pattern#/}" ]; then - echo "Expected directory '${pattern#/}' to exist" - exit 1 - fi -done - -# Verify that the root directory is not checked out -if [ -f README.md ]; then - echo "Expected top-level files not to exist" - exit 1 -fi \ No newline at end of file diff --git a/__test__/verify-sparse-checkout.sh b/__test__/verify-sparse-checkout.sh deleted file mode 100755 index a9f7748..0000000 --- a/__test__/verify-sparse-checkout.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash - -# Verify .git folder -if [ ! -d "./sparse-checkout/.git" ]; then - echo "Expected ./sparse-checkout/.git folder to exist" - exit 1 -fi - -# Verify sparse-checkout -cd sparse-checkout - -SPARSE=$(git sparse-checkout list) - -if [ "$?" != "0" ]; then - echo "Failed to validate sparse-checkout" - exit 1 -fi - -# Check that sparse-checkout list is not empty -if [ -z "$SPARSE" ]; then - echo "Expected sparse-checkout list to not be empty" - exit 1 -fi - -# Check that all folders of the sparse checkout exist -for pattern in $SPARSE -do - if [ ! -d "$pattern" ]; then - echo "Expected directory '$pattern' to exist" - exit 1 - fi -done - -checkSparse () { - if [ ! -d "./$1" ]; then - echo "Expected directory '$1' to exist" - exit 1 - fi - - for file in $(git ls-tree -r --name-only HEAD $1) - do - if [ ! -f "$file" ]; then - echo "Expected file '$file' to exist" - exit 1 - fi - done -} - -# Check that all folders and their children have been checked out -checkSparse __test__ -checkSparse .github -checkSparse dist - -# Check that only sparse-checkout folders have been checked out -for pattern in $(git ls-tree --name-only HEAD) -do - if [ -d "$pattern" ]; then - if [[ "$pattern" != "__test__" && "$pattern" != ".github" && "$pattern" != "dist" ]]; then - echo "Expected directory '$pattern' to not exist" - exit 1 - fi - fi -done \ No newline at end of file diff --git a/__test__/verify-submodules-false.sh b/__test__/verify-submodules-false.sh deleted file mode 100755 index 733e247..0000000 --- a/__test__/verify-submodules-false.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -if [ ! -f "./submodules-false/regular-file.txt" ]; then - echo "Expected regular file does not exist" - exit 1 -fi - -if [ -f "./submodules-false/submodule-level-1/submodule-file.txt" ]; then - echo "Unexpected submodule file exists" - exit 1 -fi \ No newline at end of file diff --git a/__test__/verify-submodules-recursive.sh b/__test__/verify-submodules-recursive.sh deleted file mode 100755 index 1b68f9b..0000000 --- a/__test__/verify-submodules-recursive.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -if [ ! -f "./submodules-recursive/regular-file.txt" ]; then - echo "Expected regular file does not exist" - exit 1 -fi - -if [ ! -f "./submodules-recursive/submodule-level-1/submodule-file.txt" ]; then - echo "Expected submodule file does not exist" - exit 1 -fi - -if [ ! -f "./submodules-recursive/submodule-level-1/submodule-level-2/nested-submodule-file.txt" ]; then - echo "Expected nested submodule file does not exists" - exit 1 -fi - -echo "Testing persisted credential" -pushd ./submodules-recursive/submodule-level-1/submodule-level-2 -git config --local --name-only --get-regexp http.+extraheader && git fetch -if [ "$?" != "0" ]; then - echo "Failed to validate persisted credential" - popd - exit 1 -fi -popd diff --git a/__test__/verify-submodules-true.sh b/__test__/verify-submodules-true.sh deleted file mode 100755 index 43769fe..0000000 --- a/__test__/verify-submodules-true.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -if [ ! -f "./submodules-true/regular-file.txt" ]; then - echo "Expected regular file does not exist" - exit 1 -fi - -if [ ! -f "./submodules-true/submodule-level-1/submodule-file.txt" ]; then - echo "Expected submodule file does not exist" - exit 1 -fi - -if [ -f "./submodules-true/submodule-level-1/submodule-level-2/nested-submodule-file.txt" ]; then - echo "Unexpected nested submodule file exists" - exit 1 -fi - -echo "Testing persisted credential" -pushd ./submodules-true/submodule-level-1 -git config --local --name-only --get-regexp http.+extraheader && git fetch -if [ "$?" != "0" ]; then - echo "Failed to validate persisted credential" - popd - exit 1 -fi -popd diff --git a/images/test-ubuntu-git.Dockerfile b/images/test-ubuntu-git.Dockerfile deleted file mode 100644 index 8b464c3..0000000 --- a/images/test-ubuntu-git.Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# Defines the test-ubuntu-git Container Image. -# Consumed by actions/checkout CI/CD validation workflows. - -FROM ubuntu:latest - -RUN apt update -RUN apt install -y git - -LABEL org.opencontainers.image.title="Ubuntu + git (validation image)" -LABEL org.opencontainers.image.description="Ubuntu image with git pre-installed. Intended primarily for testing `actions/checkout` during CI/CD workflows." -LABEL org.opencontainers.image.documentation="https://github.com/actions/checkout/tree/main/images/test-ubuntu-git.md" -LABEL org.opencontainers.image.licenses=MIT diff --git a/images/test-ubuntu-git.md b/images/test-ubuntu-git.md deleted file mode 100644 index adf4bf6..0000000 --- a/images/test-ubuntu-git.md +++ /dev/null @@ -1,15 +0,0 @@ -# `test-ubuntu-git` Container Image - -[![Publish test-ubuntu-git Container](https://github.com/actions/checkout/actions/workflows/update-test-ubuntu-git.yml/badge.svg)](https://github.com/actions/checkout/actions/workflows/update-test-ubuntu-git.yml) - -## Purpose - -`test-ubuntu-git` is a container image hosted on the GitHub Container Registry, `ghcr.io`. - -It is intended primarily for testing the [`actions/checkout` repository](https://github.com/actions/checkout) as part of `actions/checkout`'s CI/CD workflows. - -The composition of `test-ubuntu-git` is intentionally minimal. It is comprised of [git](https://git-scm.com/) installed on top of a [base-level ubuntu image](https://hub.docker.com/_/ubuntu/tags). - -# License - -`test-ubuntu-git` is released under the [MIT License](/LICENSE).