67
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Proプランでも使えるようになった「GitHub Copilot coding agent」を試してみた

Last updated at Posted at 2025-06-30

はじめに

X のタイムラインに、以下の「GitHub Copilot coding agent が Proプランでも使えるようになった」という情報が流れてきたので、さっそく試してみました。 

今回試した内容のレベル感は、
 「動作確認くらいの内容で、一通りの手順を体験してみた」
というものになります。

ちなみに Pro+プランなどだと、以下の 5月のタイミングから利用可能になっていたものです。

それと、Proプランで GitHub Copilot coding agent を使えるようになったタイミングは、自分が冒頭のポストを見たタイミングよりもさらに前からだったようです。

やってみたこと

作ってもらったもの

最初に、GitHub Copilot coding agent に作ってもらったものを掲載してみます。

内容は p5.js を使った Canvas への描画(ブラウザで動作するもの)です。

上記が作られた流れ

これが作れられた流れの概要は、以下になります。

  1. Isuue に簡単な仕様を数行で書く
  2. Copilot が上記の内容を元にコーディング
  3. Copilot からプルリクがくる
  4. プルリクに対する対応 ← 自分が受け入れやマージなどをする
  5. (意図しない実装になっていたので、修正依頼用の Issue を作成し、上記の流れをもう1周)

この後の部分では、「GitHub上の設定の確認」や「GitHub Copilot coding agent を試した手順の詳細」などを書いていきます。

GitHub上の設定の確認

まずは、GitHub上の「GitHub Copilot coding agent」に関する設定を確認してみました。それに関して、以下の公式ページに書かれた情報を見て、設定画面へとたどり着きました。

●Managing Copilot policies as an individual subscriber - GitHub Enterprise Cloud Docs
 https://docs.github.com/ja/enterprise-cloud@latest/copilot/how-tos/manage-your-account/managing-copilot-policies-as-an-individual-subscriber

image.png

設定画面を開く手順

GitHub Copilot coding agent の設定画面を開いた時の手順を記載します。

まずは、右上のアイコンから開けるメニューで「Your Copilot」を選びます。

image.png

そして、左側のメニューを見ると「Copilot」の部分に「Coding agent」という項目があるので、これを選びます。

image.png

そうすると、以下の GitHub Copilot coding agent の設定画面を開くことができました。

image.png

上記の赤矢印で示した部分で、対象にするリポジトリを設定できるようです。それと、このページを開いた時の URL は以下になるようでした。

●Coding agent
 https://github.com/settings/copilot/coding_agent

設定を変えなくても良かったのですが、試しに今回用のリポジトリを作って、そのリポジトリのみを対象にする、という状態でやってみました。

リポジトリでの操作など

リポジトリでの操作を行っていきます。

参照した記事について

Qiita で GitHub Copilot coding agent を検索していたら、こちらの @chomado さんの記事が出てきたので、参照させていただきました。

●GitHub で自律的に動く Copilot Coding Agent を使い issue 対応(実装からPR作成まで)を丸投げしよう #意識低いAICodingチュートリアル #03 #生成AI - Qiita
https://qiita.com/chomado/items/92650af47b55632f7ef9#github-copilot-coding-agent-%E3%81%A8%E3%81%AF

Issue を作ってみる

GitHub Copilot coding agent を使うには、Issue を作成して、そこに Copilot をアサインするというやり方のようです。

Issue を作成して内容を作っていく前の段階で、画面右の方を操作してみると Copilot をアサインできるようになっています。

image.png

Copilot をアサインしてから、以下の内容を書きこみました(以下の内容は思いつきで適当に作りました)。

  • タイトル
    • p5.js でパーティクルを描画する HTMLファイルを作成する
  • 説明
    • p5.js でパーティクルを描画する HTMLファイルを、以下の仕様で作る

image.png

その後、作成を完了させたところ、以下のようなコメントがつきました。

image.png

今回作ったテスト用のリポジトリが、README.md さえ作られていない空の内容だったので、「1回は何かをコミットするように」というコメントがきた形です。

Issue を再度作る

README.md を適当に作って、再度、先ほどと同じ Issue を作りました。

image.png

今度は、Copilot からのリアクションがついて、作成作業が開始されたようなメッセージが出ています。

以下のような計画が作られたりしつつ、作業が進んでいったようでした。

image.png

Copilot からのプルリクとその対応

この作業をしつつ、キャプチャ画像を X にポストしたりしていたのですが、そんなことをしている間に既にプルリクがきていました。

image.png

