Dogfood Perforce server
Perforce is a version control system like Git, subversion, or mercurial. While git is based on a distributed, decentralised model, Perforce is centralised. For testing purposes, you may use our Perforce dogfood server.
Setting up
-
To connect to the Perforce server, you’ll need the Perforce cli installed locally. Use the command:
brew install --cask perforce
-
The following environment variables configure your shell to point at the Perforce server. Set them to your
env
with theexport
command, or add them to your.bashrc
or.zshrc
file.
# .zshrc or .bashrc
export P4PORT=perforce.sgdev.org:1666 # This points the p4 cli at the dogfood server
export P4USER=admin # sets your user
export P4PASSWD=<session ticket> # optional, see details below, doesn't require string quotes
export P4EDITOR=/usr/bin/vim # specifies the editor opened by some p4 commands
Perforce dogfood is a service on our Sourcegraph dogfood cluster, for more info see its GCP service details.
Interacting with Perforce dogfood
To add repos to the Perforce dogfood server follow the following procedure:
Generate a session ticket
Interaction with the dogfood server requires authentication. Once you’ve set up your shell environment you’ll need to generate a session ticket with your users password. You can find the admin password, and others on our shared 1Password account.
- Once your environment is set run
p4 ping
this will prompt you for the admin password, and is a good way to test your connection to the server. - With your connection confirmed generate a session ticket with the following command:
p4 -u <p4.user> login -p -a
you’ll be prompted for your user password, once you’ve entered it a session ticket will be printed to STDOUT. You may also runp4 -u <p4.user> login -a
to set the ticket in~/.p4tickets
, this allows you to skip settingP4PASSWD
in your env, and will only work if you have noP4PASSWD
variable in your env. - Set the ticket generated in step 2 to your
P4PASSWD
env variable - p4 commands should no longer require a password. Note this ticket expires every 12 hours unless configured to do otherwise.
Create new depot
Perforce uses depots rather than repos, the concept is functionally equivalent. To see all the repos on the perforce server run p4 depots
, to create a new depot on the server run p4 depot <depot name>
, this will open a file like seen below:
Depot: support-tools
Owner: admin
Date: 2021/08/08 06:09:52
Description:
testing testing testing
Type: local
Address: local
Suffix: .p4s
StreamDepth: //support-tools/1
Map: support-tools/...
Once a depot is created on the server, we can start to add files from our local client to it.
While this new depot has been created, you still need to add it to “client/workspace” and have perforce track it.
The easiest way to do this is in the p4v
UI. Go to Connection > Edit Current Workspace > Right-click on the depot you just created > Include Tree.
You may see a warning about no files. Create a basic text file then run:
p4 add init-file.txt
then run p4 submit -d "initial commit"
.
Create a client (workspace)
Perforce is different than git in that it utilizes a concept called clients (or more recently, workspaces). This is a subset of files on your machine that mirrors files on the Perforce server. The p4 client <name>
command will open a client spec file with an editor specified by the P4EDITOR
env variable. Below is an example:
Client: warren
Update: 2021/08/08 04:17:02
Access: 2021/08/08 04:07:51
Owner: admin
Host: Warrens-MacBook-Pro.local
Description:
Created by admin.
Root: /Users/warrengifford
Options: noallwrite noclobber nocompress unlocked nomodtime normdir
SubmitOptions: submitunchanged
LineEnd: local
View:
//test-large-depot/... //warren/test-large-depot/...
//test-perms/... //warren/test-perms/...
//spec/... //warren/spec/...
//depot/... //warren/depot/...
//Tone.js/... //warren/Tone.js/...
//LifeBox/... //warren/LifeBox/...
You’ll notice under View:
a “Perforce path” or depot path on the left, followed by a client path on the right. The depot path reflects the path to the depot on the Perforce server, while the client path is the path to the directory on your local machine that you want to map to the Perforce depot.
Specifying views in your client configuration allows you to declare which files from the Perforce depot are relevant to you, or which files you want to be part of your workspace. You can learn more about this topic here.
Once you’ve created a depot on dogfood, map a local directory to it by adding an entry to your client spec under Views:
//<depot name>/... //<client name>/<root directory>/...
Note that the client name is mapped to your Root:
setting in the client spec.
Add files and submit
Once you’ve created a depot on the server, and created a client spec, adding files is a lot like git. To add the files run p4 add <relative path to files>/...
for example while in /Users/warrengifford
I could run p4 add ./LifeBox/...
. This will open a change spec for which you must provide a description:
Change: new
Client: warren
User: admin
Status: new
Description:
<enter description here>
Files:
//support-tools/.git/COMMIT_EDITMSG # add
//support-tools/.git/FETCH_HEAD # add
//support-tools/.git/HEAD # add
//support-tools/.git/ORIG_HEAD # add
//support-tools/.git/config # add
//support-tools/.git/description # add
# etc etc
You can see the files staged for adding with p4 opened
.
Finally run p4 submit
to load the files to the depo on the server.
To edit files
You must run p4 edit ${filename}
before modifying files otherwise they are locked by default and set to read-only.
Configuring Sourcegraph to sync dogfood depots
Our documentation covers the requirements to sync to Sourcegraph, however for convienience it should be noted we have a user called buildkite
on our dogfood instance whose session ticket will not expire. To generate the ticket for this account reference our shared 1Password.
To learn more about general p4 commands checkout this resource: https://www.perforce.com/perforce/doc.973/cmdguide/html/quicksta.htm
Helpful p4 flags
You can use -c
in commands like p4 add
to specify the client.
Local Perforce server
Joe has also developed an awesome Perforce server image that allows for local deployment of a Perforce server.
The following procedure runs the image:
-
Start the server
docker run --publish 1666:1666 sourcegraph/helix-p4d:2020.2
-
Open a new terminal, configure the terminal session env:
export P4PORT=:1666
export P4USER=admin
- Ping the server from a separate terminal with p4 ping and enter the password below:
pass12349ers
(Note the value listed is from the dockerfile arg declaration)
GUI tools
You can download the Helix Admin Tool which makes it easier to configure users, permissions, etc.
Testing sub-repo permissions
Sub-repo permissions are still experimental and below are the steps required to start testing them locally against our dogfood perforce server.
Add this configuration to your external service configuration in dev private
"PERFORCE":
[
{
"p4.port": "perforce.sgdev.org:1666",
"p4.user": "admin",
"p4.passwd": "REDACTED",
"depots": ["//test-perms/"],
"repositoryPathPattern": "perforce/{depot}",
"authorization": { "subRepoPermissions": true },
},
]
You can get the P4.passwd
token above from running p4 -u admin login -p -a
using the admin password from 1password. It expires every day so you’ll need to regenerate it occasionally.
Updated your local SG user to include the verified e-mail address of one of the users configured on the dogfood instance, for example alice@perforce.sgdev.org
. Alice is a user in the our dogfood instance with permissions set against the //test-perms
instance.
NOTE: Don’t modify the permissions in Perforce since they are used for integration testing.
You’ll also need Perforce and sub-repo permissions enabled in your site config under the experimentalFeatures
section:
"experimentalFeatures": {
"perforce": "enabled",
"subRepoPermissions": { "enabled": true }
}
In order to not have to wait for a permissions sync to complete, you can force one with this mutation:
mutation {
scheduleUserPermissionsSync(user: "YOUR_ID") {
alwaysNil
}
}
Your can find your user id with this query:
query {
currentUser {
id
}
}
Once the permissions sync has completed you should see something like this in your local database:
sourcegraph=# select repo_id, user_id, path_includes, path_excludes from sub_repo_permissions;
repo_id | user_id | path_includes | path_excludes
---------+---------+-------------------+----------------------------
238 | 1 | {**} | {Security/**}