内容を確認してみると、270行くらいの HTMLファイルが作られていました。

image.png

ざっと見て処理的上の問題はなさそうだったので(なぜか p5.js が使われていない感じの実装でしたが...)、内容の受け入れやブランチからのマージの操作を行いました。

マージ後のリポジトリの状態は以下のとおりで、htmlファイルが main に追加されています。

image.png

いったん動作を確認してみる

上で書いたように p5.js がきちんと使われていない実装になっていたものの、処理は問題ないものだったので、この HTMLファイルをブラウザで開いて動作を確認してみました。

そうすると、以下のような動作をするものができあがっていました。

作成されたコードをあらためて確認してみる

「GitHub Copilot coding agent」で作成された HTMLファイルの内容をあらためて見てみました。p5.js がきちんと使われていない、というのが以下などからも分かります。
※ 素の Canvas API を使った処理で実装されています

コードの一部抜粋(省略した部分あり)
        function init() {
            canvas = document.createElement('canvas');
            canvas.width = 800;
            canvas.height = 600;
            ctx = canvas.getContext('2d');
            
            document.getElementById('canvas-container').appendChild(canvas);
            
            // Launch initial fireworks
            for (let i = 0; i < 3; i++) {
                setTimeout(() => {
                    fireworks.push(new Firework(random(100, canvas.width - 100), canvas.height));
                }, i * 1000);
            }
            
            // Event listeners
            canvas.addEventListener('click', function(e) {
                const rect = canvas.getBoundingClientRect();
                const x = e.clientX - rect.left;
                fireworks.push(new Firework(x, canvas.height));
            });
            
            ...
            
            animate();
        }
        
        function animate() {
            // Clear canvas with fade effect
            ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            ...
            

問題の原因

この問題が発生した原因は、以下になるようでした。

image.png

「実装したものをテストした際に、テスト環境依存の問題が発生した(ファイヤーウォールによって CDN へのアクセスがブロックされた)」というようなことが書いてあります。

再度、Issue での修正依頼を出してみることにしました。

修正依頼

以下の内容の Issue で、修正依頼を出してみました。

image.png

Issue の内容を受けて、以下のように作業が進んでいきます。

image.png

そして作業が完了した状態になり、以下のような出力が最後の部分で出ていたりしました。

image.png

修正後のコード

修正されたコードは、以下の通りです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Particle Fireworks</title>
    <script src="https://unpkg.com/p5@1.11.8/lib/p5.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #000;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            font-family: Arial, sans-serif;
        }
        
        #canvas-container {
            border: 2px solid #333;
            border-radius: 10px;
        }
        
        .instructions {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            font-size: 14px;
            z-index: 1000;
        }
    </style>
</head>
<body>
    <div class="instructions">
        クリックして花火を打ち上げよう!
    </div>
    <div id="canvas-container"></div>
    
    <script>
        // Variables
        let fireworks = [];
        let particles = [];
        
        // Utility function for HSL to RGB conversion
        function hslToRgb(h, s, l) {
            h /= 360;
            s /= 100;
            l /= 100;
            const c = (1 - Math.abs(2 * l - 1)) * s;
            const x = c * (1 - Math.abs((h * 6) % 2 - 1));
            const m = l - c / 2;
            let r, g, b;
            
            if (0 <= h && h < 1/6) {
                [r, g, b] = [c, x, 0];
            } else if (1/6 <= h && h < 2/6) {
                [r, g, b] = [x, c, 0];
            } else if (2/6 <= h && h < 3/6) {
                [r, g, b] = [0, c, x];
            } else if (3/6 <= h && h < 4/6) {
                [r, g, b] = [0, x, c];
            } else if (4/6 <= h && h < 5/6) {
                [r, g, b] = [x, 0, c];
            } else {
                [r, g, b] = [c, 0, x];
            }
            
            return [
                Math.round((r + m) * 255),
                Math.round((g + m) * 255),
                Math.round((b + m) * 255)
            ];
        }
        
        // p5.js setup function
        function setup() {
            let canvas = createCanvas(800, 600);
            canvas.parent('canvas-container');
            
            // Launch initial fireworks
            for (let i = 0; i < 3; i++) {
                setTimeout(() => {
                    fireworks.push(new Firework(random(100, width - 100), height));
                }, i * 1000);
            }
        }
        
        // p5.js draw function (animation loop)
        function draw() {
            // Clear canvas with fade effect
            fill(0, 25);
            noStroke();
            rect(0, 0, width, height);
            
            // Update and display fireworks
            for (let i = fireworks.length - 1; i >= 0; i--) {
                fireworks[i].update();
                fireworks[i].show();
                
                if (fireworks[i].exploded) {
                    fireworks.splice(i, 1);
                }
            }
            
            // Update and display particles
            for (let i = particles.length - 1; i >= 0; i--) {
                particles[i].update();
                particles[i].show();
                
                if (particles[i].isDead()) {
                    particles.splice(i, 1);
                }
            }
            
            // Random fireworks
            if (Math.random() < 0.005) {
                fireworks.push(new Firework(random(100, width - 100), height));
            }
        }
        
        // p5.js mouse event
        function mousePressed() {
            fireworks.push(new Firework(mouseX, height));
        }
        
        // p5.js keyboard event
        function keyPressed() {
            if (key === ' ') {
                for (let i = 0; i < 3; i++) {
                    setTimeout(() => {
                        fireworks.push(new Firework(random(100, width - 100), height));
                    }, i * 200);
                }
            }
        }
        
        class Firework {
            constructor(x, y) {
                this.x = x;
                this.y = y;
                this.vx = random(-2, 2);
                this.vy = random(-15, -10);
                this.gravity = 0.2;
                this.exploded = false;
                this.hue = random(360);
                this.trail = [];
            }
            
            update() {
                if (!this.exploded) {
                    this.trail.push({x: this.x, y: this.y});
                    if (this.trail.length > 10) {
                        this.trail.shift();
                    }
                    
                    this.vy += this.gravity;
                    this.x += this.vx;
                    this.y += this.vy;
                    
                    if (this.vy >= 0) {
                        this.explode();
                    }
                }
            }
            
            explode() {
                this.exploded = true;
                let particleCount = random(20, 40);
                
                for (let i = 0; i < particleCount; i++) {
                    let angle = random(TWO_PI);
                    let speed = random(1, 8);
                    let particle = new Particle(
                        this.x, 
                        this.y, 
                        cos(angle) * speed,
                        sin(angle) * speed,
                        this.hue + random(-30, 30)
                    );
                    particles.push(particle);
                }
            }
            
            show() {
                if (!this.exploded) {
                    // Draw trail
                    for (let i = 0; i < this.trail.length; i++) {
                        let alpha = map(i, 0, this.trail.length - 1, 0, 255);
                        let [r, g, b] = hslToRgb(this.hue, 80, 50);
                        fill(r, g, b, alpha);
                        noStroke();
                        circle(this.trail[i].x, this.trail[i].y, 6);
                    }
                    
                    // Draw main firework
                    let [r, g, b] = hslToRgb(this.hue, 80, 60);
                    fill(r, g, b);
                    stroke(r, g, b);
                    strokeWeight(2);
                    circle(this.x, this.y, 12);
                }
            }
        }
        
        class Particle {
            constructor(x, y, vx, vy, hue) {
                this.x = x;
                this.y = y;
                this.vx = vx;
                this.vy = vy;
                this.gravity = 0.1;
                this.life = 255;
                this.decay = random(2, 5);
                this.hue = hue % 360;
                this.size = random(2, 5);
            }
            
            update() {
                this.vy += this.gravity;
                this.x += this.vx;
                this.y += this.vy;
                this.life -= this.decay;
                this.vx *= 0.98;
                this.vy *= 0.98;
            }
            
            show() {
                let alpha = this.life;
                let [r, g, b] = hslToRgb(this.hue, 80, 60);
                fill(r, g, b, alpha);
                noStroke();
                circle(this.x, this.y, this.size * 2);
            }
            
            isDead() {
                return this.life <= 0;
            }
        }
    </script>
</body>
</html>

今度は、一部で(冒頭部分で)p5.js が使われてない処理があったりするものの、全体的には p5.js の処理になっていました。

作業過程を見てみる

1回目の Copilot の作業では、テストでの問題が発生して p5.js を使うのをあきらめた(Vanilla JS での実装に切り替えた)、というような話が出ていましたが、今回はどうなっていたのかを少し見てみました。

今回も CDN絡みでアクセスをブロックされた、というような感じの内容が途中に出ています。

image.png

その後、今回は修正や実装に関する構文チェックを行って、それで内容確認OK として進めたようでした。

image.png

image.png

おわりに

とりあえず今回、「GitHub Copilot coding agent」を使う流れを少し体験することができました。

別途、GitHub Copilot coding agent をさらに試してみたり、また競合となるサービスも使ってみて、使い比べてみたりということができたらと思います。

67
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?